@templmf/temp-solf-lmf 0.0.53 → 0.0.55
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/guanwang/README.md +95 -0
- package/guanwang/docs/changelog.md +145 -0
- package/guanwang/docs/doc-maintenance.md +229 -0
- package/guanwang/docs/product.md +181 -0
- package/guanwang/docs/test-cases.md +395 -0
- package/guanwang/docs/usage.md +291 -0
- package/guanwang/env.example +27 -0
- package/guanwang/index.html +13 -0
- package/guanwang/package-lock.json +3825 -0
- package/guanwang/package.json +32 -0
- package/guanwang/public/favicon.svg +4 -0
- package/guanwang/public/react-runtime/babel.min.js +4 -0
- package/guanwang/public/react-runtime/react-dom.min.js +267 -0
- package/guanwang/public/react-runtime/react.min.js +31 -0
- package/guanwang/public/vue-repl-assets/compiler-sfc.esm-browser.js +50795 -0
- package/guanwang/public/vue-repl-assets/runtime-dom.esm-browser.js +12758 -0
- package/guanwang/public/vue-repl-assets/server-renderer.esm-browser.js +8600 -0
- package/guanwang/public/vue-repl-assets/vue.esm-browser.js +18672 -0
- package/guanwang/src/App.vue +61 -0
- package/guanwang/src/chat-sdk/core/components/ChatBox.vue +305 -0
- package/guanwang/src/chat-sdk/core/components/ChatSidebar.vue +84 -0
- package/guanwang/src/chat-sdk/core/components/InputBar.vue +354 -0
- package/guanwang/src/chat-sdk/core/components/MessageBubble.vue +703 -0
- package/guanwang/src/chat-sdk/core/useTheme.js +31 -0
- package/guanwang/src/chat-sdk/features/artifact/ArtifactCard.vue +172 -0
- package/guanwang/src/chat-sdk/features/artifact/ArtifactPanel.vue +963 -0
- package/guanwang/src/chat-sdk/features/artifact/index.js +13 -0
- package/guanwang/src/chat-sdk/features/artifact/useArtifactStore.js +275 -0
- package/guanwang/src/chat-sdk/features/codepreview/CodePreview.vue +523 -0
- package/guanwang/src/chat-sdk/features/codepreview/index.js +7 -0
- package/guanwang/src/chat-sdk/features/markdown/index.js +13 -0
- package/guanwang/src/chat-sdk/features/markdown/useMarkdown.js +724 -0
- package/guanwang/src/chat-sdk/features/mermaid/MermaidZoom.vue +254 -0
- package/guanwang/src/chat-sdk/features/upload/FileAttachment.vue +142 -0
- package/guanwang/src/chat-sdk/features/upload/index.js +17 -0
- package/guanwang/src/chat-sdk/features/upload/useFileHandler.js +336 -0
- package/guanwang/src/chat-sdk/headless/api/adapters/openai.js +76 -0
- package/guanwang/src/chat-sdk/headless/api/chatApi.js +126 -0
- package/guanwang/src/chat-sdk/headless/buildSystemPrompt.js +351 -0
- package/guanwang/src/chat-sdk/headless/index.js +15 -0
- package/guanwang/src/chat-sdk/headless/useChat.js +77 -0
- package/guanwang/src/chat-sdk/headless/useChatDB.js +147 -0
- package/guanwang/src/chat-sdk/headless/useChatStore.js +529 -0
- package/guanwang/src/chat-sdk/index.js +79 -0
- package/guanwang/src/chat-sdk/modes/architect.js +27 -0
- package/guanwang/src/chat-sdk/modes/ask.js +26 -0
- package/guanwang/src/chat-sdk/modes/code.js +25 -0
- package/guanwang/src/chat-sdk/modes/index.js +36 -0
- package/guanwang/src/chat-sdk/modes/requirements.js +175 -0
- package/guanwang/src/chat-sdk/settings/SettingsPanel.vue +170 -0
- package/guanwang/src/chat-sdk/settings/index.js +9 -0
- package/guanwang/src/chat-sdk/settings/useSettings.js +122 -0
- package/guanwang/src/chat-sdk/tools/defaults.js +89 -0
- package/guanwang/src/chat-sdk/tools/index.js +16 -0
- package/guanwang/src/chat-sdk/tools/parser.js +116 -0
- package/guanwang/src/components/CustomCursor.vue +69 -0
- package/guanwang/src/components/Footer.vue +24 -0
- package/guanwang/src/components/LoginModal.vue +109 -0
- package/guanwang/src/components/Navbar.vue +193 -0
- package/guanwang/src/components/ThemeToggle.vue +25 -0
- package/guanwang/src/composables/useArtifactStore.js +253 -0
- package/guanwang/src/composables/useAuth.js +88 -0
- package/guanwang/src/composables/useChatDB.js +147 -0
- package/guanwang/src/composables/useCountUp.js +24 -0
- package/guanwang/src/composables/useFileHandler.js +345 -0
- package/guanwang/src/composables/useTheme.js +31 -0
- package/guanwang/src/config/api.js +71 -0
- package/guanwang/src/main.js +23 -0
- package/guanwang/src/router/index.js +23 -0
- package/guanwang/src/services/authApi.js +27 -0
- package/guanwang/src/services/chatApi.js +66 -0
- package/guanwang/src/styles/global.css +478 -0
- package/guanwang/src/tracker/analyze.js +73 -0
- package/guanwang/src/tracker/config.js +82 -0
- package/guanwang/src/tracker/index.js +18 -0
- package/guanwang/src/tracker/service.js +102 -0
- package/guanwang/src/tracker/useChatTracker.js +179 -0
- package/guanwang/src/tracker/useTracker.js +45 -0
- package/guanwang/src/views/ChatView.vue +65 -0
- package/guanwang/src/views/HomeView.vue +156 -0
- package/guanwang/src/views/MarketView.vue +143 -0
- package/guanwang/src/views/PracticesView.vue +190 -0
- package/guanwang/src/views/SkillsView.vue +129 -0
- package/guanwang/temp +19 -0
- package/guanwang/vite.config.js +6 -0
- package/package.json +1 -1
- package/guanwang.zip +0 -0
|
@@ -0,0 +1,395 @@
|
|
|
1
|
+
# 测试用例文档
|
|
2
|
+
|
|
3
|
+
> 手动测试用例,覆盖核心功能路径。标注 `[自动化]` 的建议后续接入 Vitest / Playwright。
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 一、配置与初始化
|
|
8
|
+
|
|
9
|
+
### T-001 单模型初始化
|
|
10
|
+
**步骤**:配置单个模型,打开对话页
|
|
11
|
+
**预期**:输入栏不显示模型选择器,直接可发送消息
|
|
12
|
+
|
|
13
|
+
### T-002 多模型初始化
|
|
14
|
+
**步骤**:配置 2+ 个模型,打开对话页
|
|
15
|
+
**预期**:输入栏底部显示模型 pill,默认选中 `defaultModel`
|
|
16
|
+
|
|
17
|
+
### T-003 features 全关
|
|
18
|
+
**步骤**:`features: { artifact: false, upload: false, markdown: false, codepreview: false }`
|
|
19
|
+
**预期**:AI 回复纯文本,无代码高亮,无上传按钮,无 artifact 面板
|
|
20
|
+
|
|
21
|
+
### T-004 userControls 不声明
|
|
22
|
+
**步骤**:`features: { artifact: true }`,`userControls` 不写
|
|
23
|
+
**预期**:artifact 功能开启,设置面板中不显示 artifact 开关
|
|
24
|
+
|
|
25
|
+
### T-005 设置持久化
|
|
26
|
+
**步骤**:切换模型 → 刷新页面
|
|
27
|
+
**预期**:模型选择保持上次的值
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
## 二、对话核心
|
|
32
|
+
|
|
33
|
+
### T-010 发送纯文本消息
|
|
34
|
+
**步骤**:输入框输入文字 → Enter 发送
|
|
35
|
+
**预期**:用户气泡显示,AI 气泡流式输出,loading 状态正确
|
|
36
|
+
|
|
37
|
+
### T-011 中止流式输出
|
|
38
|
+
**步骤**:发送消息 → AI 输出中途点击"停止"
|
|
39
|
+
**预期**:输出停止,AI 气泡标记完成,loading 消失,可继续发送
|
|
40
|
+
|
|
41
|
+
### T-012 发送后自动滚到底部
|
|
42
|
+
**步骤**:消息列表超出可视区 → 发送新消息
|
|
43
|
+
**预期**:自动滚动到最新消息
|
|
44
|
+
|
|
45
|
+
### T-013 用户上翻时不强制滚动
|
|
46
|
+
**步骤**:AI 流式输出中 → 用户手动上翻
|
|
47
|
+
**预期**:不强制滚到底部,顶部显示"新消息"提示按钮
|
|
48
|
+
|
|
49
|
+
### T-014 点击"新消息"跳到底部
|
|
50
|
+
**步骤**:T-013 状态 → 点击"新消息"
|
|
51
|
+
**预期**:滚到底部,提示按钮消失
|
|
52
|
+
|
|
53
|
+
### T-015 API 请求失败
|
|
54
|
+
**步骤**:配置错误的 `baseURL` → 发送消息
|
|
55
|
+
**预期**:AI 气泡显示错误信息,不崩溃,可继续发送
|
|
56
|
+
|
|
57
|
+
### T-016 多会话切换
|
|
58
|
+
**步骤**:创建两个会话各发一条消息 → 来回切换
|
|
59
|
+
**预期**:消息列表正确隔离,artifact 各自独立
|
|
60
|
+
|
|
61
|
+
### T-017 清空会话
|
|
62
|
+
**步骤**:有消息的会话 → 点击"清空"
|
|
63
|
+
**预期**:消息清空,标题重置为"新对话",artifact 面板关闭
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 三、多模型
|
|
68
|
+
|
|
69
|
+
### T-020 运行时切换模型
|
|
70
|
+
**步骤**:发送一条消息(模型A)→ 切换到模型B → 发送第二条消息
|
|
71
|
+
**预期**:两条消息使用不同模型,API 请求的 `baseURL` 各自正确
|
|
72
|
+
|
|
73
|
+
### T-021 autoVision 自动切模型
|
|
74
|
+
**步骤**:配置一个 `vision: true` 的模型,上传图片 → 发送
|
|
75
|
+
**预期**:自动使用 vision 模型,不显示切换提示
|
|
76
|
+
|
|
77
|
+
### T-022 autoVision 纯文本不切换
|
|
78
|
+
**步骤**:发送纯文本消息
|
|
79
|
+
**预期**:使用当前选中模型,不切换到 vision 模型
|
|
80
|
+
|
|
81
|
+
---
|
|
82
|
+
|
|
83
|
+
## 四、多模式
|
|
84
|
+
|
|
85
|
+
### T-030 Code 模式默认
|
|
86
|
+
**步骤**:打开对话,默认 Code 模式
|
|
87
|
+
**预期**:AI 自我介绍为 Code 角色,回答代码类问题
|
|
88
|
+
|
|
89
|
+
### T-031 切换到 Ask 模式
|
|
90
|
+
**步骤**:顶部模式切换 → Ask
|
|
91
|
+
**预期**:下一条消息 system prompt 变为 Ask 角色,AI 不主动输出代码文件
|
|
92
|
+
|
|
93
|
+
### T-032 切换到 Architect 模式
|
|
94
|
+
**步骤**:切换到 Architect → 提问"帮我设计一个用户系统"
|
|
95
|
+
**预期**:AI 先追问信息,不直接写代码,输出技术方案文档
|
|
96
|
+
|
|
97
|
+
### T-033 需求模式四步流程
|
|
98
|
+
**步骤**:切换到需求模式 → 输入"我想做一个商品管理功能"
|
|
99
|
+
**预期**:AI 先复述目标 → 列假设清单 → 识别系统边界 → 输出需求文档
|
|
100
|
+
|
|
101
|
+
### T-034 模式 prompt 不跨会话污染
|
|
102
|
+
**步骤**:在 Code 模式对话后 → 创建新会话 → 切换到 Ask 模式
|
|
103
|
+
**预期**:新会话使用 Ask 的 system prompt,不携带 Code 模式的历史
|
|
104
|
+
|
|
105
|
+
---
|
|
106
|
+
|
|
107
|
+
## 五、Tool-use
|
|
108
|
+
|
|
109
|
+
### T-040 ask_followup_question 渲染
|
|
110
|
+
**步骤**:触发 AI 输出 `<ask_followup_question>` 工具调用
|
|
111
|
+
**预期**:气泡底部显示选项按钮,点选后文字作为新消息发送
|
|
112
|
+
|
|
113
|
+
### T-041 attempt_completion 标记完成
|
|
114
|
+
**步骤**:AI 输出 `<attempt_completion>`
|
|
115
|
+
**预期**:当前 AI 消息标记为完成状态(视觉区分),不再 loading
|
|
116
|
+
|
|
117
|
+
### T-042 switch_mode 切换提示
|
|
118
|
+
**步骤**:AI 输出 `<switch_mode mode_slug="code" reason="...">`
|
|
119
|
+
**预期**:显示切换提示,模式切换,后续 system prompt 更新
|
|
120
|
+
|
|
121
|
+
### T-043 render_artifact 触发面板
|
|
122
|
+
**步骤**:AI 输出 `<render_artifact>` 工具
|
|
123
|
+
**预期**:右侧 artifact 面板展开,文件出现在 Tab 栏
|
|
124
|
+
|
|
125
|
+
### T-044 request_context 引导提示
|
|
126
|
+
**步骤**:AI 输出 `<request_context hint="请提供...">`
|
|
127
|
+
**预期**:消息列表追加系统提示,引导用户粘贴代码
|
|
128
|
+
|
|
129
|
+
### T-045 onToolCall 覆盖默认行为
|
|
130
|
+
**步骤**:消费方注册 `onToolCall('switch_mode', handler)` → AI 触发该工具
|
|
131
|
+
**预期**:执行消费方的 handler,不执行默认行为
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 六、Artifact 面板
|
|
136
|
+
|
|
137
|
+
### T-050 生成文件并展示
|
|
138
|
+
**步骤**:Code 模式请求生成 Vue 组件
|
|
139
|
+
**预期**:右侧面板展开,Tab 显示文件名,代码视图有行号和高亮
|
|
140
|
+
|
|
141
|
+
### T-051 多文件切换
|
|
142
|
+
**步骤**:AI 在一次回复中生成多个 artifact
|
|
143
|
+
**预期**:Tab 栏显示所有文件,点击可切换
|
|
144
|
+
|
|
145
|
+
### T-052 复制代码
|
|
146
|
+
**步骤**:点击复制按钮
|
|
147
|
+
**预期**:代码写入剪贴板,按钮短暂显示对勾
|
|
148
|
+
|
|
149
|
+
### T-053 下载文件
|
|
150
|
+
**步骤**:点击下载按钮
|
|
151
|
+
**预期**:浏览器下载文件,文件名与 artifact 一致
|
|
152
|
+
|
|
153
|
+
### T-054 代码预览 HTML
|
|
154
|
+
**步骤**:生成 HTML 代码 → 点击"预览" Tab
|
|
155
|
+
**预期**:iframe 正常渲染 HTML,无跨域报错
|
|
156
|
+
|
|
157
|
+
### T-055 Vue SFC 预览
|
|
158
|
+
**步骤**:生成 Vue 组件 → 切换到"预览" Tab
|
|
159
|
+
**预期**:`@vue/repl` 加载,组件正常编译渲染
|
|
160
|
+
|
|
161
|
+
### T-056 流式高亮不闪烁
|
|
162
|
+
**步骤**:观察 AI 流式输出代码时的面板
|
|
163
|
+
**预期**:代码逐行增加,无整体重绘闪烁,行号实时更新
|
|
164
|
+
|
|
165
|
+
---
|
|
166
|
+
|
|
167
|
+
## 七、Markdown 渲染
|
|
168
|
+
|
|
169
|
+
### T-060 代码高亮
|
|
170
|
+
**步骤**:AI 输出包含代码块的回复
|
|
171
|
+
**预期**:Shiki 高亮,深色/浅色主题跟随系统
|
|
172
|
+
|
|
173
|
+
### T-061 主题切换重新渲染
|
|
174
|
+
**步骤**:切换深色/浅色主题
|
|
175
|
+
**预期**:已渲染的消息高亮主题同步更新
|
|
176
|
+
|
|
177
|
+
### T-062 KaTeX 数学公式
|
|
178
|
+
**步骤**:AI 输出 `$E=mc^2$`
|
|
179
|
+
**预期**:公式正常渲染,不显示原始 LaTeX 文本
|
|
180
|
+
|
|
181
|
+
### T-063 Mermaid 流程图
|
|
182
|
+
**步骤**:AI 输出 mermaid 代码块
|
|
183
|
+
**预期**:图表正常渲染
|
|
184
|
+
|
|
185
|
+
### T-064 原始文本调试面板 [仅开发]
|
|
186
|
+
**步骤**:`.env` 设置 `VITE_SHOW_RAW_TEXT=true` → AI 回复
|
|
187
|
+
**预期**:气泡底部显示可折叠的原始文本和字符数,生产环境不显示
|
|
188
|
+
|
|
189
|
+
---
|
|
190
|
+
|
|
191
|
+
## 八、文件上传
|
|
192
|
+
|
|
193
|
+
### T-070 上传图片
|
|
194
|
+
**步骤**:点击附件按钮 → 选择图片 → 发送
|
|
195
|
+
**预期**:气泡内显示缩略图,API 请求包含 base64 图片数据
|
|
196
|
+
|
|
197
|
+
### T-071 粘贴截图
|
|
198
|
+
**步骤**:截图后在输入框 Ctrl+V
|
|
199
|
+
**预期**:图片作为附件添加,等同手动上传
|
|
200
|
+
|
|
201
|
+
### T-072 上传代码文件
|
|
202
|
+
**步骤**:上传 `.vue` 文件
|
|
203
|
+
**预期**:文件内容作为文本附入消息,气泡显示文件名图标
|
|
204
|
+
|
|
205
|
+
### T-073 超过 5 个附件限制
|
|
206
|
+
**步骤**:尝试添加第 6 个附件
|
|
207
|
+
**预期**:显示 warning 提示,不添加第 6 个
|
|
208
|
+
|
|
209
|
+
### T-074 拖拽上传
|
|
210
|
+
**步骤**:将文件拖入输入区域
|
|
211
|
+
**预期**:显示拖拽遮罩,松开后文件被添加
|
|
212
|
+
|
|
213
|
+
---
|
|
214
|
+
|
|
215
|
+
## 九、Headless 模式 `[自动化]`
|
|
216
|
+
|
|
217
|
+
### T-080 useChat 返回正确状态
|
|
218
|
+
**步骤**:调用 `useChat(config)`
|
|
219
|
+
**预期**:`messages` 初始为空数组,`isLoading` 为 false,`availableModels` 与 config 一致
|
|
220
|
+
|
|
221
|
+
### T-081 send() 触发请求
|
|
222
|
+
**步骤**:`send({ text: 'test' })`
|
|
223
|
+
**预期**:`isLoading` 变为 true,`messages` 追加 user 和 assistant 消息
|
|
224
|
+
|
|
225
|
+
### T-082 messages 格式正确
|
|
226
|
+
**步骤**:发送消息并等待响应
|
|
227
|
+
**预期**:user 消息含 `parts`,assistant 消息 `streaming` 从 true 变 false
|
|
228
|
+
|
|
229
|
+
### T-083 switchMode 更新 currentMode
|
|
230
|
+
**步骤**:`switchMode('ask')`
|
|
231
|
+
**预期**:`currentMode.value === 'ask'`,下一条消息使用 Ask 模式 prompt
|
|
232
|
+
|
|
233
|
+
### T-084 selectModel 更新 selectedModel
|
|
234
|
+
**步骤**:`selectModel('qwen3-7b')`
|
|
235
|
+
**预期**:`selectedModel.value.id === 'qwen3-7b'`
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
## 十、CodePreview 弹框
|
|
240
|
+
|
|
241
|
+
### T-090 点击代码块打开
|
|
242
|
+
**步骤**:AI 回复含代码块 → 点击右上角"预览"按钮
|
|
243
|
+
**预期**:弹框打开,默认"分屏"Tab,左代码右预览
|
|
244
|
+
|
|
245
|
+
### T-091 代码区滚动独立
|
|
246
|
+
**步骤**:代码行数超出可视区 → 滚动代码区
|
|
247
|
+
**预期**:代码区独立滚动,状态栏不随内容滚动消失
|
|
248
|
+
|
|
249
|
+
### T-092 行列号更新
|
|
250
|
+
**步骤**:点击代码区某行
|
|
251
|
+
**预期**:底部状态栏行号更新为点击行
|
|
252
|
+
|
|
253
|
+
### T-093 Vue SFC 分屏不混乱
|
|
254
|
+
**步骤**:打开 Vue SFC 代码的预览弹框
|
|
255
|
+
**预期**:只显示 `@vue/repl` 界面,不出现我们自己的 shiki 代码面板叠加
|
|
256
|
+
|
|
257
|
+
---
|
|
258
|
+
|
|
259
|
+
## 十一、埋点
|
|
260
|
+
|
|
261
|
+
### T-100 埋点总开关关闭
|
|
262
|
+
**步骤**:`.env` 设置 `VITE_TRACK_ENABLED=false` → 发消息、复制代码
|
|
263
|
+
**预期**:Network 面板无任何 Ackee 请求,控制台无报错
|
|
264
|
+
|
|
265
|
+
### T-101 未配置 ACKEE_URL 时静默
|
|
266
|
+
**步骤**:不设置 `VITE_ACKEE_URL` → 正常使用对话功能
|
|
267
|
+
**预期**:功能正常,无 Ackee 请求,无报错
|
|
268
|
+
|
|
269
|
+
### T-102 页面访问上报
|
|
270
|
+
**步骤**:切换路由(如从首页到 /chat)
|
|
271
|
+
**预期**:Ackee「页面访问」Event 收到对应路径的 action
|
|
272
|
+
|
|
273
|
+
### T-103 消息发送三维度上报
|
|
274
|
+
**步骤**:Code 模式 + qwen3-32b 模型 + 用户"张三"发送一条消息
|
|
275
|
+
**预期**:Ackee 中「消息发送-模式」key=code、「消息发送-模型」key=qwen3-32b、「消息发送-用户」key=张三 各增加 1
|
|
276
|
+
|
|
277
|
+
### T-104 提问意图识别-代码生成
|
|
278
|
+
**步骤**:Code 模式发送"帮我生成一个登录组件"
|
|
279
|
+
**预期**:「提问-意图」key=code_gen 增加 1
|
|
280
|
+
|
|
281
|
+
### T-105 提问意图识别-调试
|
|
282
|
+
**步骤**:Ask 模式发送"这段代码报错了怎么解决"
|
|
283
|
+
**预期**:「提问-意图」key=debug 增加 1
|
|
284
|
+
|
|
285
|
+
### T-106 需求方向不上报意图
|
|
286
|
+
**步骤**:需求模式发送任意消息
|
|
287
|
+
**预期**:「提问-方向」key=requirement 增加 1,「提问-意图」不上报(无新 action)
|
|
288
|
+
|
|
289
|
+
### T-107 提问复杂度分级
|
|
290
|
+
**步骤**:分别发送 <50字、50-200字、>200字 的消息
|
|
291
|
+
**预期**:「提问-复杂度」分别上报 short / medium / long
|
|
292
|
+
|
|
293
|
+
### T-108 代码块复制埋点
|
|
294
|
+
**步骤**:点击 AI 回复里代码块的复制按钮
|
|
295
|
+
**预期**:「内容复制-来源」key=code_block、「内容复制-用户」key=当前用户名 各增加 1
|
|
296
|
+
|
|
297
|
+
### T-109 Artifact 面板复制埋点
|
|
298
|
+
**步骤**:在 ArtifactPanel 点击复制按钮
|
|
299
|
+
**预期**:「内容复制-来源」key=artifact_panel 增加 1,同时「内容复制-语言」上报对应语言
|
|
300
|
+
|
|
301
|
+
### T-110 文件下载埋点
|
|
302
|
+
**步骤**:在 ArtifactPanel 点击下载按钮
|
|
303
|
+
**预期**:「文件下载-用户」和「文件下载-语言」各增加 1
|
|
304
|
+
|
|
305
|
+
### T-111 回复耗时上报
|
|
306
|
+
**步骤**:发送消息 → 等待 AI 完整回复
|
|
307
|
+
**预期**:「回复耗时」Event 的对应模型 key 新增一条数值记录,Chart 平均值有变化
|
|
308
|
+
|
|
309
|
+
### T-112 中止上报
|
|
310
|
+
**步骤**:AI 回复中途点击停止
|
|
311
|
+
**预期**:「回复中止」Event key=当前用户名 增加 1,「回复耗时」不上报
|
|
312
|
+
|
|
313
|
+
### T-113 报错上报
|
|
314
|
+
**步骤**:配置错误 apiKey → 发送消息触发 API 报错
|
|
315
|
+
**预期**:「回复报错」Event key=api 增加 1
|
|
316
|
+
|
|
317
|
+
### T-114 模式切换上报
|
|
318
|
+
**步骤**:手动从 Code 切换到 Ask 模式
|
|
319
|
+
**预期**:「模式切换」key=code→ask:manual 增加 1
|
|
320
|
+
|
|
321
|
+
### T-115 未登录用户不上报用户维度
|
|
322
|
+
**步骤**:未登录状态下发送消息
|
|
323
|
+
**预期**:「消息发送-用户」无新 action,「消息发送-模式」和「消息发送-模型」正常上报
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
## 十一、埋点
|
|
328
|
+
|
|
329
|
+
### T-100 埋点总开关关闭
|
|
330
|
+
**步骤**:`.env` 设置 `VITE_TRACK_ENABLED=false` → 发消息、复制、切换模式
|
|
331
|
+
**预期**:不发出任何网络请求到 Ackee,控制台无埋点相关日志
|
|
332
|
+
|
|
333
|
+
### T-101 未配置 ACKEE_URL 时静默
|
|
334
|
+
**步骤**:`.env` 不填 `VITE_ACKEE_URL` → 正常使用对话框
|
|
335
|
+
**预期**:所有功能正常,不报错,埋点静默丢弃
|
|
336
|
+
|
|
337
|
+
### T-102 发消息触发模式/模型/用户三个 Event
|
|
338
|
+
**步骤**:登录后在 Code 模式用 qwen3-32b 发一条消息
|
|
339
|
+
**预期**:Ackee 后台「消息发送-模式」出现 `code`,「消息发送-模型」出现 `qwen3-32b`,「消息发送-用户」出现对应用户名
|
|
340
|
+
|
|
341
|
+
### T-103 提问方向分类
|
|
342
|
+
**步骤**:在 Code 模式发消息 → 在需求模式发消息
|
|
343
|
+
**预期**:「提问-方向」出现 `code` 和 `requirement` 两个 key
|
|
344
|
+
|
|
345
|
+
### T-104 意图识别-code_gen
|
|
346
|
+
**步骤**:发送"帮我生成一个登录组件"
|
|
347
|
+
**预期**:「提问-意图」出现 `code_gen`
|
|
348
|
+
|
|
349
|
+
### T-105 意图识别-debug
|
|
350
|
+
**步骤**:发送"这段代码报错了怎么解决"
|
|
351
|
+
**预期**:「提问-意图」出现 `debug`
|
|
352
|
+
|
|
353
|
+
### T-106 意图识别-其他(other)
|
|
354
|
+
**步骤**:发送一条不包含任何意图关键词的消息
|
|
355
|
+
**预期**:「提问-意图」出现 `other`
|
|
356
|
+
|
|
357
|
+
### T-107 需求模式不上报意图
|
|
358
|
+
**步骤**:切换到需求模式发消息
|
|
359
|
+
**预期**:「提问-意图」无新增记录(需求方向不做意图细分)
|
|
360
|
+
|
|
361
|
+
### T-108 复杂度分类
|
|
362
|
+
**步骤**:分别发送 <50字、50-200字、>200字 的消息
|
|
363
|
+
**预期**:「提问-复杂度」出现 `short` / `medium` / `long`
|
|
364
|
+
|
|
365
|
+
### T-109 代码块复制埋点
|
|
366
|
+
**步骤**:点击 AI 回复里代码块的 Copy 按钮
|
|
367
|
+
**预期**:「内容复制-来源」出现 `code_block`,「内容复制-用户」出现当前用户名,「内容复制-语言」出现对应语言
|
|
368
|
+
|
|
369
|
+
### T-110 Artifact 复制埋点
|
|
370
|
+
**步骤**:在 ArtifactPanel 点击复制按钮
|
|
371
|
+
**预期**:「内容复制-来源」出现 `artifact_panel`
|
|
372
|
+
|
|
373
|
+
### T-111 文件下载埋点
|
|
374
|
+
**步骤**:在 ArtifactPanel 点击下载按钮
|
|
375
|
+
**预期**:「文件下载-语言」和「文件下载-用户」各新增一条记录
|
|
376
|
+
|
|
377
|
+
### T-112 回复耗时上报
|
|
378
|
+
**步骤**:发一条消息等待 AI 完整回复
|
|
379
|
+
**预期**:「回复耗时」Chart 有新增数据点,value 为合理的毫秒数(>0)
|
|
380
|
+
|
|
381
|
+
### T-113 中止回复埋点
|
|
382
|
+
**步骤**:发消息后点击"停止"按钮
|
|
383
|
+
**预期**:「回复中止」出现当前用户名
|
|
384
|
+
|
|
385
|
+
### T-114 模式切换埋点
|
|
386
|
+
**步骤**:从 Code 切换到 Ask 模式
|
|
387
|
+
**预期**:「模式切换」出现 `code→ask:manual`
|
|
388
|
+
|
|
389
|
+
### T-115 工具调用埋点
|
|
390
|
+
**步骤**:触发 AI 使用 `render_artifact` 工具
|
|
391
|
+
**预期**:「工具调用」出现 `render_artifact`
|
|
392
|
+
|
|
393
|
+
### T-116 未登录用户不上报用户字段
|
|
394
|
+
**步骤**:未登录状态下发消息并复制内容
|
|
395
|
+
**预期**:「消息发送-用户」和「内容复制-用户」无新增记录(不上报 anonymous)
|
|
@@ -0,0 +1,291 @@
|
|
|
1
|
+
# chat-sdk 使用文档
|
|
2
|
+
|
|
3
|
+
## 两种接入方式
|
|
4
|
+
|
|
5
|
+
### 方式一:完整视图模式
|
|
6
|
+
|
|
7
|
+
挂载整套对话界面,无需自己写 UI。
|
|
8
|
+
|
|
9
|
+
```js
|
|
10
|
+
import { createAIChat } from '@/chat-sdk'
|
|
11
|
+
|
|
12
|
+
createAIChat({
|
|
13
|
+
el: '#chat-container',
|
|
14
|
+
|
|
15
|
+
models: [
|
|
16
|
+
{ id: 'qwen3-32b', name: 'Qwen3 32B', baseURL: 'http://192.168.1.100:8080', apiKey: 'sk-xxx', vision: false },
|
|
17
|
+
{ id: 'qwen-vl', name: 'Qwen VL', baseURL: 'http://192.168.1.101:8080', apiKey: 'sk-yyy', vision: true },
|
|
18
|
+
],
|
|
19
|
+
defaultModel: 'qwen3-32b',
|
|
20
|
+
autoVision: true,
|
|
21
|
+
|
|
22
|
+
features: {
|
|
23
|
+
artifact: true,
|
|
24
|
+
markdown: true,
|
|
25
|
+
upload: true,
|
|
26
|
+
codepreview: true,
|
|
27
|
+
},
|
|
28
|
+
|
|
29
|
+
userControls: {
|
|
30
|
+
modelSelector: true,
|
|
31
|
+
artifact: true,
|
|
32
|
+
upload: true,
|
|
33
|
+
},
|
|
34
|
+
|
|
35
|
+
modes: ['code', 'ask', 'architect', 'requirements'],
|
|
36
|
+
defaultMode: 'code',
|
|
37
|
+
customInstructions: '你是公司内部 AI 助手,回答请简洁专业。',
|
|
38
|
+
})
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
---
|
|
42
|
+
|
|
43
|
+
### 方式二:Headless 模式
|
|
44
|
+
|
|
45
|
+
只接入能力,自己控制视图。
|
|
46
|
+
|
|
47
|
+
```vue
|
|
48
|
+
<script setup>
|
|
49
|
+
import { useChat } from '@/chat-sdk/headless'
|
|
50
|
+
|
|
51
|
+
const {
|
|
52
|
+
messages,
|
|
53
|
+
isLoading,
|
|
54
|
+
currentMode,
|
|
55
|
+
selectedModel,
|
|
56
|
+
availableModels,
|
|
57
|
+
activeArtifacts,
|
|
58
|
+
send,
|
|
59
|
+
abort,
|
|
60
|
+
switchMode,
|
|
61
|
+
selectModel,
|
|
62
|
+
clearSession,
|
|
63
|
+
newSession,
|
|
64
|
+
onToolCall,
|
|
65
|
+
} = useChat({
|
|
66
|
+
models: [
|
|
67
|
+
{ id: 'qwen3-32b', name: 'Qwen3 32B', baseURL: 'http://192.168.1.100:8080', apiKey: 'sk-xxx', vision: false },
|
|
68
|
+
],
|
|
69
|
+
defaultModel: 'qwen3-32b',
|
|
70
|
+
modes: ['code', 'ask'],
|
|
71
|
+
defaultMode: 'code',
|
|
72
|
+
features: { artifact: true, markdown: true },
|
|
73
|
+
})
|
|
74
|
+
|
|
75
|
+
// 可选:覆盖工具默认行为
|
|
76
|
+
onToolCall('ask_followup_question', ({ params, resolve }) => {
|
|
77
|
+
// 自己渲染选项 UI,用户选择后调用 resolve(answer)
|
|
78
|
+
showMyOptions(params.suggests, resolve)
|
|
79
|
+
})
|
|
80
|
+
</script>
|
|
81
|
+
|
|
82
|
+
<template>
|
|
83
|
+
<div v-for="msg in messages" :key="msg.id">
|
|
84
|
+
<span>{{ msg.role }}</span>
|
|
85
|
+
<span>{{ msg.content }}</span>
|
|
86
|
+
<!-- activeArtifacts 自己决定如何渲染 -->
|
|
87
|
+
</div>
|
|
88
|
+
<button @click="send({ text: '你好' })">发送</button>
|
|
89
|
+
</template>
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
---
|
|
93
|
+
|
|
94
|
+
## config 完整字段说明
|
|
95
|
+
|
|
96
|
+
| 字段 | 类型 | 必填 | 说明 |
|
|
97
|
+
|---|---|---|---|
|
|
98
|
+
| `el` | `string \| HTMLElement` | 完整视图必填 | 挂载节点,如 `'#app'` |
|
|
99
|
+
| `models` | `ModelConfig[]` | 是 | 模型列表,见下方 |
|
|
100
|
+
| `defaultModel` | `string` | 是 | 默认模型 id |
|
|
101
|
+
| `autoVision` | `boolean` | 否 | 消息含图片时自动切 `vision:true` 的模型 |
|
|
102
|
+
| `features` | `FeaturesConfig` | 否 | 控制哪些 chunk 加载,见下方 |
|
|
103
|
+
| `userControls` | `UserControlsConfig` | 否 | 控制哪些开关对用户可见 |
|
|
104
|
+
| `modes` | `string[]` | 否 | 启用的模式,默认 `['code']` |
|
|
105
|
+
| `defaultMode` | `string` | 否 | 默认模式 id |
|
|
106
|
+
| `customInstructions` | `string` | 否 | 追加到所有模式 prompt 末尾的自定义指令 |
|
|
107
|
+
| `title` | `string` | 否 | 对话框标题,默认 `'AI 助手'` |
|
|
108
|
+
| `placeholder` | `string` | 否 | 输入框占位文字 |
|
|
109
|
+
|
|
110
|
+
### ModelConfig
|
|
111
|
+
|
|
112
|
+
```ts
|
|
113
|
+
{
|
|
114
|
+
id: string // 模型唯一标识(也是发给 API 的 model 字段)
|
|
115
|
+
name: string // 显示名称
|
|
116
|
+
baseURL: string // 接口地址,如 'http://192.168.1.100:8080'
|
|
117
|
+
apiKey: string // API Key,内网可传空字符串
|
|
118
|
+
vision: boolean // 是否支持图片输入
|
|
119
|
+
}
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### FeaturesConfig
|
|
123
|
+
|
|
124
|
+
控制对应 chunk 是否下载,`false` 时代码完全不加载。
|
|
125
|
+
|
|
126
|
+
| key | 说明 |
|
|
127
|
+
|---|---|
|
|
128
|
+
| `artifact` | 代码文件生成面板 |
|
|
129
|
+
| `markdown` | Markdown / 代码高亮 / KaTeX 渲染 |
|
|
130
|
+
| `upload` | 文件和图片上传 |
|
|
131
|
+
| `codepreview` | 代码预览弹框(含 Vue SFC / HTML 预览)|
|
|
132
|
+
|
|
133
|
+
### UserControlsConfig
|
|
134
|
+
|
|
135
|
+
声明哪些开关在设置面板里对用户可见。
|
|
136
|
+
|
|
137
|
+
| 值 | 含义 |
|
|
138
|
+
|---|---|
|
|
139
|
+
| `true` | 显示开关,默认开启,用户可关闭 |
|
|
140
|
+
| `false` | 显示开关,默认关闭,用户可开启 |
|
|
141
|
+
| 不填 | 不显示开关,强制开启 |
|
|
142
|
+
|
|
143
|
+
---
|
|
144
|
+
|
|
145
|
+
## useChat() 返回值
|
|
146
|
+
|
|
147
|
+
### 状态(只读 ref)
|
|
148
|
+
|
|
149
|
+
| 名称 | 类型 | 说明 |
|
|
150
|
+
|---|---|---|
|
|
151
|
+
| `messages` | `Ref<Message[]>` | 当前会话消息列表 |
|
|
152
|
+
| `isLoading` | `Ref<boolean>` | 是否请求中 |
|
|
153
|
+
| `currentMode` | `Ref<string>` | 当前模式 id |
|
|
154
|
+
| `selectedModel` | `ComputedRef<ModelConfig>` | 当前选中模型 |
|
|
155
|
+
| `availableModels` | `ModelConfig[]` | 全部可用模型(非响应式) |
|
|
156
|
+
| `activeArtifacts` | `Ref<Artifact[]>` | 当前会话的 artifact 列表 |
|
|
157
|
+
|
|
158
|
+
### 方法
|
|
159
|
+
|
|
160
|
+
| 名称 | 签名 | 说明 |
|
|
161
|
+
|---|---|---|
|
|
162
|
+
| `send` | `(input: SendInput) => void` | 发送消息 |
|
|
163
|
+
| `abort` | `() => void` | 中止当前流式请求 |
|
|
164
|
+
| `switchMode` | `(modeId: string) => void` | 切换模式 |
|
|
165
|
+
| `selectModel` | `(modelId: string) => void` | 切换模型 |
|
|
166
|
+
| `clearSession` | `() => void` | 清空当前会话 |
|
|
167
|
+
| `newSession` | `() => number` | 新建会话,返回会话 id |
|
|
168
|
+
| `onToolCall` | `(name, handler) \| (handler)` | 注册工具回调 |
|
|
169
|
+
|
|
170
|
+
### SendInput
|
|
171
|
+
|
|
172
|
+
```ts
|
|
173
|
+
// 纯文本
|
|
174
|
+
send({ text: '帮我写一个登录组件' })
|
|
175
|
+
|
|
176
|
+
// 带附件
|
|
177
|
+
send({
|
|
178
|
+
text: '分析这张截图',
|
|
179
|
+
attachments: [{ type: 'image', file: File }],
|
|
180
|
+
})
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Message 格式
|
|
184
|
+
|
|
185
|
+
```ts
|
|
186
|
+
{
|
|
187
|
+
id: number
|
|
188
|
+
role: 'user' | 'assistant' | 'system-tip' | 'followup'
|
|
189
|
+
content: string // AI / 用户文字内容
|
|
190
|
+
parts: Part[] // 结构化内容(text / image / file)
|
|
191
|
+
streaming: boolean // 是否流式输出中
|
|
192
|
+
error: boolean // 是否出错
|
|
193
|
+
artifacts: string[] // 关联的 artifact id 列表
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
---
|
|
198
|
+
|
|
199
|
+
## 模式说明
|
|
200
|
+
|
|
201
|
+
| 模式 id | 名称 | 职责 |
|
|
202
|
+
|---|---|---|
|
|
203
|
+
| `code` | Code | 编写、修改、重构代码,输出完整代码文件 |
|
|
204
|
+
| `ask` | Ask | 解释概念、回答技术问题,不生成代码文件 |
|
|
205
|
+
| `architect` | Architect | 系统设计、技术方案、架构拆解,输出技术文档 |
|
|
206
|
+
| `requirements` | 需求 | 梳理需求,输出用户故事和功能拆解列表 |
|
|
207
|
+
|
|
208
|
+
模式切换方式:
|
|
209
|
+
```js
|
|
210
|
+
// 代码切换
|
|
211
|
+
switchMode('architect')
|
|
212
|
+
|
|
213
|
+
// AI 自动触发(通过 switch_mode 工具)
|
|
214
|
+
// 消费方监听
|
|
215
|
+
onToolCall('switch_mode', ({ params, resolve }) => {
|
|
216
|
+
if (confirm(`切换到 ${params.mode_slug} 模式?`)) {
|
|
217
|
+
switchMode(params.mode_slug)
|
|
218
|
+
resolve()
|
|
219
|
+
}
|
|
220
|
+
})
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
## 埋点接入
|
|
226
|
+
|
|
227
|
+
### 官网页面埋点
|
|
228
|
+
|
|
229
|
+
在 `App.vue` 路由钩子和登录成功回调里接入:
|
|
230
|
+
|
|
231
|
+
```js
|
|
232
|
+
import { useTracker } from '@/tracker'
|
|
233
|
+
const tracker = useTracker()
|
|
234
|
+
|
|
235
|
+
// 路由 afterEach
|
|
236
|
+
router.afterEach((to) => tracker.pageView(to.path))
|
|
237
|
+
|
|
238
|
+
// 按钮点击
|
|
239
|
+
tracker.btnClick('hero_cta', '立即体验')
|
|
240
|
+
|
|
241
|
+
// 登录成功
|
|
242
|
+
tracker.loginSuccess(user.name)
|
|
243
|
+
```
|
|
244
|
+
|
|
245
|
+
### 对话框埋点
|
|
246
|
+
|
|
247
|
+
对话行为埋点(发消息、回复、中止、模式切换)已内置在 `useChatStore` 中,只需在 `createAIChat` config 里注入 `getUser`:
|
|
248
|
+
|
|
249
|
+
```js
|
|
250
|
+
createAIChat({
|
|
251
|
+
// ...其他配置
|
|
252
|
+
getUser: () => ({ name: currentUser.name, id: currentUser.id }),
|
|
253
|
+
})
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
采纳行为埋点(复制、下载)在 `ArtifactPanel` 和 `MessageBubble` 里通过 `chatStore.tracker` 调用,已自动处理,无需额外接入。
|
|
257
|
+
|
|
258
|
+
### 环境变量
|
|
259
|
+
|
|
260
|
+
```env
|
|
261
|
+
VITE_ACKEE_URL=http://your-ackee-server:3000 # Ackee 服务地址
|
|
262
|
+
VITE_ACKEE_DOMAIN=your-domain-uuid # Ackee Domain ID
|
|
263
|
+
VITE_TRACK_ENABLED=true # false 时全部静默,默认 true
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 自定义关键词字典
|
|
267
|
+
|
|
268
|
+
在 `src/tracker/config.js` 的 `INTENT_KEYWORDS` 里维护意图匹配关键词,修改后无需改动其他文件。
|
|
269
|
+
|
|
270
|
+
---
|
|
271
|
+
|
|
272
|
+
## 环境变量(guanwang 项目专用)
|
|
273
|
+
|
|
274
|
+
项目根目录创建 `.env.local`:
|
|
275
|
+
|
|
276
|
+
```env
|
|
277
|
+
VITE_API_BASE_URL=http://192.168.1.100:8080
|
|
278
|
+
VITE_API_KEY=sk-xxx
|
|
279
|
+
VITE_MODEL=qwen3-32b
|
|
280
|
+
|
|
281
|
+
# 多模型(逗号分隔)
|
|
282
|
+
VITE_MODELS=qwen3-32b,qwen3-7b,qwen-vl
|
|
283
|
+
|
|
284
|
+
# 调试:AI 气泡底部显示原始文本
|
|
285
|
+
VITE_SHOW_RAW_TEXT=false
|
|
286
|
+
|
|
287
|
+
# 埋点
|
|
288
|
+
VITE_ACKEE_URL=http://192.168.1.200:3000
|
|
289
|
+
VITE_ACKEE_DOMAIN=your-domain-uuid
|
|
290
|
+
VITE_TRACK_ENABLED=true
|
|
291
|
+
```
|