14 KiB
14 KiB
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 或加密文件中)
安装依赖
cd dev-assistant
npm install
启动开发环境
# 启动桥接服务
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,启动时自动加载,支持热更新。
核心配置项
# 项目信息 — 驱动 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
环境变量覆盖
生产环境可通过环境变量覆盖配置:
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 有效性。
bridge:
auth:
type: http
verifyUrl: http://server:9010/api/auth/me
requiredRole: ROLE_ADMIN
2. JWT 本地解析
无需网络调用,本地解析 JWT 验证用户和角色。
bridge:
auth:
type: jwt-local
jwtSecret: ${JWT_SECRET} # 从环境变量读取
jwtIssuer: admin-xy
jwtAudience: admin-xy-web
jwtUsernameClaim: sub
jwtRolesClaim: roles
requiredRole: ROLE_ADMIN
3. 禁用认证(仅开发环境)
bridge:
auth:
type: disabled
或通过环境变量:
BRIDGE_AUTH_DISABLED=true npm run bridge:dev
模型管理
模型配置和 API Key 通过 Web SDK 动态管理,存储在 dev-assistant/.cache/ 目录(gitignore)。
支持的模型
- Claude (Anthropic) - 原生支持
- GLM (智谱 AI) - 通过协议适配器
- MiniMax - 通过协议适配器
管理接口
# 获取模型列表
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 协议
客户端 → 服务端
// 发起对话
{
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: '允许此操作'
}
服务端 → 客户端
// 会话开始
{
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
前端集成
// 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:
@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
# 获取日志源列表
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
启动桥接服务
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 启动
npx dev-assistant-bridge --config ./dev-assistant.yaml
Docker 部署
# 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
安全注意事项
- API Key 管理:禁止将 API Key 写入配置文件或代码,使用 keychain 或加密文件存储
- 认证配置:生产环境必须启用认证(type: http 或 jwt-local)
- 路径限制:配置
workspace.denyWrite保护敏感目录(.env、node_modules、.claude) - 速率限制:根据实际使用调整
rateLimit防止滥用 - CORS 配置:
bridge.origin严格限制允许的前端来源
故障排查
连接失败
- 检查桥接服务是否启动:
curl http://localhost:9020/health - 验证 CORS 配置:
bridge.origin是否包含前端域名 - 确认认证配置是否正确
认证失败
- 检查 JWT 是否有效:通过后端
/api/auth/me验证 - 确认用户角色包含
requiredRole(默认 ROLE_ADMIN) - 查看桥接服务日志中的认证错误
模型调用失败
- 验证 API Key 是否配置:通过
/api/models查看 - 检查模型协议适配器日志
- 确认网络可访问模型 API 端点
开发
# 安装依赖
npm install
# 开发模式(热重载)
npm run bridge:dev
# 构建
npm run build
# 测试
npm test
npm run test:watch
许可证
MIT