506 lines
14 KiB
Markdown
506 lines
14 KiB
Markdown
# Dev-Assistant
|
||
|
||
嵌入式 AI 开发助手 — 专为 admin-xy 项目设计,支持 Claude / GLM / MiniMax 多模型运行时切换。
|
||
|
||
## 架构概览
|
||
|
||
```
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ admin-xy/web (React) │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ DevAssistantMount (侧栏组件) │ │
|
||
│ │ ┌─────────────────────────────────────────────────────────┐ │ │
|
||
│ │ │ @dev-assistant/web-sdk │ │ │
|
||
│ │ │ - WebSocket 通信 │ │ │
|
||
│ │ │ - 页面上下文捕获 (选区/控制台/网络请求) │ │ │
|
||
│ │ │ - 流式响应渲染 │ │ │
|
||
│ │ │ - 工具执行确认 │ │ │
|
||
│ │ └─────────────────────────────────────────────────────────┘ │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
│ WebSocket + HTTP
|
||
▼
|
||
┌─────────────────────────────────────────────────────────────────┐
|
||
│ @dev-assistant/bridge (Node.js) │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ WebSocket 会话管理 │ │
|
||
│ │ - JWT 认证校验 (支持 HTTP 校验 / 本地解析) │ │
|
||
│ │ - 速率限制 │ │
|
||
│ │ - 上下文收集 (日志/文件/代码) │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
│ ┌─────────────────────────────────────────────────────────────┐ │
|
||
│ │ 模型路由 & Agent SDK │ │
|
||
│ │ - 多模型协议适配 (Anthropic 兼容) │ │
|
||
│ │ - 工具执行 (Read/Edit/Bash/Glob/Grep) │ │
|
||
│ │ - 流式响应处理 │ │
|
||
│ └─────────────────────────────────────────────────────────────┘ │
|
||
└─────────────────────────────────────────────────────────────────┘
|
||
│ HTTP
|
||
▼
|
||
┌────────────┴────────────┐
|
||
│ │
|
||
GLM / MiniMax Claude API
|
||
```
|
||
|
||
## 快速开始
|
||
|
||
### 前置要求
|
||
|
||
- Node.js >= 20
|
||
- admin-xy 后端服务运行在 http://localhost:9010
|
||
- AI 模型 API Key(配置后存储在 keychain 或加密文件中)
|
||
|
||
### 安装依赖
|
||
|
||
```bash
|
||
cd dev-assistant
|
||
npm install
|
||
```
|
||
|
||
### 启动开发环境
|
||
|
||
```bash
|
||
# 启动桥接服务
|
||
npm run bridge:dev
|
||
|
||
# 构建前端 SDK(admin-xy/web 集成时需要)
|
||
npm run web-sdk:build
|
||
```
|
||
|
||
桥接服务默认监听 `http://127.0.0.1:9020`,WebSocket 路径为 `/copilot`。
|
||
|
||
## 配置说明
|
||
|
||
配置文件位于 `config/dev-assistant.yaml`,启动时自动加载,支持热更新。
|
||
|
||
### 核心配置项
|
||
|
||
```yaml
|
||
# 项目信息 — 驱动 AI 系统提示
|
||
project:
|
||
name: admin-xy
|
||
description: 企业管理系统 — 用户/角色/菜单/权限管理
|
||
techStack:
|
||
- Spring Boot 3
|
||
- Java 21
|
||
- React 18
|
||
- Vite
|
||
- TypeScript
|
||
conventions:
|
||
- 分层架构(Controller → Service → Repository → Entity → DTO)
|
||
- JWT 无状态认证
|
||
- Flyway 数据库迁移
|
||
|
||
# 工作目录配置
|
||
workspace:
|
||
root: ./ # 相对于仓库根
|
||
allowWrite:
|
||
- admin-xy/** # 允许写入的路径
|
||
- dev-assistant/**
|
||
denyWrite:
|
||
- .claude/** # 禁止写入的路径
|
||
- '**/.env*'
|
||
- '**/target/**'
|
||
- '**/node_modules/**'
|
||
|
||
# 日志源配置(用于 bugfix 场景自动附加)
|
||
logs:
|
||
- id: admin-server
|
||
label: admin-xy Spring Boot
|
||
path: admin-xy/server/logs/app.log
|
||
format: logback-json # 支持 logback-json / plain / spring-default
|
||
tailLines: 500
|
||
followDurationSec: 30
|
||
|
||
# 上下文预算控制
|
||
context:
|
||
maxPromptTokens: 16000
|
||
attachAsFileThreshold: 4000 # 超过此大小作为文件附件而非内联
|
||
cacheDir: dev-assistant/.cache
|
||
console:
|
||
keepLines: 200 # 控制台保留行数
|
||
network:
|
||
keepRequests: 50 # 网络请求保留数量
|
||
captureBody: true
|
||
bodyMaxBytes: 4096
|
||
|
||
# 场景配置
|
||
scenarios:
|
||
modify:
|
||
label: 调整现有页面
|
||
requireSelection: true # 要求用户选择文本
|
||
bugfix:
|
||
label: 排查页面问题
|
||
attachErrorLogs: true # 自动附加错误日志
|
||
followJavaLogs: true
|
||
|
||
# 桥接服务配置
|
||
bridge:
|
||
port: 9020
|
||
host: 127.0.0.1 # 容器环境改为 0.0.0.0
|
||
wsPath: /copilot
|
||
origin: https://oa.xiangyuetech.cn # CORS 允许的前端 Origin
|
||
wsIdleTimeoutMs: 1800000 # 30 分钟空闲超时
|
||
maxConcurrentChats: 1
|
||
auth:
|
||
type: http # http / jwt-local / disabled
|
||
verifyUrl: http://server:9010/api/auth/me # HTTP 校验端点
|
||
requiredRole: ROLE_ADMIN
|
||
cacheTtlSec: 60
|
||
rateLimit:
|
||
chatPerMinute: 20
|
||
httpPerMinute: 120
|
||
```
|
||
|
||
### 环境变量覆盖
|
||
|
||
生产环境可通过环境变量覆盖配置:
|
||
|
||
```bash
|
||
BRIDGE_HOST=0.0.0.0 # 监听地址
|
||
BRIDGE_AUTH_VERIFY_URL=http://... # 认证校验端点
|
||
BRIDGE_AUTH_DISABLED=true # 跳过认证(仅本机开发)
|
||
BRIDGE_ORIGIN=https://... # CORS 允许的 Origin
|
||
```
|
||
|
||
## 认证机制
|
||
|
||
支持三种认证模式:
|
||
|
||
### 1. HTTP 远程校验(默认)
|
||
|
||
桥接服务调用后端 `/api/auth/me` 接口验证 JWT 有效性。
|
||
|
||
```yaml
|
||
bridge:
|
||
auth:
|
||
type: http
|
||
verifyUrl: http://server:9010/api/auth/me
|
||
requiredRole: ROLE_ADMIN
|
||
```
|
||
|
||
### 2. JWT 本地解析
|
||
|
||
无需网络调用,本地解析 JWT 验证用户和角色。
|
||
|
||
```yaml
|
||
bridge:
|
||
auth:
|
||
type: jwt-local
|
||
jwtSecret: ${JWT_SECRET} # 从环境变量读取
|
||
jwtIssuer: admin-xy
|
||
jwtAudience: admin-xy-web
|
||
jwtUsernameClaim: sub
|
||
jwtRolesClaim: roles
|
||
requiredRole: ROLE_ADMIN
|
||
```
|
||
|
||
### 3. 禁用认证(仅开发环境)
|
||
|
||
```yaml
|
||
bridge:
|
||
auth:
|
||
type: disabled
|
||
```
|
||
|
||
或通过环境变量:
|
||
|
||
```bash
|
||
BRIDGE_AUTH_DISABLED=true npm run bridge:dev
|
||
```
|
||
|
||
## 模型管理
|
||
|
||
模型配置和 API Key 通过 Web SDK 动态管理,存储在 `dev-assistant/.cache/` 目录(gitignore)。
|
||
|
||
### 支持的模型
|
||
|
||
- **Claude** (Anthropic) - 原生支持
|
||
- **GLM** (智谱 AI) - 通过协议适配器
|
||
- **MiniMax** - 通过协议适配器
|
||
|
||
### 管理接口
|
||
|
||
```http
|
||
# 获取模型列表
|
||
GET /api/models
|
||
|
||
# 设置活跃模型
|
||
PUT /api/models/active
|
||
Body: { "provider": "claude", "model": "claude-sonnet-4-6" }
|
||
|
||
# 更新 API Key
|
||
PUT /api/models/:provider/key
|
||
Body: { "apiKey": "sk-..." }
|
||
```
|
||
|
||
## WebSocket 协议
|
||
|
||
### 客户端 → 服务端
|
||
|
||
```typescript
|
||
// 发起对话
|
||
{
|
||
type: 'chat',
|
||
requestId: 'uuid',
|
||
scenario: 'bugfix',
|
||
prompt: '修复用户登录失败的问题',
|
||
context: {
|
||
url: '/login',
|
||
selection: '选中的代码',
|
||
console: [...],
|
||
network: [...]
|
||
}
|
||
}
|
||
|
||
// 中止对话
|
||
{ type: 'abort', requestId: 'uuid' }
|
||
|
||
// 工具执行决策
|
||
{
|
||
type: 'tool_decision',
|
||
requestId: 'uuid',
|
||
toolUseId: 'tool-xxx',
|
||
decision: 'allow', // 或 'deny'
|
||
message: '允许此操作'
|
||
}
|
||
```
|
||
|
||
### 服务端 → 客户端
|
||
|
||
```typescript
|
||
// 会话开始
|
||
{
|
||
type: 'session_started',
|
||
serverTime: 1714567890123,
|
||
active: { name: 'Claude', model: 'claude-sonnet-4-6' }
|
||
}
|
||
|
||
// 消息开始
|
||
{
|
||
type: 'message_started',
|
||
requestId: 'uuid',
|
||
provider: 'claude',
|
||
model: 'claude-sonnet-4-6'
|
||
}
|
||
|
||
// 文本流式输出
|
||
{
|
||
type: 'text_delta',
|
||
requestId: 'uuid',
|
||
text: '根据日志分析...'
|
||
}
|
||
|
||
// 工具使用开始
|
||
{
|
||
type: 'tool_use_started',
|
||
requestId: 'uuid',
|
||
toolUseId: 'tool-xxx',
|
||
name: 'Read'
|
||
}
|
||
|
||
// 工具执行请求(需用户确认)
|
||
{
|
||
type: 'tool_request',
|
||
requestId: 'uuid',
|
||
toolUseId: 'tool-xxx',
|
||
name: 'Bash',
|
||
input: { command: 'npm install' },
|
||
destructive: false
|
||
}
|
||
|
||
// 消息完成
|
||
{
|
||
type: 'message_done',
|
||
requestId: 'uuid',
|
||
stopReason: 'end_turn',
|
||
outputTokens: 1234
|
||
}
|
||
```
|
||
|
||
## 集成到 admin-xy
|
||
|
||
### 前端集成
|
||
|
||
```tsx
|
||
// admin-xy/web/src/integrations/dev-assistant.tsx
|
||
import { useEffect, useRef } from 'react';
|
||
import {
|
||
ADMIN_ROLE,
|
||
mountDevAssistant,
|
||
type DevAssistantHandle,
|
||
} from '@dev-assistant/web-sdk';
|
||
import '@dev-assistant/web-sdk/styles.css';
|
||
import { useAuthStore } from '@/stores/auth-store';
|
||
|
||
export function DevAssistantMount(): null {
|
||
const user = useAuthStore((s) => s.user);
|
||
const handleRef = useRef<DevAssistantHandle | null>(null);
|
||
|
||
useEffect(() => {
|
||
const isAdmin = !!user?.roles?.includes(ADMIN_ROLE);
|
||
if (!isAdmin) {
|
||
handleRef.current?.unmount();
|
||
return;
|
||
}
|
||
if (handleRef.current) return;
|
||
|
||
const token = useAuthStore.getState().token ?? undefined;
|
||
handleRef.current = mountDevAssistant({
|
||
bridgeHttpUrl: 'http://localhost:9020',
|
||
bridgeWsUrl: 'ws://localhost:9020/copilot',
|
||
roles: user?.roles ?? [],
|
||
userIdentifier: user?.username,
|
||
token,
|
||
});
|
||
|
||
return () => {
|
||
handleRef.current?.unmount();
|
||
handleRef.current = null;
|
||
};
|
||
}, [user]);
|
||
|
||
return null;
|
||
}
|
||
```
|
||
|
||
### 后端日志集成
|
||
|
||
在 Spring Boot 中添加 `RequestIdFilter` 和 `MdcUserFilter`,将请求 ID 和用户信息写入 MDC:
|
||
|
||
```java
|
||
@Component
|
||
public class RequestIdFilter implements Filter {
|
||
@Override
|
||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) {
|
||
String requestId = ((HttpServletRequest) request).getHeader("X-Request-Id");
|
||
MDC.put("requestId", requestId != null ? requestId : UUID.randomUUID().toString());
|
||
try {
|
||
chain.doFilter(request, response);
|
||
} finally {
|
||
MDC.remove("requestId");
|
||
}
|
||
}
|
||
}
|
||
```
|
||
|
||
配置 logback JSON 输出,使日志包含 MDC 字段,便于 bridge 关联查询。
|
||
|
||
## 日志查询 API
|
||
|
||
```http
|
||
# 获取日志源列表
|
||
GET /api/logs/sources
|
||
|
||
# 读取单个日志源尾部
|
||
GET /api/logs/admin-server?tailLines=100&minLevel=WARN&contains=ERROR
|
||
|
||
# 聚合读取所有日志源
|
||
GET /api/logs?priority=high&minLevel=ERROR
|
||
|
||
# 按 RequestId 关联查询
|
||
GET /api/logs?requestId=abc-123-def
|
||
```
|
||
|
||
## 编程式 API
|
||
|
||
### 启动桥接服务
|
||
|
||
```typescript
|
||
import { startBridge } from '@dev-assistant/bridge';
|
||
|
||
const handle = await startBridge({
|
||
configPath: './my-config.yaml',
|
||
configOverrides: {
|
||
bridge: { port: 9021 }
|
||
},
|
||
// 自定义认证验证器
|
||
verifier: {
|
||
async verify(token) {
|
||
// 返回 { username, roles, isAdmin } 或 null
|
||
}
|
||
},
|
||
onReady: ({ port, host }) => {
|
||
console.log(`Bridge listening on ${host}:${port}`);
|
||
}
|
||
});
|
||
|
||
// 关闭服务
|
||
await handle.close();
|
||
```
|
||
|
||
### CLI 启动
|
||
|
||
```bash
|
||
npx dev-assistant-bridge --config ./dev-assistant.yaml
|
||
```
|
||
|
||
## Docker 部署
|
||
|
||
```yaml
|
||
# docker-compose.yml
|
||
services:
|
||
dev-assistant:
|
||
image: dev-assistant:latest
|
||
ports:
|
||
- "9020:9020"
|
||
environment:
|
||
- BRIDGE_HOST=0.0.0.0
|
||
- BRIDGE_AUTH_VERIFY_URL=http://admin-server:9010/api/auth/me
|
||
- BRIDGE_ORIGIN=https://oa.xiangyuetech.cn
|
||
volumes:
|
||
- ./config/dev-assistant.yaml:/app/dev-assistant.yaml
|
||
- ./dev-assistant-data:/app/dev-assistant-data
|
||
depends_on:
|
||
- admin-server
|
||
```
|
||
|
||
## 安全注意事项
|
||
|
||
1. **API Key 管理**:禁止将 API Key 写入配置文件或代码,使用 keychain 或加密文件存储
|
||
2. **认证配置**:生产环境必须启用认证(type: http 或 jwt-local)
|
||
3. **路径限制**:配置 `workspace.denyWrite` 保护敏感目录(.env、node_modules、.claude)
|
||
4. **速率限制**:根据实际使用调整 `rateLimit` 防止滥用
|
||
5. **CORS 配置**:`bridge.origin` 严格限制允许的前端来源
|
||
|
||
## 故障排查
|
||
|
||
### 连接失败
|
||
|
||
1. 检查桥接服务是否启动:`curl http://localhost:9020/health`
|
||
2. 验证 CORS 配置:`bridge.origin` 是否包含前端域名
|
||
3. 确认认证配置是否正确
|
||
|
||
### 认证失败
|
||
|
||
1. 检查 JWT 是否有效:通过后端 `/api/auth/me` 验证
|
||
2. 确认用户角色包含 `requiredRole`(默认 ROLE_ADMIN)
|
||
3. 查看桥接服务日志中的认证错误
|
||
|
||
### 模型调用失败
|
||
|
||
1. 验证 API Key 是否配置:通过 `/api/models` 查看
|
||
2. 检查模型协议适配器日志
|
||
3. 确认网络可访问模型 API 端点
|
||
|
||
## 开发
|
||
|
||
```bash
|
||
# 安装依赖
|
||
npm install
|
||
|
||
# 开发模式(热重载)
|
||
npm run bridge:dev
|
||
|
||
# 构建
|
||
npm run build
|
||
|
||
# 测试
|
||
npm test
|
||
npm run test:watch
|
||
```
|
||
|
||
## 许可证
|
||
|
||
MIT
|