refactor: DevTools → ethend 重命名 + 加入生产环境
- 目录 devtools/ → ethend/ - CLI 脚本 devtools.sh/.bat → ethend.sh/.bat - 环境变量 DEVTOOLS_PORT → ETHEND_PORT - docker-compose.yml 新增 ethend 服务(生产部署) - 同步更新全部文档、注释和配置文件 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -45,6 +45,9 @@ ENABLE_BACKGROUND_THINKING=true
|
|||||||
# ========== Webhook(可选) ==========
|
# ========== Webhook(可选) ==========
|
||||||
WEBHOOK_API_KEY=
|
WEBHOOK_API_KEY=
|
||||||
|
|
||||||
|
# ========== 管理控制台端口 ==========
|
||||||
|
ETHEND_PORT=9090
|
||||||
|
|
||||||
# ========== 反向代理端口(避免与已有 nginx 等服务冲突) ==========
|
# ========== 反向代理端口(避免与已有 nginx 等服务冲突) ==========
|
||||||
CADDY_HTTP_PORT=80
|
CADDY_HTTP_PORT=80
|
||||||
CADDY_HTTPS_PORT=443
|
CADDY_HTTPS_PORT=443
|
||||||
|
|||||||
+4
-4
@@ -59,10 +59,10 @@ docs/*
|
|||||||
debug/cache/
|
debug/cache/
|
||||||
debug/logs/
|
debug/logs/
|
||||||
|
|
||||||
# ========== DevTools 运行时 ==========
|
# ========== ethend 运行时 ==========
|
||||||
devtools/node_modules/
|
ethend/node_modules/
|
||||||
devtools/logs/
|
ethend/logs/
|
||||||
devtools/package-lock.json
|
ethend/package-lock.json
|
||||||
|
|
||||||
# ========== 语音服务外部依赖 (C++ 编译产物 / 模型文件) ==========
|
# ========== 语音服务外部依赖 (C++ 编译产物 / 模型文件) ==========
|
||||||
backend/voice-service/whisper.cpp/
|
backend/voice-service/whisper.cpp/
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Cyrene 部署指南
|
# Cyrene 部署指南
|
||||||
|
|
||||||
三种方式启动开发环境:**DevTools 一键**(推荐)、**手动逐服务**、**Docker Compose**。
|
三种方式启动开发环境:**ethend 一键**(推荐)、**手动逐服务**、**Docker Compose**。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -9,9 +9,9 @@
|
|||||||
| 依赖 | 版本 | 用途 |
|
| 依赖 | 版本 | 用途 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| Go | 1.21+ | 编译后端服务 |
|
| Go | 1.21+ | 编译后端服务 |
|
||||||
| Node.js | 20+ (LTS) | 前端 / DevTools |
|
| Node.js | 20+ (LTS) | 前端 / ethend |
|
||||||
| Docker & Docker Compose | — | 数据库 & 基础设施 |
|
| Docker & Docker Compose | — | 数据库 & 基础设施 |
|
||||||
| Git Bash (Windows) | — | 运行 devtools.sh |
|
| Git Bash (Windows) | — | 运行 ethend.sh |
|
||||||
|
|
||||||
### Windows 额外要求
|
### Windows 额外要求
|
||||||
|
|
||||||
@@ -23,14 +23,14 @@ Windows 提供两个启动脚本:
|
|||||||
|
|
||||||
| 脚本 | 终端 | 适用场景 |
|
| 脚本 | 终端 | 适用场景 |
|
||||||
|------|------|----------|
|
|------|------|----------|
|
||||||
| `devtools.bat` | CMD / PowerShell | 双击运行,无需 Git Bash |
|
| `ethend.bat` | CMD / PowerShell | 双击运行,无需 Git Bash |
|
||||||
| `devtools.sh` | Git Bash | 完整 CLI 体验(推荐) |
|
| `ethend.sh` | Git Bash | 完整 CLI 体验(推荐) |
|
||||||
|
|
||||||
两者支持相同的命令集,日常开发推荐使用 Git Bash 运行 `./devtools.sh`;快速启动可直接双击 `devtools.bat`。
|
两者支持相同的命令集,日常开发推荐使用 Git Bash 运行 `./ethend.sh`;快速启动可直接双击 `ethend.bat`。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 方式一:DevTools 一键启动(推荐)
|
## 方式一:ethend 一键启动(推荐)
|
||||||
|
|
||||||
### 1. 配置环境变量
|
### 1. 配置环境变量
|
||||||
|
|
||||||
@@ -44,13 +44,13 @@ cp backend/.env.example backend/.env
|
|||||||
### 2. 启动数据库
|
### 2. 启动数据库
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./devtools.sh db:start
|
./ethend.sh db:start
|
||||||
```
|
```
|
||||||
|
|
||||||
### 3. 编译并启动全部服务
|
### 3. 编译并启动全部服务
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./devtools.sh start --build
|
./ethend.sh start --build
|
||||||
```
|
```
|
||||||
|
|
||||||
首次运行会编译全部后端 Go 服务(约 1-2 分钟),之后按依赖顺序启动全部服务,每步等待健康检查通过。
|
首次运行会编译全部后端 Go 服务(约 1-2 分钟),之后按依赖顺序启动全部服务,每步等待健康检查通过。
|
||||||
@@ -59,10 +59,10 @@ cp backend/.env.example backend/.env
|
|||||||
|
|
||||||
| 地址 | 说明 |
|
| 地址 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `http://localhost:9090` | DevTools 管理面板 |
|
| `http://localhost:9090` | ethend 管理面板 |
|
||||||
| `http://localhost:5173` | 前端聊天界面 |
|
| `http://localhost:5173` | 前端聊天界面 |
|
||||||
|
|
||||||
详细 CLI 用法见 [docs/api/devtools.md](docs/api/devtools.md)。
|
详细 CLI 用法见 [docs/api/ethend.md](docs/api/ethend.md)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -111,7 +111,7 @@ cd frontend/web && npm install && npx vite --host 0.0.0.0
|
|||||||
docker compose -f docker-compose.dev.yml up -d
|
docker compose -f docker-compose.dev.yml up -d
|
||||||
```
|
```
|
||||||
|
|
||||||
启动服务:postgres, redis, qdrant, minio, searxng, memory-service, voice-service, iot-debug-service, ai-core, gateway, devtools。前端需本地启动。
|
启动服务:postgres, redis, qdrant, minio, searxng, memory-service, voice-service, iot-debug-service, ai-core, gateway, ethend。前端需本地启动。
|
||||||
|
|
||||||
### 生产环境
|
### 生产环境
|
||||||
|
|
||||||
@@ -140,16 +140,16 @@ Cyrene/
|
|||||||
│ ├── voice-service/ # 语音服务 (DashScope STT + Edge-TTS)
|
│ ├── voice-service/ # 语音服务 (DashScope STT + Edge-TTS)
|
||||||
│ ├── iot-debug-service/ # IoT 调试服务 (8 个模拟智能家居设备)
|
│ ├── iot-debug-service/ # IoT 调试服务 (8 个模拟智能家居设备)
|
||||||
│ └── pkg/ # 共享包 (logger, plugins — 15 个通用插件/工具)
|
│ └── pkg/ # 共享包 (logger, plugins — 15 个通用插件/工具)
|
||||||
├── devtools/ # DevTools 管理面板 (Express + WebSocket)
|
├── ethend/ # ethend 管理面板 (Express + WebSocket)
|
||||||
├── scripts/ # 辅助脚本 (migrate / tunnel / whisper-setup / pg-backup)
|
├── scripts/ # 辅助脚本 (migrate / tunnel / whisper-setup / pg-backup)
|
||||||
├── searxng/ # SearXNG 搜索引擎配置
|
├── searxng/ # SearXNG 搜索引擎配置
|
||||||
├── backups/ # 数据库备份文件
|
├── backups/ # 数据库备份文件
|
||||||
├── test/ # E2E 测试
|
├── test/ # E2E 测试
|
||||||
├── docs/ # 文档
|
├── docs/ # 文档
|
||||||
├── docker-compose.dev.db.yml # 开发基础设施
|
├── docker-compose.dev.db.yml # 开发基础设施
|
||||||
├── docker-compose.dev.yml # 开发环境 (DB + 后端 + DevTools + SearXNG)
|
├── docker-compose.dev.yml # 开发环境 (DB + 后端 + ethend + SearXNG)
|
||||||
├── docker-compose.yml # 生产环境 (+ Caddy)
|
├── docker-compose.yml # 生产环境 (+ Caddy)
|
||||||
└── devtools.sh # DevTools CLI
|
└── ethend.sh # ethend CLI
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -165,7 +165,7 @@ Cyrene/
|
|||||||
| 8091 | Memory Service | 否 |
|
| 8091 | Memory Service | 否 |
|
||||||
| 8088 | SearXNG | 否 |
|
| 8088 | SearXNG | 否 |
|
||||||
| 8093 | Voice Service | 否 |
|
| 8093 | Voice Service | 否 |
|
||||||
| 9090 | DevTools | 是 |
|
| 9090 | ethend | 是 |
|
||||||
| 5432 | PostgreSQL | 否 |
|
| 5432 | PostgreSQL | 否 |
|
||||||
| 6379 | Redis | 否 |
|
| 6379 | Redis | 否 |
|
||||||
| 6333 | Qdrant HTTP | 否 |
|
| 6333 | Qdrant HTTP | 否 |
|
||||||
@@ -239,10 +239,10 @@ Cyrene/
|
|||||||
## 数据库管理
|
## 数据库管理
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 通过 DevTools CLI
|
# 通过 ethend CLI
|
||||||
./devtools.sh db:start # 启动
|
./ethend.sh db:start # 启动
|
||||||
./devtools.sh db:stop # 停止
|
./ethend.sh db:stop # 停止
|
||||||
./devtools.sh db:status # 状态检查
|
./ethend.sh db:status # 状态检查
|
||||||
|
|
||||||
# 直接 Docker Compose
|
# 直接 Docker Compose
|
||||||
docker compose -f docker-compose.dev.db.yml up -d
|
docker compose -f docker-compose.dev.db.yml up -d
|
||||||
@@ -280,23 +280,23 @@ docker exec -it cyrene_postgres psql -U cyrene -d cyrene_ai
|
|||||||
|
|
||||||
| 脚本 | 终端 | 说明 |
|
| 脚本 | 终端 | 说明 |
|
||||||
|------|------|------|
|
|------|------|------|
|
||||||
| `devtools.bat` | CMD / PowerShell | 双击即可运行,无需 Git Bash |
|
| `ethend.bat` | CMD / PowerShell | 双击即可运行,无需 Git Bash |
|
||||||
| `devtools.sh` | Git Bash | 完整 CLI(推荐) |
|
| `ethend.sh` | Git Bash | 完整 CLI(推荐) |
|
||||||
|
|
||||||
```cmd
|
```cmd
|
||||||
:: CMD 中直接运行
|
:: CMD 中直接运行
|
||||||
devtools.bat start --build
|
ethend.bat start --build
|
||||||
devtools.bat status
|
ethend.bat status
|
||||||
devtools.bat logs gateway
|
ethend.bat logs gateway
|
||||||
|
|
||||||
:: Git Bash 中运行
|
:: Git Bash 中运行
|
||||||
./devtools.sh start --build
|
./ethend.sh start --build
|
||||||
./devtools.sh status
|
./ethend.sh status
|
||||||
```
|
```
|
||||||
|
|
||||||
### 编译差异
|
### 编译差异
|
||||||
|
|
||||||
Windows 下 Go 编译产物为 `main.exe` 而非 `main`。DevTools 已自动处理此差异,手动编译时需要注意:
|
Windows 下 Go 编译产物为 `main.exe` 而非 `main`。ethend 已自动处理此差异,手动编译时需要注意:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Windows (Git Bash / PowerShell)
|
# Windows (Git Bash / PowerShell)
|
||||||
@@ -325,9 +325,9 @@ netstat -ano | findstr ":8080"
|
|||||||
# 杀进程 (PowerShell)
|
# 杀进程 (PowerShell)
|
||||||
powershell -Command "Stop-Process -Id <PID> -Force"
|
powershell -Command "Stop-Process -Id <PID> -Force"
|
||||||
|
|
||||||
# 或者直接用 DevTools CLI(跨平台兼容)
|
# 或者直接用 ethend CLI(跨平台兼容)
|
||||||
./devtools.sh status # 查看各服务端口状态
|
./ethend.sh status # 查看各服务端口状态
|
||||||
./devtools.sh stop # 停止 DevTools
|
./ethend.sh stop # 停止 ethend
|
||||||
```
|
```
|
||||||
|
|
||||||
### Docker Desktop
|
### Docker Desktop
|
||||||
@@ -361,7 +361,7 @@ export PATH="$PATH:/c/Program Files/nodejs"
|
|||||||
| 症状 | 可能原因 | 解决 |
|
| 症状 | 可能原因 | 解决 |
|
||||||
|------|----------|------|
|
|------|----------|------|
|
||||||
| `go: command not found` | Go 未加入 PATH | 重启 Git Bash 或手动 `export PATH` |
|
| `go: command not found` | Go 未加入 PATH | 重启 Git Bash 或手动 `export PATH` |
|
||||||
| `Only one usage of each socket address` | 端口被占用 | `./devtools.sh stop` 或用 PowerShell 杀进程 |
|
| `Only one usage of each socket address` | 端口被占用 | `./ethend.sh stop` 或用 PowerShell 杀进程 |
|
||||||
| `docker: error during connect` | Docker Desktop 未启动 | 启动 Docker Desktop 等待就绪 |
|
| `docker: error during connect` | Docker Desktop 未启动 | 启动 Docker Desktop 等待就绪 |
|
||||||
| `GOWORK` 相关编译错误 | 未设置 GOWORK=off | `export GOWORK=off` 或在命令前加 `GOWORK=off` |
|
| `GOWORK` 相关编译错误 | 未设置 GOWORK=off | `export GOWORK=off` 或在命令前加 `GOWORK=off` |
|
||||||
| `npm install` 卡住 | Windows 下 npm 网络问题 | 设置镜像 `npm config set registry https://registry.npmmirror.com` |
|
| `npm install` 卡住 | Windows 下 npm 网络问题 | 设置镜像 `npm config set registry https://registry.npmmirror.com` |
|
||||||
|
|||||||
+7
-7
@@ -19,7 +19,7 @@
|
|||||||
| 前端配置文件 | `frontend/web/vite.config.ts`, `frontend/web/tsconfig.json`, `frontend/web/tailwind.config.ts` 等 | 构建和样式配置 |
|
| 前端配置文件 | `frontend/web/vite.config.ts`, `frontend/web/tsconfig.json`, `frontend/web/tailwind.config.ts` 等 | 构建和样式配置 |
|
||||||
| 前端入口 | `frontend/web/index.html` | HTML 入口 |
|
| 前端入口 | `frontend/web/index.html` | HTML 入口 |
|
||||||
| 公共资源 | `frontend/web/public/` | 静态资源(头像、背景图、manifest 等) |
|
| 公共资源 | `frontend/web/public/` | 静态资源(头像、背景图、manifest 等) |
|
||||||
| DevTools | `devtools/` | 管理面板源码 |
|
| ethend | `ethend/` | 管理面板源码 |
|
||||||
| Python 测试脚本 | `debug/cache/*.py` | 调试和端到端测试脚本 |
|
| Python 测试脚本 | `debug/cache/*.py` | 调试和端到端测试脚本 |
|
||||||
| Shell 调试脚本 | `debug/*.sh`, `debug/*.mjs` | Chromium 调试、诊断脚本 |
|
| Shell 调试脚本 | `debug/*.sh`, `debug/*.mjs` | Chromium 调试、诊断脚本 |
|
||||||
| 项目配置 | `.editorconfig`, `.gitignore`, `package.json` 等 | 项目级配置 |
|
| 项目配置 | `.editorconfig`, `.gitignore`, `package.json` 等 | 项目级配置 |
|
||||||
@@ -36,7 +36,7 @@
|
|||||||
|------|----------|------|
|
|------|----------|------|
|
||||||
| 编译后的 Go 二进制 | `main`, `backend/*/main`, `backend/*/cmd/*` (不含 `.go`) | 平台相关,需在 Windows 重新编译 |
|
| 编译后的 Go 二进制 | `main`, `backend/*/main`, `backend/*/cmd/*` (不含 `.go`) | 平台相关,需在 Windows 重新编译 |
|
||||||
| Windows 可执行文件 | `*.exe` | 旧的 Windows 编译产物 |
|
| Windows 可执行文件 | `*.exe` | 旧的 Windows 编译产物 |
|
||||||
| Node.js 依赖 | `node_modules/`, `frontend/web/node_modules/`, `frontend/node_modules/`, `devtools/node_modules/` | 体积大,通过 `npm install` 重新安装 |
|
| Node.js 依赖 | `node_modules/`, `frontend/web/node_modules/`, `frontend/node_modules/`, `ethend/node_modules/` | 体积大,通过 `npm install` 重新安装 |
|
||||||
| 前端构建产物 | `frontend/web/dist/` | 通过 `npm run build` 重新构建 |
|
| 前端构建产物 | `frontend/web/dist/` | 通过 `npm run build` 重新构建 |
|
||||||
| 敏感配置文件 | `backend/.env` | 包含 API 密钥和密码 |
|
| 敏感配置文件 | `backend/.env` | 包含 API 密钥和密码 |
|
||||||
| 锁文件 | `package-lock.json`, `frontend/web/package-lock.json`, `frontend/package-lock.json` | 跨平台 npm 依赖树可能不同 |
|
| 锁文件 | `package-lock.json`, `frontend/web/package-lock.json`, `frontend/package-lock.json` | 跨平台 npm 依赖树可能不同 |
|
||||||
@@ -241,10 +241,10 @@ docker-compose -f docker-compose.dev.db.yml up -d
|
|||||||
|
|
||||||
### 6.5 启动顺序
|
### 6.5 启动顺序
|
||||||
|
|
||||||
**推荐使用 DevTools 一键启动**(自动编译 + 按序启动 + 健康检查):
|
**推荐使用 ethend 一键启动**(自动编译 + 按序启动 + 健康检查):
|
||||||
|
|
||||||
```cmd
|
```cmd
|
||||||
cd devtools
|
cd ethend
|
||||||
node src\index.js
|
node src\index.js
|
||||||
:: 浏览器打开 http://localhost:9090,点击「一键启动」
|
:: 浏览器打开 http://localhost:9090,点击「一键启动」
|
||||||
```
|
```
|
||||||
@@ -252,10 +252,10 @@ node src\index.js
|
|||||||
或使用启动脚本:
|
或使用启动脚本:
|
||||||
|
|
||||||
```cmd
|
```cmd
|
||||||
devtools.bat
|
ethend.bat
|
||||||
```
|
```
|
||||||
|
|
||||||
DevTools 会按以下顺序自动编译并启动所有 6 个服务:
|
ethend 会按以下顺序自动编译并启动所有 6 个服务:
|
||||||
|
|
||||||
| 顺序 | 服务 | 端口 | 说明 |
|
| 顺序 | 服务 | 端口 | 说明 |
|
||||||
|------|------|------|------|
|
|------|------|------|------|
|
||||||
@@ -266,7 +266,7 @@ DevTools 会按以下顺序自动编译并启动所有 6 个服务:
|
|||||||
| 5 | gateway | 8080 | API 网关 / JWT / WebSocket |
|
| 5 | gateway | 8080 | API 网关 / JWT / WebSocket |
|
||||||
| 6 | frontend | 5173 | React 开发服务器 |
|
| 6 | frontend | 5173 | React 开发服务器 |
|
||||||
|
|
||||||
> 每个步骤会自动等待健康检查通过后再启动下一个服务。如果 Go 二进制未编译,DevTools 会自动先编译再启动。
|
> 每个步骤会自动等待健康检查通过后再启动下一个服务。如果 Go 二进制未编译,ethend 会自动先编译再启动。
|
||||||
|
|
||||||
如需手动逐个启动:
|
如需手动逐个启动:
|
||||||
|
|
||||||
|
|||||||
@@ -89,10 +89,10 @@ docker compose -f docker-compose.dev.db.yml up -d
|
|||||||
|
|
||||||
```bash
|
```bash
|
||||||
# Linux / macOS (Git Bash)
|
# Linux / macOS (Git Bash)
|
||||||
./devtools.sh start --build
|
./ethend.sh start --build
|
||||||
|
|
||||||
# Windows CMD / PowerShell
|
# Windows CMD / PowerShell
|
||||||
devtools.bat start --build
|
ethend.bat start --build
|
||||||
```
|
```
|
||||||
|
|
||||||
按依赖顺序编译并启动全部 8 个服务:memory → plugin-manager → iot-debug → voice → ai-core → platform-bridge → gateway → frontend。
|
按依赖顺序编译并启动全部 8 个服务:memory → plugin-manager → iot-debug → voice → ai-core → platform-bridge → gateway → frontend。
|
||||||
@@ -102,21 +102,21 @@ devtools.bat start --build
|
|||||||
| 地址 | 说明 |
|
| 地址 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `http://localhost:5173` | 前端聊天界面 |
|
| `http://localhost:5173` | 前端聊天界面 |
|
||||||
| `http://localhost:9090` | DevTools 管理面板 |
|
| `http://localhost:9090` | ethend 管理面板 |
|
||||||
|
|
||||||
使用 `.env` 中配置的 `ADMIN_USERNAME` / `ADMIN_PASSWORD` 登录。
|
使用 `.env` 中配置的 `ADMIN_USERNAME` / `ADMIN_PASSWORD` 登录。
|
||||||
|
|
||||||
### 其他 CLI 命令
|
### 其他 CLI 命令
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./devtools.sh status # 查看服务状态
|
./ethend.sh status # 查看服务状态
|
||||||
./devtools.sh logs gateway # 查看 Gateway 日志
|
./ethend.sh logs gateway # 查看 Gateway 日志
|
||||||
./devtools.sh build ai-core # 单独编译 AI-Core
|
./ethend.sh build ai-core # 单独编译 AI-Core
|
||||||
./devtools.sh db:status # 检查数据库状态
|
./ethend.sh db:status # 检查数据库状态
|
||||||
./devtools.sh help # 完整帮助
|
./ethend.sh help # 完整帮助
|
||||||
```
|
```
|
||||||
|
|
||||||
详见 [docs/api/devtools.md](docs/api/devtools.md)。
|
详见 [docs/api/ethend.md](docs/api/ethend.md)。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -135,7 +135,7 @@ Cyrene/
|
|||||||
│ ├── plugin-manager/ # 插件管理器 (管理 API,插件逻辑在 pkg/plugins)
|
│ ├── plugin-manager/ # 插件管理器 (管理 API,插件逻辑在 pkg/plugins)
|
||||||
│ ├── platform-bridge/ # 多平台桥接 (QQ / Telegram / Discord / Webhook)
|
│ ├── platform-bridge/ # 多平台桥接 (QQ / Telegram / Discord / Webhook)
|
||||||
│ └── pkg/ # 共享包 (logger, plugins — 15 个通用插件/工具)
|
│ └── pkg/ # 共享包 (logger, plugins — 15 个通用插件/工具)
|
||||||
├── devtools/ # DevTools 管理面板 (Express + WebSocket)
|
├── ethend/ # ethend 管理面板 (Express + WebSocket)
|
||||||
├── scripts/ # 辅助脚本 (migrate / tunnel / whisper-setup / pg-backup)
|
├── scripts/ # 辅助脚本 (migrate / tunnel / whisper-setup / pg-backup)
|
||||||
├── backups/ # 数据库备份文件 (.gitignore)
|
├── backups/ # 数据库备份文件 (.gitignore)
|
||||||
├── test/ # E2E 测试
|
├── test/ # E2E 测试
|
||||||
@@ -145,8 +145,8 @@ Cyrene/
|
|||||||
├── docker-compose.dev.db.yml # 开发基础设施 (仅 DB)
|
├── docker-compose.dev.db.yml # 开发基础设施 (仅 DB)
|
||||||
├── docker-compose.dev.yml # 开发环境一键启动
|
├── docker-compose.dev.yml # 开发环境一键启动
|
||||||
├── docker-compose.yml # 生产环境 (含 Caddy)
|
├── docker-compose.yml # 生产环境 (含 Caddy)
|
||||||
├── devtools.sh # DevTools CLI (Git Bash)
|
├── ethend.sh # ethend CLI (Git Bash)
|
||||||
├── devtools.bat # DevTools CLI (CMD / PowerShell)
|
├── ethend.bat # ethend CLI (CMD / PowerShell)
|
||||||
└── Caddyfile # 反向代理配置
|
└── Caddyfile # 反向代理配置
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -165,7 +165,7 @@ Cyrene/
|
|||||||
| 8093 | Voice Service | 否 |
|
| 8093 | Voice Service | 否 |
|
||||||
| 8094 | Plugin Manager | 否 |
|
| 8094 | Plugin Manager | 否 |
|
||||||
| 8095 | Platform Bridge | 否 |
|
| 8095 | Platform Bridge | 否 |
|
||||||
| 9090 | DevTools | 是 |
|
| 9090 | ethend | 是 |
|
||||||
| 5432 | PostgreSQL | 否 |
|
| 5432 | PostgreSQL | 否 |
|
||||||
| 6379 | Redis | 否 |
|
| 6379 | Redis | 否 |
|
||||||
| 6333 | Qdrant HTTP | 否 |
|
| 6333 | Qdrant HTTP | 否 |
|
||||||
@@ -200,7 +200,7 @@ Cyrene/
|
|||||||
|------|------|
|
|------|------|
|
||||||
| [Deploy.md](Deploy.md) | 部署指南(含 Windows 说明) |
|
| [Deploy.md](Deploy.md) | 部署指南(含 Windows 说明) |
|
||||||
| [docs/api/gateway-api.md](docs/api/gateway-api.md) | 客户端 API 文档 |
|
| [docs/api/gateway-api.md](docs/api/gateway-api.md) | 客户端 API 文档 |
|
||||||
| [docs/api/devtools.md](docs/api/devtools.md) | DevTools CLI + Web 控制台文档 |
|
| [docs/api/ethend.md](docs/api/ethend.md) | ethend CLI + Web 控制台文档 |
|
||||||
| [docs/api/backend-services/](docs/api/backend-services/) | 后端服务 API 文档 |
|
| [docs/api/backend-services/](docs/api/backend-services/) | 后端服务 API 文档 |
|
||||||
| [docs/dev_must_read.md](docs/dev_must_read.md) | 开发者必读 |
|
| [docs/dev_must_read.md](docs/dev_must_read.md) | 开发者必读 |
|
||||||
| [docs/pg-backup-migration.md](docs/pg-backup-migration.md) | PG 备份与迁移指南 |
|
| [docs/pg-backup-migration.md](docs/pg-backup-migration.md) | PG 备份与迁移指南 |
|
||||||
|
|||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -176,7 +176,7 @@ func (h *Hub) cleanupIdleSessions() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetAllActiveSessions 返回所有会话状态(包括 idle),供 DevTools 监看使用
|
// GetAllActiveSessions 返回所有会话状态(包括 idle),供 ethend 监看使用
|
||||||
func (h *Hub) GetAllActiveSessions() []*SessionState {
|
func (h *Hub) GetAllActiveSessions() []*SessionState {
|
||||||
h.mu.RLock()
|
h.mu.RLock()
|
||||||
defer h.mu.RUnlock()
|
defer h.mu.RUnlock()
|
||||||
|
|||||||
@@ -0,0 +1,224 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
mode := flag.String("mode", "offline", "测试模式: offline (非实时) 或 realtime (实时)")
|
||||||
|
file := flag.String("file", "", "音频文件路径 (WAV/MP3/OGG/FLAC)")
|
||||||
|
server := flag.String("server", "http://localhost:8093", "Voice-Service 地址")
|
||||||
|
lang := flag.String("lang", "zh", "语言代码")
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
if *file == "" {
|
||||||
|
fmt.Println("用法: test_asr -mode=offline -file=audio.wav [-server=http://localhost:8093]")
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch *mode {
|
||||||
|
case "offline":
|
||||||
|
testOffline(*server, *file, *lang)
|
||||||
|
case "realtime":
|
||||||
|
testRealtime(*server, *file, *lang)
|
||||||
|
default:
|
||||||
|
fmt.Printf("未知模式: %s (支持: offline, realtime)\n", *mode)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// testOffline 测试非实时语音识别 (HTTP multipart 上传)。
|
||||||
|
func testOffline(server, filePath, lang string) {
|
||||||
|
fmt.Printf("=== 非实时 ASR 测试 ===\n")
|
||||||
|
fmt.Printf("服务器: %s\n", server)
|
||||||
|
fmt.Printf("文件: %s\n", filePath)
|
||||||
|
fmt.Printf("语言: %s\n\n", lang)
|
||||||
|
|
||||||
|
// 读取音频文件
|
||||||
|
audioData, err := os.ReadFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("读取文件失败: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Printf("音频大小: %d bytes\n", len(audioData))
|
||||||
|
|
||||||
|
// 创建 multipart 请求
|
||||||
|
req, err := http.NewRequest("POST", server+"/api/v1/transcribe", nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("创建请求失败: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// 使用 multipart form
|
||||||
|
body, contentType, err := createMultipartBody(audioData, filePath, lang)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("创建 multipart body 失败: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
req.Body = body
|
||||||
|
req.Header.Set("Content-Type", contentType)
|
||||||
|
|
||||||
|
start := time.Now()
|
||||||
|
resp, err := http.DefaultClient.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("请求失败: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
elapsed := time.Since(start)
|
||||||
|
respBody, _ := io.ReadAll(resp.Body)
|
||||||
|
|
||||||
|
fmt.Printf("状态码: %d\n", resp.StatusCode)
|
||||||
|
fmt.Printf("耗时: %v\n", elapsed)
|
||||||
|
fmt.Printf("响应:\n%s\n", string(respBody))
|
||||||
|
|
||||||
|
if resp.StatusCode == 200 {
|
||||||
|
fmt.Println("\n✅ 非实时语音识别成功!")
|
||||||
|
} else {
|
||||||
|
fmt.Println("\n❌ 非实时语音识别失败")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// testRealtime 测试实时语音识别 (WebSocket 流式)。
|
||||||
|
func testRealtime(server, filePath, lang string) {
|
||||||
|
fmt.Printf("=== 实时 ASR 测试 ===\n")
|
||||||
|
fmt.Printf("服务器: %s\n", server)
|
||||||
|
fmt.Printf("文件: %s\n", filePath)
|
||||||
|
fmt.Printf("语言: %s\n\n", lang)
|
||||||
|
|
||||||
|
// 读取音频文件
|
||||||
|
audioData, err := os.ReadFile(filePath)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("读取文件失败: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
fmt.Printf("音频大小: %d bytes\n", len(audioData))
|
||||||
|
|
||||||
|
// 推断格式
|
||||||
|
format := inferFormat(filePath)
|
||||||
|
|
||||||
|
// 连接 WebSocket
|
||||||
|
wsURL := fmt.Sprintf("ws://%s/api/v1/stt/stream?format=%s&language=%s",
|
||||||
|
server[7:], format, lang) // 去掉 http:// 前缀
|
||||||
|
conn, _, err := websocket.DefaultDialer.Dial(wsURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("WebSocket 连接失败: %v\n", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
|
||||||
|
fmt.Printf("WebSocket 已连接: %s\n", wsURL)
|
||||||
|
|
||||||
|
// 设置 interrupt 处理
|
||||||
|
interrupt := make(chan os.Signal, 1)
|
||||||
|
signal.Notify(interrupt, os.Interrupt)
|
||||||
|
|
||||||
|
// goroutine: 读取识别结果
|
||||||
|
done := make(chan struct{})
|
||||||
|
go func() {
|
||||||
|
defer close(done)
|
||||||
|
for {
|
||||||
|
_, msg, err := conn.ReadMessage()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("读取结果错误: %v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fmt.Printf("◀ 结果: %s\n", string(msg))
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
// 模拟实时流式发送音频(每 100ms 发送 3200 bytes)
|
||||||
|
chunkSize := 3200
|
||||||
|
totalSent := 0
|
||||||
|
start := time.Now()
|
||||||
|
var elapsed time.Duration
|
||||||
|
|
||||||
|
cancelled := false
|
||||||
|
for i := 0; i < len(audioData); i += chunkSize {
|
||||||
|
end := i + chunkSize
|
||||||
|
if end > len(audioData) {
|
||||||
|
end = len(audioData)
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
case <-interrupt:
|
||||||
|
fmt.Println("\n用户中断")
|
||||||
|
cancelled = true
|
||||||
|
default:
|
||||||
|
}
|
||||||
|
if cancelled {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := conn.WriteMessage(websocket.BinaryMessage, audioData[i:end]); err != nil {
|
||||||
|
fmt.Printf("发送音频失败: %v\n", err)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
totalSent += end - i
|
||||||
|
fmt.Printf("▶ 发送 %d/%d bytes (%.1f%%)\n", totalSent, len(audioData),
|
||||||
|
float64(totalSent)/float64(len(audioData))*100)
|
||||||
|
time.Sleep(100 * time.Millisecond)
|
||||||
|
}
|
||||||
|
|
||||||
|
elapsed = time.Since(start)
|
||||||
|
|
||||||
|
// 发送停止消息
|
||||||
|
conn.WriteMessage(websocket.TextMessage, []byte(`{"action":"stop"}`))
|
||||||
|
|
||||||
|
// 等待最后的结果
|
||||||
|
time.Sleep(2 * time.Second)
|
||||||
|
|
||||||
|
fmt.Printf("\n总耗时: %v, 总发送: %d bytes\n", elapsed, totalSent)
|
||||||
|
fmt.Println("✅ 实时语音识别测试完成")
|
||||||
|
}
|
||||||
|
|
||||||
|
func inferFormat(filename string) string {
|
||||||
|
ext := ""
|
||||||
|
for i := len(filename) - 1; i >= 0; i-- {
|
||||||
|
if filename[i] == '.' {
|
||||||
|
ext = filename[i+1:]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switch ext {
|
||||||
|
case "wav", "wave":
|
||||||
|
return "wav"
|
||||||
|
case "mp3", "mpeg":
|
||||||
|
return "mp3"
|
||||||
|
case "ogg", "opus":
|
||||||
|
return "ogg"
|
||||||
|
case "flac":
|
||||||
|
return "flac"
|
||||||
|
case "m4a", "mp4", "aac":
|
||||||
|
return "m4a"
|
||||||
|
default:
|
||||||
|
return "pcm"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createMultipartBody(audioData []byte, filename, lang string) (io.ReadCloser, string, error) {
|
||||||
|
boundary := "cyrene-asr-test-boundary"
|
||||||
|
header := fmt.Sprintf("--%s\r\nContent-Disposition: form-data; name=\"audio\"; filename=\"%s\"\r\nContent-Type: application/octet-stream\r\n\r\n",
|
||||||
|
boundary, filename)
|
||||||
|
footer := fmt.Sprintf("\r\n--%s\r\nContent-Disposition: form-data; name=\"language\"\r\n\r\n%s\r\n--%s--\r\n",
|
||||||
|
boundary, lang, boundary)
|
||||||
|
|
||||||
|
pr, pw := io.Pipe()
|
||||||
|
go func() {
|
||||||
|
pw.Write([]byte(header))
|
||||||
|
pw.Write(audioData)
|
||||||
|
pw.Write([]byte(footer))
|
||||||
|
pw.Close()
|
||||||
|
}()
|
||||||
|
|
||||||
|
return pr, "multipart/form-data; boundary=" + boundary, nil
|
||||||
|
}
|
||||||
Vendored
+1
-1
@@ -668,7 +668,7 @@ print("\n" + "=" * 70)
|
|||||||
print("Part I: 服务日志摘要")
|
print("Part I: 服务日志摘要")
|
||||||
print("=" * 70)
|
print("=" * 70)
|
||||||
|
|
||||||
LOG_DIR = "/home/aska/Code/Cyrene/devtools/logs"
|
LOG_DIR = "/home/aska/Code/Cyrene/ethend/logs"
|
||||||
log_files = {
|
log_files = {
|
||||||
"ai-core": f"{LOG_DIR}/ai-core.log",
|
"ai-core": f"{LOG_DIR}/ai-core.log",
|
||||||
"gateway": f"{LOG_DIR}/gateway.log",
|
"gateway": f"{LOG_DIR}/gateway.log",
|
||||||
|
|||||||
Vendored
+1
-1
@@ -4,7 +4,7 @@ import json, time, base64, os
|
|||||||
from websocket import create_connection
|
from websocket import create_connection
|
||||||
|
|
||||||
PAGE_URL = "http://localhost:5199/"
|
PAGE_URL = "http://localhost:5199/"
|
||||||
CDP_WS = "ws://127.0.0.1:9225/devtools/browser/b2fca0da-35d6-4180-8413-eddf53753c6a"
|
CDP_WS = "ws://127.0.0.1:9225/ethend/browser/b2fca0da-35d6-4180-8413-eddf53753c6a"
|
||||||
|
|
||||||
def send_cmd(ws, method, params=None, msg_id=1):
|
def send_cmd(ws, method, params=None, msg_id=1):
|
||||||
payload = json.dumps({"id": msg_id, "method": method, "params": params or {}})
|
payload = json.dumps({"id": msg_id, "method": method, "params": params or {}})
|
||||||
|
|||||||
@@ -74,19 +74,19 @@ services:
|
|||||||
- "8088:8080"
|
- "8088:8080"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
# ========== 开发调试工具 ==========
|
# ==========管理控制台 ==========
|
||||||
devtools:
|
ethend:
|
||||||
container_name: cyrene_devtools
|
container_name: cyrene_ethend
|
||||||
build:
|
build:
|
||||||
context: ./devtools
|
context: ./ethend
|
||||||
dockerfile: Dockerfile
|
dockerfile: Dockerfile
|
||||||
environment:
|
environment:
|
||||||
DEVTOOLS_PORT: "9090"
|
ETHEND_PORT: "9090"
|
||||||
GATEWAY_URL: http://gateway:8080
|
GATEWAY_URL: http://gateway:8080
|
||||||
AI_CORE_URL: http://ai-core:8081
|
AI_CORE_URL: http://ai-core:8081
|
||||||
MEMORY_SERVICE_URL: http://memory-service:8091
|
MEMORY_SERVICE_URL: http://memory-service:8091
|
||||||
VOICE_SERVICE_URL: http://voice-service:8093
|
VOICE_SERVICE_URL: http://voice-service:8093
|
||||||
PLATFORM_BRIDGE_URL: http://platform-bridge:8095
|
IOT_DEBUG_SERVICE_URL: http://iot-debug-service:8083
|
||||||
ADMIN_USERNAME: admin
|
ADMIN_USERNAME: admin
|
||||||
ADMIN_PASSWORD: cyrene-dev-admin
|
ADMIN_PASSWORD: cyrene-dev-admin
|
||||||
ports:
|
ports:
|
||||||
|
|||||||
@@ -143,6 +143,27 @@ services:
|
|||||||
IOT_DEBUG_PORT: "8083"
|
IOT_DEBUG_PORT: "8083"
|
||||||
restart: unless-stopped
|
restart: unless-stopped
|
||||||
|
|
||||||
|
# ========== 管理控制台 ==========
|
||||||
|
ethend:
|
||||||
|
container_name: cyrene_ethend
|
||||||
|
build:
|
||||||
|
context: ./ethend
|
||||||
|
dockerfile: Dockerfile
|
||||||
|
environment:
|
||||||
|
ETHEND_PORT: "${ETHEND_PORT:-9090}"
|
||||||
|
GATEWAY_URL: http://gateway:8080
|
||||||
|
AI_CORE_URL: http://ai-core:8081
|
||||||
|
MEMORY_SERVICE_URL: http://memory-service:8091
|
||||||
|
VOICE_SERVICE_URL: http://voice-service:8093
|
||||||
|
IOT_DEBUG_SERVICE_URL: http://iot-debug-service:8083
|
||||||
|
ADMIN_USERNAME: ${ADMIN_USERNAME:-admin}
|
||||||
|
ADMIN_PASSWORD: ${ADMIN_PASSWORD}
|
||||||
|
ports:
|
||||||
|
- "${ETHEND_PORT:-9090}:9090"
|
||||||
|
depends_on:
|
||||||
|
- gateway
|
||||||
|
restart: unless-stopped
|
||||||
|
|
||||||
# ========== 基础设施 ==========
|
# ========== 基础设施 ==========
|
||||||
postgres:
|
postgres:
|
||||||
container_name: cyrene_postgres
|
container_name: cyrene_postgres
|
||||||
|
|||||||
@@ -1,12 +1,12 @@
|
|||||||
# Cyrene DevTools 文档
|
# Cyrene ethend 文档
|
||||||
|
|
||||||
DevTools 是 Cyrene 项目的开发管理控制台,提供 Web UI + CLI 两种使用方式。默认端口 **9090**。
|
ethend 是 Cyrene 项目的开发管理控制台,提供 Web UI + CLI 两种使用方式。默认端口 **9090**。
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 目录
|
## 目录
|
||||||
|
|
||||||
1. [CLI 命令 (devtools.sh)](#1-cli-命令)
|
1. [CLI 命令 (ethend.sh)](#1-cli-命令)
|
||||||
2. [Web 控制台面板](#2-web-控制台面板)
|
2. [Web 控制台面板](#2-web-控制台面板)
|
||||||
3. [REST API](#3-rest-api)
|
3. [REST API](#3-rest-api)
|
||||||
|
|
||||||
@@ -14,16 +14,16 @@ DevTools 是 Cyrene 项目的开发管理控制台,提供 Web UI + CLI 两种
|
|||||||
|
|
||||||
## 1. CLI 命令
|
## 1. CLI 命令
|
||||||
|
|
||||||
`./devtools.sh [命令] [选项]`
|
`./ethend.sh [命令] [选项]`
|
||||||
|
|
||||||
### 基本命令
|
### 基本命令
|
||||||
|
|
||||||
| 命令 | 说明 |
|
| 命令 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `start` | 启动 DevTools 控制台 |
|
| `start` | 启动 ethend 控制台 |
|
||||||
| `start --build` | 编译全部后端服务后启动 |
|
| `start --build` | 编译全部后端服务后启动 |
|
||||||
| `start --fresh` | 强制重启全部后端服务后启动 |
|
| `start --fresh` | 强制重启全部后端服务后启动 |
|
||||||
| `stop` | 停止 DevTools 控制台 |
|
| `stop` | 停止 ethend 控制台 |
|
||||||
| `status` | 查看所有服务状态(运行/停止、PID、uptime) |
|
| `status` | 查看所有服务状态(运行/停止、PID、uptime) |
|
||||||
| `logs <服务ID> [行数]` | 查看服务日志 |
|
| `logs <服务ID> [行数]` | 查看服务日志 |
|
||||||
| `build [服务ID]` | 编译服务(不指定则编译全部) |
|
| `build [服务ID]` | 编译服务(不指定则编译全部) |
|
||||||
@@ -36,7 +36,7 @@ DevTools 是 Cyrene 项目的开发管理控制台,提供 Web UI + CLI 两种
|
|||||||
|
|
||||||
| 选项 | 说明 |
|
| 选项 | 说明 |
|
||||||
|------|------|
|
|------|------|
|
||||||
| `--port, -p <端口>` | 指定 DevTools 端口 (默认: 9090) |
|
| `--port, -p <端口>` | 指定 ethend 端口 (默认: 9090) |
|
||||||
| `--fresh` | 启动前强制重启全部后端服务 |
|
| `--fresh` | 启动前强制重启全部后端服务 |
|
||||||
| `--build` | 启动前编译全部服务 |
|
| `--build` | 启动前编译全部服务 |
|
||||||
|
|
||||||
@@ -47,12 +47,12 @@ DevTools 是 Cyrene 项目的开发管理控制台,提供 Web UI + CLI 两种
|
|||||||
### 示例
|
### 示例
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
./devtools.sh # 快速启动
|
./ethend.sh # 快速启动
|
||||||
./devtools.sh start --build # 编译后启动
|
./ethend.sh start --build # 编译后启动
|
||||||
./devtools.sh start --fresh # 全新重启
|
./ethend.sh start --fresh # 全新重启
|
||||||
./devtools.sh logs gateway 20 # 查看 Gateway 最近 20 行日志
|
./ethend.sh logs gateway 20 # 查看 Gateway 最近 20 行日志
|
||||||
./devtools.sh build ai-core # 仅编译 AI-Core
|
./ethend.sh build ai-core # 仅编译 AI-Core
|
||||||
./devtools.sh db:status # 检查数据库状态
|
./ethend.sh db:status # 检查数据库状态
|
||||||
```
|
```
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -139,13 +139,13 @@ STT 转录日志(内存环形缓冲,最多 200 条),支持上传音频
|
|||||||
|
|
||||||
## 3. REST API
|
## 3. REST API
|
||||||
|
|
||||||
DevTools 自身暴露的 REST API,供脚本和外部工具使用。
|
ethend 自身暴露的 REST API,供脚本和外部工具使用。
|
||||||
|
|
||||||
### 健康检查
|
### 健康检查
|
||||||
|
|
||||||
```
|
```
|
||||||
GET /api/health
|
GET /api/health
|
||||||
→ { "status": "ok", "service": "cyrene-devtools", "uptime": 3600, "wsClients": 2 }
|
→ { "status": "ok", "service": "cyrene-ethend", "uptime": 3600, "wsClients": 2 }
|
||||||
```
|
```
|
||||||
|
|
||||||
### 服务管理
|
### 服务管理
|
||||||
@@ -191,7 +191,7 @@ GET /api/dashboard
|
|||||||
|
|
||||||
所有代理路由自动获取 Gateway JWT Token(通过 admin 凭据登录并缓存)。
|
所有代理路由自动获取 Gateway JWT Token(通过 admin 凭据登录并缓存)。
|
||||||
|
|
||||||
| DevTools 路径 | 目标服务 | 实际路径 |
|
| ethend 路径 | 目标服务 | 实际路径 |
|
||||||
|---------------|----------|----------|
|
|---------------|----------|----------|
|
||||||
| `/api/memory/*` | Gateway | `/api/v1/memory/*` |
|
| `/api/memory/*` | Gateway | `/api/v1/memory/*` |
|
||||||
| `/api/sessions*` | Gateway | `/api/v1/admin/sessions*` |
|
| `/api/sessions*` | Gateway | `/api/v1/admin/sessions*` |
|
||||||
@@ -201,7 +201,7 @@ GET /api/dashboard
|
|||||||
| `/api/tool-calls*` | AI-Core | `/api/v1/tools/calls*` |
|
| `/api/tool-calls*` | AI-Core | `/api/v1/tools/calls*` |
|
||||||
| `/api/voice/status` | Voice-Service | `/api/v1/status` |
|
| `/api/voice/status` | Voice-Service | `/api/v1/status` |
|
||||||
| `/api/voice/transcribe` | Voice-Service | `/api/v1/transcribe` |
|
| `/api/voice/transcribe` | Voice-Service | `/api/v1/transcribe` |
|
||||||
| `/api/voice/logs` | DevTools 内部 | 内存环形缓冲区 |
|
| `/api/voice/logs` | ethend 内部 | 内存环形缓冲区 |
|
||||||
| `/api/v1/thinking*` | Memory-Service | `/api/v1/thinking*` |
|
| `/api/v1/thinking*` | Memory-Service | `/api/v1/thinking*` |
|
||||||
| `/api/memory-timeline` | Memory-Service | 合并 Memories + Thinking |
|
| `/api/memory-timeline` | Memory-Service | 合并 Memories + Thinking |
|
||||||
| `/api/chat-platforms/*` | Platform-Bridge | `/api/v1/*` |
|
| `/api/chat-platforms/*` | Platform-Bridge | `/api/v1/*` |
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
- [自定义 Hooks](#44-自定义-hooks)
|
- [自定义 Hooks](#44-自定义-hooks)
|
||||||
- [API 模块](#45-api-模块)
|
- [API 模块](#45-api-模块)
|
||||||
- [WebSocket 消息流](#46-websocket-消息流)
|
- [WebSocket 消息流](#46-websocket-消息流)
|
||||||
5. [DevTools (9090) — 调试工具](#五devtools-9090--调试工具)
|
5. [ethend (9090) — 调试工具](#五ethend-9090--调试工具)
|
||||||
6. [对话管线详解](#六对话管线详解)
|
6. [对话管线详解](#六对话管线详解)
|
||||||
7. [数据库设计](#七数据库设计)
|
7. [数据库设计](#七数据库设计)
|
||||||
8. [安全性](#八安全性)
|
8. [安全性](#八安全性)
|
||||||
@@ -588,9 +588,9 @@ App
|
|||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## 五、DevTools (:9090) — 调试工具
|
## 五、ethend (:9090) — 调试工具
|
||||||
|
|
||||||
**目录**:`devtools/`
|
**目录**:`ethend/`
|
||||||
**类型**:Node.js Express 应用
|
**类型**:Node.js Express 应用
|
||||||
|
|
||||||
### 5.1 服务管理
|
### 5.1 服务管理
|
||||||
@@ -616,14 +616,14 @@ App
|
|||||||
|
|
||||||
### 5.3 关键配置
|
### 5.3 关键配置
|
||||||
|
|
||||||
**构建命令**([config.js](devtools/src/config.js)):
|
**构建命令**([config.js](ethend/src/config.js)):
|
||||||
```javascript
|
```javascript
|
||||||
buildCommand: 'go',
|
buildCommand: 'go',
|
||||||
buildArgs: ['build', '-o', isWin ? 'main.exe' : 'main', './cmd/main.go'],
|
buildArgs: ['build', '-o', isWin ? 'main.exe' : 'main', './cmd/main.go'],
|
||||||
goBin: GO_BIN
|
goBin: GO_BIN
|
||||||
```
|
```
|
||||||
|
|
||||||
所有 Go 服务统一编译为 `main.exe`(Windows),DevTools 通过 `./main` 启动。**自定义二进制名称不会被 DevTools 识别。**
|
所有 Go 服务统一编译为 `main.exe`(Windows),ethend 通过 `./main` 启动。**自定义二进制名称不会被 ethend 识别。**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -767,7 +767,7 @@ postgres://cyrene:cyrene_pass@localhost:5432/cyrene_ai?sslmode=disable
|
|||||||
| Memory | 8091 | net/http + pgvector |
|
| Memory | 8091 | net/http + pgvector |
|
||||||
| Voice | 8093 | net/http + whisper.cpp |
|
| Voice | 8093 | net/http + whisper.cpp |
|
||||||
| Frontend (dev) | 5173 | Vite |
|
| Frontend (dev) | 5173 | Vite |
|
||||||
| DevTools | 9090 | Express |
|
| ethend | 9090 | Express |
|
||||||
|
|
||||||
### 常用命令
|
### 常用命令
|
||||||
|
|
||||||
@@ -777,7 +777,7 @@ cd backend/ai-core && GOWORK=off go build -o main.exe ./cmd/main.go
|
|||||||
cd backend/gateway && GOWORK=off go build -o main.exe ./cmd/main.go
|
cd backend/gateway && GOWORK=off go build -o main.exe ./cmd/main.go
|
||||||
# ... 其他服务同理
|
# ... 其他服务同理
|
||||||
|
|
||||||
# 或通过 DevTools API
|
# 或通过 ethend API
|
||||||
curl -X POST http://localhost:9090/api/services/ai-core/build
|
curl -X POST http://localhost:9090/api/services/ai-core/build
|
||||||
curl -X POST http://localhost:9090/api/services/gateway/build
|
curl -X POST http://localhost:9090/api/services/gateway/build
|
||||||
|
|
||||||
@@ -845,7 +845,7 @@ Phase 6 新增,位于 `backend/models.json`(`.gitignore` 已排除)。格
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
**配置管理 API**(Gateway admin,DevTools 代理提供 UI):
|
**配置管理 API**(Gateway admin,ethend 代理提供 UI):
|
||||||
|
|
||||||
| Method | Path | Description |
|
| Method | Path | Description |
|
||||||
|--------|------|-------------|
|
|--------|------|-------------|
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ docker compose logs -f
|
|||||||
| memory-service | 8091 (内部) | 记忆检索 |
|
| memory-service | 8091 (内部) | 记忆检索 |
|
||||||
| voice-service | 8093 (内部) | 语音识别 |
|
| voice-service | 8093 (内部) | 语音识别 |
|
||||||
| iot-debug-service | 8083 (内部) | IoT 调试 |
|
| iot-debug-service | 8083 (内部) | IoT 调试 |
|
||||||
|
| ethend | 9090 (外部) | 管理控制台 |
|
||||||
| postgres | 5432 (内部) | 数据库 (pgvector/pg16) |
|
| postgres | 5432 (内部) | 数据库 (pgvector/pg16) |
|
||||||
| redis | 6379 (内部) | 缓存 |
|
| redis | 6379 (内部) | 缓存 |
|
||||||
| qdrant | 6333 (内部) | 向量数据库 |
|
| qdrant | 6333 (内部) | 向量数据库 |
|
||||||
|
|||||||
@@ -85,7 +85,7 @@ HOST_EXEC_MAX_TIMEOUT=300
|
|||||||
|
|
||||||
## 验证
|
## 验证
|
||||||
|
|
||||||
用 DevTools 或 API 测试:
|
用 ethend 或 API 测试:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
# 通过 API 发送消息,让昔涟使用 os_exec
|
# 通过 API 发送消息,让昔涟使用 os_exec
|
||||||
|
|||||||
+28
-28
@@ -1,15 +1,15 @@
|
|||||||
@echo off
|
@echo off
|
||||||
setlocal enabledelayedexpansion
|
setlocal enabledelayedexpansion
|
||||||
:: ========================================
|
:: ========================================
|
||||||
:: Cyrene DevTools CLI (Windows CMD)
|
:: Cyrene ethend CLI (Windows CMD)
|
||||||
:: Usage: devtools.bat [command] [options]
|
:: Usage: ethend.bat [command] [options]
|
||||||
:: ========================================
|
:: ========================================
|
||||||
|
|
||||||
set "SCRIPT_DIR=%~dp0"
|
set "SCRIPT_DIR=%~dp0"
|
||||||
set "DEVTOOLS_DIR=%SCRIPT_DIR%devtools"
|
set "ETHEND_DIR=%SCRIPT_DIR%ethend"
|
||||||
set "ROOT=%SCRIPT_DIR%"
|
set "ROOT=%SCRIPT_DIR%"
|
||||||
if "%DEVTOOLS_PORT%"=="" (set PORT=9090) else (set PORT=%DEVTOOLS_PORT%)
|
if "%ETHEND_PORT%"=="" (set PORT=9090) else (set PORT=%ETHEND_PORT%)
|
||||||
set "LOG_DIR=%DEVTOOLS_DIR%\logs"
|
set "LOG_DIR=%ETHEND_DIR%\logs"
|
||||||
set "LOG_FILE=%LOG_DIR%\sh.log"
|
set "LOG_FILE=%LOG_DIR%\sh.log"
|
||||||
set "DB_COMPOSE_FILE=%ROOT%docker-compose.dev.db.yml"
|
set "DB_COMPOSE_FILE=%ROOT%docker-compose.dev.db.yml"
|
||||||
|
|
||||||
@@ -34,15 +34,15 @@ goto :help
|
|||||||
|
|
||||||
:: ==========================================
|
:: ==========================================
|
||||||
:help
|
:help
|
||||||
echo Cyrene DevTools - Development Management Tool
|
echo Cyrene ethend - Development Management Tool
|
||||||
echo.
|
echo.
|
||||||
echo Usage: devtools.bat [command] [options]
|
echo Usage: ethend.bat [command] [options]
|
||||||
echo.
|
echo.
|
||||||
echo Commands:
|
echo Commands:
|
||||||
echo start Start DevTools console (default)
|
echo start Start ethend console (default)
|
||||||
echo start --build Build all services before start
|
echo start --build Build all services before start
|
||||||
echo start --fresh Force restart all services before start
|
echo start --fresh Force restart all services before start
|
||||||
echo stop Stop DevTools console
|
echo stop Stop ethend console
|
||||||
echo status Show all service status
|
echo status Show all service status
|
||||||
echo logs [service] View service logs (default: last 20 lines)
|
echo logs [service] View service logs (default: last 20 lines)
|
||||||
echo build [service] Build service(s) (omit to build all)
|
echo build [service] Build service(s) (omit to build all)
|
||||||
@@ -56,12 +56,12 @@ echo --build Build all backend services before start
|
|||||||
echo --fresh Force restart all services before start
|
echo --fresh Force restart all services before start
|
||||||
echo.
|
echo.
|
||||||
echo Examples:
|
echo Examples:
|
||||||
echo devtools.bat Quick start
|
echo ethend.bat Quick start
|
||||||
echo devtools.bat start --build Build and start
|
echo ethend.bat start --build Build and start
|
||||||
echo devtools.bat start --fresh Fresh restart
|
echo ethend.bat start --fresh Fresh restart
|
||||||
echo devtools.bat logs gateway View Gateway log
|
echo ethend.bat logs gateway View Gateway log
|
||||||
echo devtools.bat build ai-core Build AI-Core only
|
echo ethend.bat build ai-core Build AI-Core only
|
||||||
echo devtools.bat db:status Check database
|
echo ethend.bat db:status Check database
|
||||||
echo.
|
echo.
|
||||||
echo Web console: http://localhost:%PORT%
|
echo Web console: http://localhost:%PORT%
|
||||||
exit /b 0
|
exit /b 0
|
||||||
@@ -85,7 +85,7 @@ exit /b 1
|
|||||||
:start
|
:start
|
||||||
echo.
|
echo.
|
||||||
echo ==========================================
|
echo ==========================================
|
||||||
echo Cyrene DevTools
|
echo Cyrene ethend
|
||||||
echo ==========================================
|
echo ==========================================
|
||||||
call :check_node
|
call :check_node
|
||||||
for /f "tokens=*" %%i in ('!NODE_CMD! --version') do echo Node.js: %%i
|
for /f "tokens=*" %%i in ('!NODE_CMD! --version') do echo Node.js: %%i
|
||||||
@@ -117,7 +117,7 @@ if %DO_FRESH%==1 (
|
|||||||
curl -s -o nul "http://localhost:%PORT%/api/health" 2>nul
|
curl -s -o nul "http://localhost:%PORT%/api/health" 2>nul
|
||||||
if %ERRORLEVEL%==0 (
|
if %ERRORLEVEL%==0 (
|
||||||
echo.
|
echo.
|
||||||
echo [OK] DevTools already running: http://localhost:%PORT%
|
echo [OK] ethend already running: http://localhost:%PORT%
|
||||||
echo API: http://localhost:%PORT%/api/health
|
echo API: http://localhost:%PORT%/api/health
|
||||||
exit /b 0
|
exit /b 0
|
||||||
)
|
)
|
||||||
@@ -129,7 +129,7 @@ for /f "tokens=5" %%a in ('netstat -ano ^| findstr /R ":%PORT% " ^| findstr "LIS
|
|||||||
timeout /t 1 /nobreak >nul
|
timeout /t 1 /nobreak >nul
|
||||||
)
|
)
|
||||||
|
|
||||||
cd /d "%DEVTOOLS_DIR%"
|
cd /d "%ETHEND_DIR%"
|
||||||
|
|
||||||
:: Install dependencies
|
:: Install dependencies
|
||||||
if not exist "node_modules\" (
|
if not exist "node_modules\" (
|
||||||
@@ -141,16 +141,16 @@ if not exist "node_modules\" (
|
|||||||
if not exist "%LOG_DIR%" mkdir "%LOG_DIR%"
|
if not exist "%LOG_DIR%" mkdir "%LOG_DIR%"
|
||||||
|
|
||||||
echo.
|
echo.
|
||||||
echo [INFO] Starting DevTools on port %PORT%
|
echo [INFO] Starting ethend on port %PORT%
|
||||||
echo Web UI: http://localhost:%PORT%
|
echo Web UI: http://localhost:%PORT%
|
||||||
echo API: http://localhost:%PORT%/api/health
|
echo API: http://localhost:%PORT%/api/health
|
||||||
echo WebSocket: ws://localhost:%PORT%/ws
|
echo WebSocket: ws://localhost:%PORT%/ws
|
||||||
echo.
|
echo.
|
||||||
|
|
||||||
start "Cyrene-DevTools" /B !NODE_CMD! src\index.js 1>>"%LOG_FILE%" 2>&1
|
start "Cyrene-ethend" /B !NODE_CMD! src\index.js 1>>"%LOG_FILE%" 2>&1
|
||||||
|
|
||||||
:: Health check (up to 30s)
|
:: Health check (up to 30s)
|
||||||
echo [INFO] Waiting for DevTools to be ready...
|
echo [INFO] Waiting for ethend to be ready...
|
||||||
set MAX_WAIT=30
|
set MAX_WAIT=30
|
||||||
set WAITED=0
|
set WAITED=0
|
||||||
:health_loop
|
:health_loop
|
||||||
@@ -159,7 +159,7 @@ powershell -Command "try { (Invoke-WebRequest 'http://localhost:%PORT%/api/healt
|
|||||||
if %ERRORLEVEL%==0 (
|
if %ERRORLEVEL%==0 (
|
||||||
echo.
|
echo.
|
||||||
echo ==========================================
|
echo ==========================================
|
||||||
echo DevTools is ready!
|
echo ethend is ready!
|
||||||
echo Console: http://localhost:%PORT%
|
echo Console: http://localhost:%PORT%
|
||||||
echo Log: %LOG_FILE%
|
echo Log: %LOG_FILE%
|
||||||
echo ==========================================
|
echo ==========================================
|
||||||
@@ -179,22 +179,22 @@ exit /b 0
|
|||||||
:: ==========================================
|
:: ==========================================
|
||||||
:stop
|
:stop
|
||||||
for /f "tokens=5" %%a in ('netstat -ano ^| findstr /R ":%PORT% " ^| findstr "LISTENING"') do (
|
for /f "tokens=5" %%a in ('netstat -ano ^| findstr /R ":%PORT% " ^| findstr "LISTENING"') do (
|
||||||
echo [INFO] Stopping DevTools (PID: %%a)...
|
echo [INFO] Stopping ethend (PID: %%a)...
|
||||||
taskkill /PID %%a /F >nul 2>&1
|
taskkill /PID %%a /F >nul 2>&1
|
||||||
echo [OK] DevTools stopped
|
echo [OK] ethend stopped
|
||||||
exit /b 0
|
exit /b 0
|
||||||
)
|
)
|
||||||
echo [INFO] DevTools is not running
|
echo [INFO] ethend is not running
|
||||||
exit /b 0
|
exit /b 0
|
||||||
|
|
||||||
:: ==========================================
|
:: ==========================================
|
||||||
:status
|
:status
|
||||||
curl -s -o nul "http://localhost:%PORT%/api/health" 2>nul
|
curl -s -o nul "http://localhost:%PORT%/api/health" 2>nul
|
||||||
if %ERRORLEVEL% neq 0 (
|
if %ERRORLEVEL% neq 0 (
|
||||||
echo [ERROR] DevTools is offline
|
echo [ERROR] ethend is offline
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
echo [OK] DevTools online
|
echo [OK] ethend online
|
||||||
echo.
|
echo.
|
||||||
echo Service Status:
|
echo Service Status:
|
||||||
curl -s "http://localhost:%PORT%/api/services" 2>nul | !NODE_CMD! -e "const d=require('fs').readFileSync(0,'utf-8');const s=JSON.parse(d);for(const[k,v]of Object.entries(s)){const icon=v.status==='running'?'+':' ';const pid=v.pid?' (PID:'+v.pid+')':'';const upt=v.uptime?' uptime:'+Math.round(v.uptime/1000)+'s':'';console.log(' ['+icon+'] '+v.name.padEnd(18)+v.status+pid+upt);}" 2>nul
|
curl -s "http://localhost:%PORT%/api/services" 2>nul | !NODE_CMD! -e "const d=require('fs').readFileSync(0,'utf-8');const s=JSON.parse(d);for(const[k,v]of Object.entries(s)){const icon=v.status==='running'?'+':' ';const pid=v.pid?' (PID:'+v.pid+')':'';const upt=v.uptime?' uptime:'+Math.round(v.uptime/1000)+'s':'';console.log(' ['+icon+'] '+v.name.padEnd(18)+v.status+pid+upt);}" 2>nul
|
||||||
@@ -208,7 +208,7 @@ exit /b 0
|
|||||||
set SVC_ID=%2
|
set SVC_ID=%2
|
||||||
set LINES=%3
|
set LINES=%3
|
||||||
if "%SVC_ID%"=="" (
|
if "%SVC_ID%"=="" (
|
||||||
echo Usage: devtools.bat logs ^<service-id^> [lines]
|
echo Usage: ethend.bat logs ^<service-id^> [lines]
|
||||||
echo Available: gateway, ai-core, memory-service, tool-engine, voice-service, iot-debug-service, plugin-manager, platform-bridge, frontend
|
echo Available: gateway, ai-core, memory-service, tool-engine, voice-service, iot-debug-service, plugin-manager, platform-bridge, frontend
|
||||||
exit /b 1
|
exit /b 1
|
||||||
)
|
)
|
||||||
+37
-37
@@ -1,15 +1,15 @@
|
|||||||
#!/bin/bash
|
#!/bin/bash
|
||||||
# ========================================
|
# ========================================
|
||||||
# Cyrene DevTools 启动脚本
|
# Cyrene ethend 启动脚本
|
||||||
# 管理开发环境: 数据库 / 服务编译 / DevTools 控制台
|
# 管理开发环境: 数据库 / 服务编译 / ethend 控制台
|
||||||
# ========================================
|
# ========================================
|
||||||
set -e
|
set -e
|
||||||
|
|
||||||
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
|
||||||
DEVTOOLS_DIR="$SCRIPT_DIR/devtools"
|
ETHEND_DIR="$SCRIPT_DIR/ethend"
|
||||||
ROOT="$SCRIPT_DIR"
|
ROOT="$SCRIPT_DIR"
|
||||||
PORT="${DEVTOOLS_PORT:-9090}"
|
PORT="${ETHEND_PORT:-9090}"
|
||||||
LOG_DIR="$DEVTOOLS_DIR/logs"
|
LOG_DIR="$ETHEND_DIR/logs"
|
||||||
LOG_FILE="$LOG_DIR/sh.log"
|
LOG_FILE="$LOG_DIR/sh.log"
|
||||||
|
|
||||||
# 颜色
|
# 颜色
|
||||||
@@ -28,16 +28,16 @@ esac
|
|||||||
|
|
||||||
# ========== 帮助 ==========
|
# ========== 帮助 ==========
|
||||||
show_help() {
|
show_help() {
|
||||||
echo -e "${CYAN}Cyrene DevTools${NC} — 开发环境管理工具"
|
echo -e "${CYAN}Cyrene ethend${NC} — 开发环境管理工具"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}用法:${NC} ./devtools.sh [命令] [选项]"
|
echo -e "${BOLD}用法:${NC} ./ethend.sh [命令] [选项]"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}命令:${NC}"
|
echo -e "${BOLD}命令:${NC}"
|
||||||
echo " (无参数) 启动 DevTools 控制台 (默认)"
|
echo " (无参数) 启动 ethend 控制台 (默认)"
|
||||||
echo " start 启动 DevTools 控制台"
|
echo " start 启动 ethend 控制台"
|
||||||
echo " start --fresh 强制重启全部后端服务后启动"
|
echo " start --fresh 强制重启全部后端服务后启动"
|
||||||
echo " start --build 编译全部服务后启动"
|
echo " start --build 编译全部服务后启动"
|
||||||
echo " stop 停止 DevTools 控制台"
|
echo " stop 停止 ethend 控制台"
|
||||||
echo " status 查看所有服务状态"
|
echo " status 查看所有服务状态"
|
||||||
echo " logs [服务ID] 查看服务日志 (默认显示最近 20 行)"
|
echo " logs [服务ID] 查看服务日志 (默认显示最近 20 行)"
|
||||||
echo " build [服务ID] 编译服务 (不指定则编译全部)"
|
echo " build [服务ID] 编译服务 (不指定则编译全部)"
|
||||||
@@ -47,17 +47,17 @@ show_help() {
|
|||||||
echo " help 显示此帮助"
|
echo " help 显示此帮助"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}选项:${NC}"
|
echo -e "${BOLD}选项:${NC}"
|
||||||
echo " --port, -p <端口> 指定 DevTools 端口 (默认: 9090)"
|
echo " --port, -p <端口> 指定 ethend 端口 (默认: 9090)"
|
||||||
echo " --fresh 启动前强制重启全部后端服务"
|
echo " --fresh 启动前强制重启全部后端服务"
|
||||||
echo " --build 启动前编译全部服务"
|
echo " --build 启动前编译全部服务"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}示例:${NC}"
|
echo -e "${BOLD}示例:${NC}"
|
||||||
echo " ./devtools.sh # 快速启动"
|
echo " ./ethend.sh # 快速启动"
|
||||||
echo " ./devtools.sh start --build # 编译后启动"
|
echo " ./ethend.sh start --build # 编译后启动"
|
||||||
echo " ./devtools.sh start --fresh # 全新重启"
|
echo " ./ethend.sh start --fresh # 全新重启"
|
||||||
echo " ./devtools.sh logs gateway # 查看 Gateway 日志"
|
echo " ./ethend.sh logs gateway # 查看 Gateway 日志"
|
||||||
echo " ./devtools.sh build ai-core # 仅编译 AI-Core"
|
echo " ./ethend.sh build ai-core # 仅编译 AI-Core"
|
||||||
echo " ./devtools.sh db:status # 检查数据库"
|
echo " ./ethend.sh db:status # 检查数据库"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${BOLD}Web 控制台:${NC} http://localhost:$PORT"
|
echo -e "${BOLD}Web 控制台:${NC} http://localhost:$PORT"
|
||||||
}
|
}
|
||||||
@@ -248,8 +248,8 @@ show_logs() {
|
|||||||
tail -n "$lines" "$log_path"
|
tail -n "$lines" "$log_path"
|
||||||
}
|
}
|
||||||
|
|
||||||
# ========== 启动 DevTools ==========
|
# ========== 启动 ethend ==========
|
||||||
start_devtools() {
|
start_ethend() {
|
||||||
local do_build=false
|
local do_build=false
|
||||||
local do_fresh=false
|
local do_fresh=false
|
||||||
|
|
||||||
@@ -265,7 +265,7 @@ start_devtools() {
|
|||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
echo -e "${CYAN} Cyrene DevTools${NC}"
|
echo -e "${CYAN} Cyrene ethend${NC}"
|
||||||
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
echo -e "${CYAN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
|
|
||||||
# 依赖检查
|
# 依赖检查
|
||||||
@@ -291,9 +291,9 @@ start_devtools() {
|
|||||||
|
|
||||||
# 检查并释放端口
|
# 检查并释放端口
|
||||||
if port_in_use "$PORT"; then
|
if port_in_use "$PORT"; then
|
||||||
# 检查是否是已有 DevTools 实例
|
# 检查是否是已有 ethend 实例
|
||||||
if curl -s -o /dev/null "http://localhost:$PORT/api/health" 2>/dev/null; then
|
if curl -s -o /dev/null "http://localhost:$PORT/api/health" 2>/dev/null; then
|
||||||
echo -e "${GREEN}✓ DevTools 已在运行: http://localhost:$PORT${NC}"
|
echo -e "${GREEN}✓ ethend 已在运行: http://localhost:$PORT${NC}"
|
||||||
echo -e "${CYAN} API: http://localhost:$PORT/api/health${NC}"
|
echo -e "${CYAN} API: http://localhost:$PORT/api/health${NC}"
|
||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
@@ -301,8 +301,8 @@ start_devtools() {
|
|||||||
kill_port "$PORT"
|
kill_port "$PORT"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# 切换到 devtools 目录
|
# 切换到 ethend 目录
|
||||||
cd "$DEVTOOLS_DIR"
|
cd "$ETHEND_DIR"
|
||||||
|
|
||||||
# 安装依赖
|
# 安装依赖
|
||||||
if [ ! -d "node_modules" ] || [ ! -f "node_modules/.package-lock.json" ]; then
|
if [ ! -d "node_modules" ] || [ ! -f "node_modules/.package-lock.json" ]; then
|
||||||
@@ -314,14 +314,14 @@ start_devtools() {
|
|||||||
mkdir -p "$LOG_DIR"
|
mkdir -p "$LOG_DIR"
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}启动 DevTools 服务器 (端口: $PORT)...${NC}"
|
echo -e "${GREEN}启动 ethend 服务器 (端口: $PORT)...${NC}"
|
||||||
echo -e "${CYAN} Web 控制台: http://localhost:$PORT${NC}"
|
echo -e "${CYAN} Web 控制台: http://localhost:$PORT${NC}"
|
||||||
echo -e "${CYAN} API: http://localhost:$PORT/api/health${NC}"
|
echo -e "${CYAN} API: http://localhost:$PORT/api/health${NC}"
|
||||||
echo -e "${CYAN} WebSocket: ws://localhost:$PORT/ws${NC}"
|
echo -e "${CYAN} WebSocket: ws://localhost:$PORT/ws${NC}"
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${YELLOW}正在后台启动...${NC}"
|
echo -e "${YELLOW}正在后台启动...${NC}"
|
||||||
|
|
||||||
# 后台启动 DevTools
|
# 后台启动 ethend
|
||||||
nohup node src/index.js > "$LOG_FILE" 2>&1 &
|
nohup node src/index.js > "$LOG_FILE" 2>&1 &
|
||||||
local pid=$!
|
local pid=$!
|
||||||
cd "$ROOT"
|
cd "$ROOT"
|
||||||
@@ -331,7 +331,7 @@ start_devtools() {
|
|||||||
if health_check "http://localhost:$PORT/api/health" 30; then
|
if health_check "http://localhost:$PORT/api/health" 30; then
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
echo -e "${GREEN}━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━${NC}"
|
||||||
echo -e "${GREEN} DevTools 已启动!${NC}"
|
echo -e "${GREEN} ethend 已启动!${NC}"
|
||||||
echo -e "${GREEN} PID: ${pid}${NC}"
|
echo -e "${GREEN} PID: ${pid}${NC}"
|
||||||
echo -e "${GREEN} 控制台: http://localhost:$PORT${NC}"
|
echo -e "${GREEN} 控制台: http://localhost:$PORT${NC}"
|
||||||
echo -e "${GREEN} 日志: ${LOG_FILE}${NC}"
|
echo -e "${GREEN} 日志: ${LOG_FILE}${NC}"
|
||||||
@@ -356,25 +356,25 @@ start_devtools() {
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ========== 停止 DevTools ==========
|
# ========== 停止 ethend ==========
|
||||||
stop_devtools() {
|
stop_ethend() {
|
||||||
if port_in_use "$PORT"; then
|
if port_in_use "$PORT"; then
|
||||||
echo -e "${CYAN}停止 DevTools...${NC}"
|
echo -e "${CYAN}停止 ethend...${NC}"
|
||||||
if $IS_WIN; then
|
if $IS_WIN; then
|
||||||
kill_port "$PORT"
|
kill_port "$PORT"
|
||||||
else
|
else
|
||||||
fuser -k "$PORT/tcp" 2>/dev/null || true
|
fuser -k "$PORT/tcp" 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
echo -e "${GREEN}✓ DevTools 已停止${NC}"
|
echo -e "${GREEN}✓ ethend 已停止${NC}"
|
||||||
else
|
else
|
||||||
echo -e "${YELLOW}DevTools 未在运行${NC}"
|
echo -e "${YELLOW}ethend 未在运行${NC}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
# ========== 查看状态 ==========
|
# ========== 查看状态 ==========
|
||||||
show_status() {
|
show_status() {
|
||||||
if curl -s -o /dev/null "http://localhost:$PORT/api/health" 2>/dev/null; then
|
if curl -s -o /dev/null "http://localhost:$PORT/api/health" 2>/dev/null; then
|
||||||
echo -e "${GREEN}✓ DevTools 在线${NC}"
|
echo -e "${GREEN}✓ ethend 在线${NC}"
|
||||||
|
|
||||||
# 获取服务状态
|
# 获取服务状态
|
||||||
local status_json=$(curl -s "http://localhost:$PORT/api/services" 2>/dev/null)
|
local status_json=$(curl -s "http://localhost:$PORT/api/services" 2>/dev/null)
|
||||||
@@ -401,7 +401,7 @@ show_status() {
|
|||||||
echo ""
|
echo ""
|
||||||
db_status
|
db_status
|
||||||
else
|
else
|
||||||
echo -e "${RED}✗ DevTools 离线${NC}"
|
echo -e "${RED}✗ ethend 离线${NC}"
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -414,17 +414,17 @@ case "$CMD" in
|
|||||||
show_help
|
show_help
|
||||||
;;
|
;;
|
||||||
start|"")
|
start|"")
|
||||||
start_devtools "$@"
|
start_ethend "$@"
|
||||||
;;
|
;;
|
||||||
stop)
|
stop)
|
||||||
stop_devtools
|
stop_ethend
|
||||||
;;
|
;;
|
||||||
status)
|
status)
|
||||||
show_status
|
show_status
|
||||||
;;
|
;;
|
||||||
logs)
|
logs)
|
||||||
if [ -z "$1" ]; then
|
if [ -z "$1" ]; then
|
||||||
echo -e "${YELLOW}用法: ./devtools.sh logs <服务ID>${NC}"
|
echo -e "${YELLOW}用法: ./ethend.sh logs <服务ID>${NC}"
|
||||||
echo "可用服务: gateway, ai-core, memory-service, tool-engine, voice-service, iot-debug-service, plugin-manager, platform-bridge, frontend"
|
echo "可用服务: gateway, ai-core, memory-service, tool-engine, voice-service, iot-debug-service, plugin-manager, platform-bridge, frontend"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
@@ -8,8 +8,8 @@ RUN npm ci --omit=dev
|
|||||||
COPY src/ ./src/
|
COPY src/ ./src/
|
||||||
COPY public/ ./public/
|
COPY public/ ./public/
|
||||||
|
|
||||||
ENV DEVTOOLS_PORT=9090
|
ENV ETHEND_PORT=9090
|
||||||
ENV NODE_ENV=development
|
ENV NODE_ENV=production
|
||||||
|
|
||||||
EXPOSE 9090
|
EXPOSE 9090
|
||||||
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "cyrene-devtools",
|
"name": "cyrene-ethend",
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
"description": "Cyrene AI 开发调试工具 - 服务管理、日志监控、性能分析",
|
"description": "Cyrene AI 高级管理控制台 - 服务管理、日志监控、性能分析",
|
||||||
"private": true,
|
"private": true,
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Cyrene DevTools</title>
|
<title>Cyrene ethend</title>
|
||||||
<style>
|
<style>
|
||||||
/* ========== CSS Variables (深色主题) ========== */
|
/* ========== CSS Variables (深色主题) ========== */
|
||||||
:root {
|
:root {
|
||||||
@@ -747,7 +747,7 @@ input[type="range"] { accent-color: var(--accent); padding: 0; }
|
|||||||
<!-- ========== 侧边栏 ========== -->
|
<!-- ========== 侧边栏 ========== -->
|
||||||
<aside id="sidebar">
|
<aside id="sidebar">
|
||||||
<div class="sidebar-header">
|
<div class="sidebar-header">
|
||||||
<span class="sidebar-title">🛠️ DevTools</span>
|
<span class="sidebar-title">ethend</span>
|
||||||
<button id="toggle-sidebar" title="折叠侧边栏">☰</button>
|
<button id="toggle-sidebar" title="折叠侧边栏">☰</button>
|
||||||
</div>
|
</div>
|
||||||
<nav class="sidebar-nav">
|
<nav class="sidebar-nav">
|
||||||
@@ -1319,7 +1319,7 @@ async function renderDashboard() {
|
|||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="stat-card orange">' +
|
'<div class="stat-card orange">' +
|
||||||
'<div class="stat-value" id="stat-heap">' + (data.system?.heapUsedMB ?? '—') + ' MB</div>' +
|
'<div class="stat-value" id="stat-heap">' + (data.system?.heapUsedMB ?? '—') + ' MB</div>' +
|
||||||
'<div class="stat-label">DevTools 内存</div>' +
|
'<div class="stat-label">ethend 内存</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
|
|
||||||
@@ -1331,7 +1331,7 @@ async function renderDashboard() {
|
|||||||
'<button class="btn btn-sm btn-accent" onclick="svcAction(\'start-all\')">▶ 一键启动</button>' +
|
'<button class="btn btn-sm btn-accent" onclick="svcAction(\'start-all\')">▶ 一键启动</button>' +
|
||||||
'<button class="btn btn-sm" onclick="svcAction(\'start-all-fresh\')">🔄 强制重启全部</button>' +
|
'<button class="btn btn-sm" onclick="svcAction(\'start-all-fresh\')">🔄 强制重启全部</button>' +
|
||||||
'<button class="btn btn-sm btn-red" onclick="svcAction(\'stop-all\')">⏹ 全部停止</button>' +
|
'<button class="btn btn-sm btn-red" onclick="svcAction(\'stop-all\')">⏹ 全部停止</button>' +
|
||||||
'<button class="btn btn-sm" onclick="restartDevTools()" style="margin-left:8px;border-color:var(--accent);color:var(--accent)" title="重启 DevTools 自身以应用更新">🔁 重启 DevTools</button>' +
|
'<button class="btn btn-sm" onclick="restartEthend()" style="margin-left:8px;border-color:var(--accent);color:var(--accent)" title="重启 ethend 自身以应用更新">🔁 重启 ethend</button>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'</div>' +
|
'</div>' +
|
||||||
'<div class="cards-grid cards-4" id="dashboard-svc-cards"></div>' +
|
'<div class="cards-grid cards-4" id="dashboard-svc-cards"></div>' +
|
||||||
@@ -2624,11 +2624,11 @@ async function clearSvcLogs() {
|
|||||||
renderServiceLog();
|
renderServiceLog();
|
||||||
}
|
}
|
||||||
|
|
||||||
// ---- DevTools 自重启 ----
|
// ---- ethend 自重启 ----
|
||||||
async function restartDevTools() {
|
async function restartEthend() {
|
||||||
if (!confirm('确定要重启 DevTools 吗?\n\n页面将在几秒后自动刷新。')) return;
|
if (!confirm('确定要重启 ethend 吗?\n\n页面将在几秒后自动刷新。')) return;
|
||||||
try {
|
try {
|
||||||
await api('/api/devtools/restart', { method: 'POST' });
|
await api('/api/ethend/restart', { method: 'POST' });
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
// 请求可能在收到响应前就中断(因为服务已退出),这是正常的
|
// 请求可能在收到响应前就中断(因为服务已退出),这是正常的
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* 调试工具配置
|
* 管理控制台配置
|
||||||
* 定义各服务的启动参数、端口、健康检查等
|
* 定义各服务的启动参数、端口、健康检查等
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -15,7 +15,7 @@ const ROOT = path.resolve(__dirname, '../..');
|
|||||||
const isWin = os.platform() === 'win32';
|
const isWin = os.platform() === 'win32';
|
||||||
|
|
||||||
// 读取 backend/.env 文件,将值合并到 process.env(不覆盖已有的环境变量)
|
// 读取 backend/.env 文件,将值合并到 process.env(不覆盖已有的环境变量)
|
||||||
// 这样 DevTools 启动各服务时能传递用户配置的凭据
|
// 这样 ethend 启动各服务时能传递用户配置的凭据
|
||||||
function loadEnvFile() {
|
function loadEnvFile() {
|
||||||
const envPath = path.join(ROOT, 'backend', '.env');
|
const envPath = path.join(ROOT, 'backend', '.env');
|
||||||
try {
|
try {
|
||||||
@@ -53,7 +53,7 @@ function findGoBin() {
|
|||||||
|
|
||||||
const GO_BIN = findGoBin();
|
const GO_BIN = findGoBin();
|
||||||
|
|
||||||
export const DEVTOOLS_PORT = process.env.DEVTOOLS_PORT || 9090;
|
export const ETHEND_PORT = process.env.ETHEND_PORT || 9090;
|
||||||
export const LOGS_DIR = path.resolve(__dirname, '../logs');
|
export const LOGS_DIR = path.resolve(__dirname, '../logs');
|
||||||
export const GATEWAY_URL = process.env.GATEWAY_URL || 'http://localhost:8080';
|
export const GATEWAY_URL = process.env.GATEWAY_URL || 'http://localhost:8080';
|
||||||
export const PLUGIN_MANAGER_URL = process.env.PLUGIN_MANAGER_URL || 'http://localhost:8094';
|
export const PLUGIN_MANAGER_URL = process.env.PLUGIN_MANAGER_URL || 'http://localhost:8094';
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/**
|
/**
|
||||||
* Cyrene DevTools - 主入口
|
* Cyrene ethend - 主入口
|
||||||
*
|
*
|
||||||
* 提供:
|
* 提供:
|
||||||
* - REST API: 服务管理、状态查询、性能分析、健康检查代理
|
* - REST API: 服务管理、状态查询、性能分析、健康检查代理
|
||||||
@@ -17,7 +17,7 @@ import { execSync, spawn } from 'child_process';
|
|||||||
|
|
||||||
import { processManager } from './process-manager.js';
|
import { processManager } from './process-manager.js';
|
||||||
import { performanceMonitor } from './performance.js';
|
import { performanceMonitor } from './performance.js';
|
||||||
import { SERVICES, DEVTOOLS_PORT, LOGS_DIR, logFile, GATEWAY_URL, PLUGIN_MANAGER_URL, ADMIN_USERNAME, ADMIN_PASSWORD } from './config.js';
|
import { SERVICES, ETHEND_PORT, LOGS_DIR, logFile, GATEWAY_URL, PLUGIN_MANAGER_URL, ADMIN_USERNAME, ADMIN_PASSWORD } from './config.js';
|
||||||
|
|
||||||
const AI_CORE_URL = process.env.AI_CORE_URL || 'http://localhost:8081';
|
const AI_CORE_URL = process.env.AI_CORE_URL || 'http://localhost:8081';
|
||||||
const MEMORY_SERVICE_URL = process.env.MEMORY_SERVICE_URL || 'http://localhost:8091';
|
const MEMORY_SERVICE_URL = process.env.MEMORY_SERVICE_URL || 'http://localhost:8091';
|
||||||
@@ -209,15 +209,15 @@ async function proxyToAICore(path, opts = {}) {
|
|||||||
app.get('/api/health', (_req, res) => {
|
app.get('/api/health', (_req, res) => {
|
||||||
res.json({
|
res.json({
|
||||||
status: 'ok',
|
status: 'ok',
|
||||||
service: 'cyrene-devtools',
|
service: 'cyrene-ethend',
|
||||||
uptime: process.uptime(),
|
uptime: process.uptime(),
|
||||||
wsClients: wsClients.size,
|
wsClients: wsClients.size,
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
// ---- DevTools 自重启 ----
|
// ---- ethend 自重启 ----
|
||||||
app.post('/api/devtools/restart', (_req, res) => {
|
app.post('/api/ethend/restart', (_req, res) => {
|
||||||
res.json({ success: true, message: 'DevTools 正在重启...' });
|
res.json({ success: true, message: 'ethend 正在重启...' });
|
||||||
|
|
||||||
// 延迟 500ms 确保响应已发送,然后 spawn 新进程并退出
|
// 延迟 500ms 确保响应已发送,然后 spawn 新进程并退出
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
@@ -918,7 +918,7 @@ const sttLogEntries = [];
|
|||||||
const MAX_STT_LOGS = 200;
|
const MAX_STT_LOGS = 200;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 记录 STT 请求日志(devtools 自身维护,因为 voice-service 无持久化日志)
|
* 记录 STT 请求日志(ethend 自身维护,因为 voice-service 无持久化日志)
|
||||||
*/
|
*/
|
||||||
function recordSTTLog(entry) {
|
function recordSTTLog(entry) {
|
||||||
sttLogEntries.unshift(entry);
|
sttLogEntries.unshift(entry);
|
||||||
@@ -969,7 +969,7 @@ app.post('/api/voice/transcribe', async (req, res) => {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
// 构建 multipart/form-data 请求转发到 Voice-Service
|
// 构建 multipart/form-data 请求转发到 Voice-Service
|
||||||
const boundary = '----DevToolsFormBoundary' + Math.random().toString(36).slice(2);
|
const boundary = '----ethendFormBoundary' + Math.random().toString(36).slice(2);
|
||||||
const crlf = '\r\n';
|
const crlf = '\r\n';
|
||||||
const headerParts = [
|
const headerParts = [
|
||||||
'--' + boundary + crlf,
|
'--' + boundary + crlf,
|
||||||
@@ -1026,7 +1026,7 @@ app.post('/api/voice/transcribe', async (req, res) => {
|
|||||||
recordSTTLog(logEntry);
|
recordSTTLog(logEntry);
|
||||||
return res.status(voiceResp.status).json({
|
return res.status(voiceResp.status).json({
|
||||||
...voiceBody,
|
...voiceBody,
|
||||||
devtools_log_id: logEntry.id,
|
ethend_log_id: logEntry.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1045,7 +1045,7 @@ app.post('/api/voice/transcribe', async (req, res) => {
|
|||||||
recordSTTLog(logEntry);
|
recordSTTLog(logEntry);
|
||||||
return res.json({
|
return res.json({
|
||||||
...voiceBody,
|
...voiceBody,
|
||||||
devtools_log_id: logEntry.id,
|
ethend_log_id: logEntry.id,
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
const elapsedMs = Date.now() - startTime;
|
const elapsedMs = Date.now() - startTime;
|
||||||
@@ -1070,7 +1070,7 @@ app.post('/api/voice/transcribe', async (req, res) => {
|
|||||||
hint: isConnRefused
|
hint: isConnRefused
|
||||||
? 'Voice-Service 服务未启动,请先在「服务管理」面板中启动 Voice-Service'
|
? 'Voice-Service 服务未启动,请先在「服务管理」面板中启动 Voice-Service'
|
||||||
: 'Voice-Service 服务无响应,请检查网络连接和服务状态',
|
: 'Voice-Service 服务无响应,请检查网络连接和服务状态',
|
||||||
devtools_log_id: logEntry.id,
|
ethend_log_id: logEntry.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -1725,11 +1725,11 @@ performanceMonitor.start();
|
|||||||
// 确保日志目录存在
|
// 确保日志目录存在
|
||||||
fs.mkdirSync(LOGS_DIR, { recursive: true });
|
fs.mkdirSync(LOGS_DIR, { recursive: true });
|
||||||
|
|
||||||
server.listen(DEVTOOLS_PORT, () => {
|
server.listen(ETHEND_PORT, () => {
|
||||||
console.log(`🛠️ Cyrene DevTools 已启动: http://localhost:${DEVTOOLS_PORT}`);
|
console.log(`🛠️ Cyrene ethend 已启动: http://localhost:${ETHEND_PORT}`);
|
||||||
console.log(` API: http://localhost:${DEVTOOLS_PORT}/api/health`);
|
console.log(` API: http://localhost:${ETHEND_PORT}/api/health`);
|
||||||
console.log(` WebSocket: ws://localhost:${DEVTOOLS_PORT}/ws`);
|
console.log(` WebSocket: ws://localhost:${ETHEND_PORT}/ws`);
|
||||||
console.log(` Web控制台: http://localhost:${DEVTOOLS_PORT}`);
|
console.log(` Web控制台: http://localhost:${ETHEND_PORT}`);
|
||||||
console.log('');
|
console.log('');
|
||||||
console.log(' 可用服务:');
|
console.log(' 可用服务:');
|
||||||
for (const [id, svc] of Object.entries(SERVICES)) {
|
for (const [id, svc] of Object.entries(SERVICES)) {
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// 页面路由 Store — 管理当前显示的页面
|
||||||
|
|
||||||
|
import { create } from 'zustand';
|
||||||
|
|
||||||
|
export type PageId = 'chat' | 'admin-models' | 'admin-dashboard' | 'profile';
|
||||||
|
|
||||||
|
interface PageState {
|
||||||
|
currentPage: PageId;
|
||||||
|
setPage: (page: PageId) => void;
|
||||||
|
goToChat: () => void;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const usePageStore = create<PageState>((set) => ({
|
||||||
|
currentPage: 'chat',
|
||||||
|
setPage: (page) => set({ currentPage: page }),
|
||||||
|
goToChat: () => set({ currentPage: 'chat' }),
|
||||||
|
}));
|
||||||
+1
-1
@@ -55,7 +55,7 @@ tar -czf "${OUTPUT_DIR}/${ARCHIVE_NAME}" \
|
|||||||
--exclude='frontend/web/node_modules' \
|
--exclude='frontend/web/node_modules' \
|
||||||
--exclude='frontend/web/dist' \
|
--exclude='frontend/web/dist' \
|
||||||
--exclude='frontend/node_modules' \
|
--exclude='frontend/node_modules' \
|
||||||
--exclude='devtools/node_modules' \
|
--exclude='ethend/node_modules' \
|
||||||
--exclude='frontend/packages/*/node_modules' \
|
--exclude='frontend/packages/*/node_modules' \
|
||||||
--exclude='.env' \
|
--exclude='.env' \
|
||||||
--exclude='backend/.env' \
|
--exclude='backend/.env' \
|
||||||
|
|||||||
Reference in New Issue
Block a user