本地 RAG 知识库
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

7.6 KiB

CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

项目定位

这是 AI 智能客服系统的前端 SDK 工程chatbot-sdk),与仓库根目录的 Spring Boot 后端、src/main/resources/static/ 下的 Vue 3 管理后台是三个独立部分。SDK 产物是一行 <script> 标签即可嵌入第三方站点的悬浮客服窗口,IIFE 格式挂载到 window.ChatbotSDK

根目录的 ../CLAUDE.md 描述后端架构,本文件只覆盖 client/ 工程。

构建与开发

cd client/

# 安装依赖
npm install

# 构建(输出 dist/chatbot-sdk.js 与 dist/chatbot-sdk.min.js)
npm run build

# 开发 watch 模式
npm run dev
  • 构建工具:Rollup + @rollup/plugin-typescript + @rollup/plugin-terser,配置见 rollup.config.js
  • TypeScript 配置:tsconfig.jsontarget: ES2017strict: truerootDir: ./src,不生成 .d.ts
  • 产物双份:chatbot-sdk.js(未压缩 + sourcemap,~5.6MB)和 chatbot-sdk.min.js(压缩,~4.0MB,gzip ~1.1MB)。体积主要由内置的 TDesign Web Components 组件库贡献(按需 tree-shaking 后打包进 IIFE)
  • 无测试框架:验证通过后端的 http://localhost:9090/sdk/test.html 运行 10 个浏览器端核心用例(见 README 第十四节),本工程内没有可运行的自动化测试

运行时依赖

SDK 本身不独立运行,需要后端在 requestDomain(通常 http://localhost:9090)提供以下接口:

  • 基础对话:GET /ai/chatGET /ai/chat/stream
  • RAG:GET /ai/chat/streamenableRag=true)、GET /ai/chat/sources
  • 分类:GET /category/treeGET /category/list
  • 会话:GET /conversation/listGET /conversation/{id}/messagesDELETE /conversation/{id}GET /conversation/{id}/export

完整接口契约见 README.md 第六节。修改 api.ts 时务必与后端 AiController / ConversationController 保持参数一致。

架构

模块职责与数据流

入口 src/index.ts 是单例,按固定顺序串联各模块(init() 中的 12 个步骤即生命周期):

init(rawConfig)
  → config.ts    parseConfig()        解析 + 校验,返回 ResolvedConfig(失败返回 null,不抛异常)
  → i18n.ts      setLocale()          设置语言字典(zh-CN / en)
  → logger.ts    setDebug()           控制日志级别
  → api.ts       setApiConfig()       注入 requestDomain 等,供后续 HTTP/SSE 调用复用
  → styles.ts    injectStyles()       注入 <style data-csk-sdk>,按 primaryColor 生成主题
  → dom.ts       createLauncher() / createChatWindow()  构建 DOM,返回元素引用与 loading 控制函数
  → dom.ts       enableDrag()         弹窗头部拖拽,返回 cleanup 函数
  → chat.ts      initChat()           绑定事件、注入 DOM 引用,建立对话核心状态
  → chat.ts      initChatHistory()    异步加载 chatId 与历史(不阻塞 UI)

模块间通过两种方式通信:

  1. 闭包状态index.tschat.tsapi.ts 各自持有模块级变量,靠 init* 函数注入
  2. CustomEvent:DOM 层(dom.ts)派发 csk:categoryChangecsk:loadHistoryindex.ts 监听后转发给 chat.ts

关键模块

  • chat.ts(最大、最核心):对话状态机。处理发送、SSE 流式追加、RAG 来源展示、流中断兜底、无流内容降级为同步、chatId 自动管理逻辑、清空会话。Markdown 渲染由 t-chat-item 内置 cherry-markdown 处理。修改对话行为优先改这里。
  • api.ts:HTTP 封装 + SSE 流解析。三种 SSE 接口(普通流式、RAG 流式、同步)的解析逻辑都在这里,注意流式解析的边界处理。
  • dom.ts:纯 DOM 构建与事件绑定,含知识库下拉、RAG 来源卡片、历史会话面板的渲染。
  • styles.ts:所有 CSS 字符串模板,按 primaryColor 动态着色,并通过 --td-* CSS 变量透传给 TDesign 组件。改动 UI 视觉改这里,不要dom.ts 里写内联样式。
    • 主题/聊天变量自包含约定:TDesign 的变量分为两类,都必须自包含声明在 .csk-root 上(tdThemeVars() 负责主题变量 --td-brand/--td-gray/--td-bg/...tdChatVars() 负责聊天/markdown/input 变量 --td-chat-*/--td-chat-md-*/--td-chat-input-*)。原因:这些变量在 tdesign-web-components 里定义于 globalCSS 的 constructable stylesheet、选择器为 :root,但 adoptedStyleSheets 里的 :root 不匹配 shadow root,无法进入 shadow DOM;直接声明在 .csk-root 上才能经 CSS 自定义属性继承穿透 shadow DOM。升级 tdesign-web-components 版本时需同步核对 style/index.jscss$2/css/css$1 三个变量块。
    • light-DOM 组件样式补注入t-tag 是 tdesign-web-components 的 light DOM 组件(isLightDOM: true),其 .t-tag 样式在 globalCSS 里只对 shadow DOM 生效、进不了 light DOM,需在 getStyles() 里以 .csk-root .t-tag 前缀手动补注入(来源 _chunks/dep-5245073d.js)。新增 light DOM 组件时同样排查是否需要补样式。
  • markdown.ts:已废弃并移除。原基于 marked 的 Markdown 渲染器改由 TDesign Chat 组件(t-chat-item)内置 cherry-markdown 承担,无需额外加载 marked.min.js。cherry-markdown 的 XSS 防护由 TDesign 组件保证;如后续需要自定义渲染,仍需维持白名单/转义等安全策略。

单例与生命周期

index.ts 用模块级变量持有 config 和所有 DOM 引用,isInitialized 防止重复初始化。destroy() 必须清理:移除 DOM、调用 dragCleanup()removeStyles()、置空所有引用。新增 DOM 引用时记得在 destroy() 中同步置空。

关键约定

参数映射(SDK → 后端)

SDK 入参 后端参数 说明
integrateId roleId 客服角色 ID,决定 AI 人设和知识库范围(必传
userId accountId 客户账号 ID,账号绑定角色后服务端会覆盖 roleId
(自动管理) chatId /conversation/list 取或生成 sdk_时间戳_随机串

chatId 缓存在 localStorage(key: csk_chatId_{integrateId}_{userId}),clearHistory() 会重新生成。改 chat.ts 的 chatId 逻辑时注意与后端 ConversationController 的会话匹配规则一致。

CSS 命名空间

所有 class/id 用 csk- 前缀,样式注入到 <style data-csk-sdk>,z-index:悬浮按钮 9998,弹窗 9999。新增 DOM 元素必须带前缀,避免污染宿主页面。

localStorage

  • 消息历史 key:csk_history_{integrateId},上限 200 条,超出裁剪最早 50 条
  • chatId key:csk_chatId_{integrateId}_{userId}
  • 不同 integrateId 隔离,互不影响

错误处理

所有错误不抛异常、不阻塞宿主页面,仅 console.error 输出(error 始终输出,info/warndebug 控制)。新增异步逻辑要 try/catch 包裹,失败走 logger.warn / logger.error

部署

构建脚本(rollup.config.jscopyAssets 插件)会自动把 chatbot-sdk.js / chatbot-sdk.min.jslauncher-logo.png 复制到后端 src/main/resources/static/sdk/,宿主页面通过 <script src="/sdk/chatbot-sdk.min.js"></script> 引入即可;CDN 分发时同样只需部署这三类文件(chatbot-sdk.js / chatbot-sdk.min.js / launcher-logo.png)。README.md 有完整接入示例与全部配置参数表,文档是 SDK 对外契约的一部分,改公开 API(init/destroy/open/close/toggle/clearHistory)或 SDKConfig 字段时同步更新 README。