xykj-plus/claude-ecc/dev-assistant/README.md
2026-06-13 13:48:51 +08:00

14 KiB
Raw Blame History

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

# 构建前端 SDKadmin-xy/web 集成时需要)
npm run web-sdk:build

桥接服务默认监听 http://127.0.0.1:9020WebSocket 路径为 /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 中添加 RequestIdFilterMdcUserFilter,将请求 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

安全注意事项

  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 端点

开发

# 安装依赖
npm install

# 开发模式(热重载)
npm run bridge:dev

# 构建
npm run build

# 测试
npm test
npm run test:watch

许可证

MIT