@huyooo/ai-chat-frontend-react 0.1.6 → 0.2.0
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/README.md +368 -0
- package/dist/index.css +2575 -0
- package/dist/index.css.map +1 -0
- package/dist/index.d.ts +378 -135
- package/dist/index.js +3956 -1042
- package/dist/index.js.map +1 -1
- package/dist/style.css +48 -987
- package/package.json +7 -4
- package/src/adapter.ts +10 -70
- package/src/components/ChatPanel.tsx +373 -117
- package/src/components/common/ConfirmDialog.css +136 -0
- package/src/components/common/ConfirmDialog.tsx +91 -0
- package/src/components/common/CopyButton.css +22 -0
- package/src/components/common/CopyButton.tsx +46 -0
- package/src/components/common/IndexingSettings.css +207 -0
- package/src/components/common/IndexingSettings.tsx +398 -0
- package/src/components/common/SettingsPanel.css +256 -0
- package/src/components/common/SettingsPanel.tsx +120 -0
- package/src/components/common/Toast.css +50 -0
- package/src/components/common/Toast.tsx +38 -0
- package/src/components/common/ToggleSwitch.css +52 -0
- package/src/components/common/ToggleSwitch.tsx +20 -0
- package/src/components/header/ChatHeader.css +285 -0
- package/src/components/header/ChatHeader.tsx +376 -0
- package/src/components/input/AtFilePicker.css +147 -0
- package/src/components/input/AtFilePicker.tsx +519 -0
- package/src/components/input/ChatInput.css +204 -0
- package/src/components/input/ChatInput.tsx +506 -0
- package/src/components/input/DropdownSelector.css +159 -0
- package/src/components/input/DropdownSelector.tsx +195 -0
- package/src/components/input/ImagePreviewModal.css +124 -0
- package/src/components/input/ImagePreviewModal.tsx +118 -0
- package/src/components/input/at-views/AtBranchView.tsx +34 -0
- package/src/components/input/at-views/AtBrowserView.tsx +34 -0
- package/src/components/input/at-views/AtChatsView.tsx +34 -0
- package/src/components/input/at-views/AtDocsView.tsx +34 -0
- package/src/components/input/at-views/AtFilesView.tsx +168 -0
- package/src/components/input/at-views/AtTerminalsView.tsx +34 -0
- package/src/components/input/at-views/AtViewStyles.css +143 -0
- package/src/components/input/at-views/index.ts +9 -0
- package/src/components/message/ContentRenderer.css +9 -0
- package/src/components/message/ContentRenderer.tsx +63 -0
- package/src/components/message/MessageBubble.css +190 -0
- package/src/components/message/MessageBubble.tsx +231 -0
- package/src/components/message/PartsRenderer.css +4 -0
- package/src/components/message/PartsRenderer.tsx +114 -0
- package/src/components/message/ToolResultRenderer.tsx +21 -0
- package/src/components/message/WelcomeMessage.css +221 -0
- package/src/components/message/WelcomeMessage.tsx +93 -0
- package/src/components/message/blocks/CodeBlock.tsx +60 -0
- package/src/components/message/blocks/TextBlock.tsx +15 -0
- package/src/components/message/blocks/blocks.css +141 -0
- package/src/components/message/blocks/index.ts +6 -0
- package/src/components/message/parts/CollapsibleCard.css +78 -0
- package/src/components/message/parts/CollapsibleCard.tsx +77 -0
- package/src/components/message/parts/ErrorPart.css +9 -0
- package/src/components/message/parts/ErrorPart.tsx +40 -0
- package/src/components/message/parts/ImagePart.css +50 -0
- package/src/components/message/parts/ImagePart.tsx +54 -0
- package/src/components/message/parts/SearchPart.css +44 -0
- package/src/components/message/parts/SearchPart.tsx +63 -0
- package/src/components/message/parts/TextPart.css +10 -0
- package/src/components/message/parts/TextPart.tsx +20 -0
- package/src/components/message/parts/ThinkingPart.css +9 -0
- package/src/components/message/parts/ThinkingPart.tsx +48 -0
- package/src/components/message/parts/ToolCallPart.css +220 -0
- package/src/components/message/parts/ToolCallPart.tsx +285 -0
- package/src/components/message/parts/ToolResultPart.css +68 -0
- package/src/components/message/parts/ToolResultPart.tsx +96 -0
- package/src/components/message/parts/index.ts +11 -0
- package/src/components/message/tool-results/DefaultToolResult.tsx +26 -0
- package/src/components/message/tool-results/SearchResults.tsx +69 -0
- package/src/components/message/tool-results/WeatherCard.tsx +63 -0
- package/src/components/message/tool-results/index.ts +7 -0
- package/src/components/message/tool-results/tool-results.css +179 -0
- package/src/components/message/welcome-types.ts +46 -0
- package/src/context/AutoRunConfigContext.tsx +13 -0
- package/src/context/ChatAdapterContext.tsx +8 -0
- package/src/context/ChatInputContext.tsx +40 -0
- package/src/context/RenderersContext.tsx +41 -0
- package/src/hooks/useChat.ts +855 -237
- package/src/hooks/useImageUpload.ts +253 -0
- package/src/index.ts +96 -39
- package/src/styles.css +48 -987
- package/src/types/index.ts +172 -103
- package/src/utils/fileIcon.ts +49 -0
- package/src/components/ChatInput.tsx +0 -368
- package/src/components/chat/messages/ExecutionSteps.tsx +0 -234
- package/src/components/chat/messages/MessageBubble.tsx +0 -130
- package/src/components/chat/ui/ChatHeader.tsx +0 -301
- package/src/components/chat/ui/WelcomeMessage.tsx +0 -107
package/README.md
ADDED
|
@@ -0,0 +1,368 @@
|
|
|
1
|
+
# @huyooo/ai-chat-frontend-react
|
|
2
|
+
|
|
3
|
+
AI Chat 前端组件库 - React 版本。
|
|
4
|
+
|
|
5
|
+
> 📖 **深入了解**:查看 [技术架构文档](../../ARCHITECTURE.md) 了解流式渲染、Content Parts 架构、自定义 UI 注入等核心原理。
|
|
6
|
+
|
|
7
|
+
## 安装
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @huyooo/ai-chat-frontend-react
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## 快速开始
|
|
14
|
+
|
|
15
|
+
```tsx
|
|
16
|
+
import { ChatPanel } from '@huyooo/ai-chat-frontend-react'
|
|
17
|
+
import '@huyooo/ai-chat-frontend-react/style.css'
|
|
18
|
+
import { createElectronAdapter } from '@huyooo/ai-chat-bridge-electron/renderer'
|
|
19
|
+
|
|
20
|
+
const adapter = createElectronAdapter()
|
|
21
|
+
|
|
22
|
+
function App() {
|
|
23
|
+
return <ChatPanel adapter={adapter} />
|
|
24
|
+
}
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## 组件
|
|
28
|
+
|
|
29
|
+
### ChatPanel
|
|
30
|
+
|
|
31
|
+
主聊天面板组件。
|
|
32
|
+
|
|
33
|
+
```tsx
|
|
34
|
+
<ChatPanel
|
|
35
|
+
adapter={adapter}
|
|
36
|
+
workingDir="/path/to/dir"
|
|
37
|
+
defaultModel="anthropic/claude-opus-4.5"
|
|
38
|
+
defaultMode="agent"
|
|
39
|
+
models={modelList}
|
|
40
|
+
hideHeader={false}
|
|
41
|
+
welcomeConfig={welcomeConfig}
|
|
42
|
+
onClose={handleClose}
|
|
43
|
+
/>
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
#### Props
|
|
47
|
+
|
|
48
|
+
| 属性 | 类型 | 默认值 | 说明 |
|
|
49
|
+
|------|------|--------|------|
|
|
50
|
+
| `adapter` | `ChatAdapter` | 必填 | 通信适配器 |
|
|
51
|
+
| `workingDir` | `string` | - | 工作目录 |
|
|
52
|
+
| `defaultModel` | `string` | `'anthropic/claude-opus-4.5'` | 默认模型 |
|
|
53
|
+
| `defaultMode` | `ChatMode` | `'agent'` | 默认模式 |
|
|
54
|
+
| `models` | `ModelOption[]` | `[]` | 可用模型列表 |
|
|
55
|
+
| `hideHeader` | `boolean` | `false` | 是否隐藏标题栏 |
|
|
56
|
+
| `welcomeConfig` | `Partial<WelcomeConfig>` | - | 欢迎页配置 |
|
|
57
|
+
| `stepsExpandedType` | `'open' \| 'close' \| 'auto'` | `'auto'` | 执行步骤展开模式 |
|
|
58
|
+
| `toolRenderers` | `ToolRenderers` | `{}` | 自定义工具结果渲染器 |
|
|
59
|
+
| `blockRenderers` | `BlockRenderers` | `{}` | 自定义内容块渲染器 |
|
|
60
|
+
| `autoRunConfig` | `AutoRunConfig` | - | 自动运行配置 |
|
|
61
|
+
| `onClose` | `() => void` | - | 关闭回调 |
|
|
62
|
+
| `onToolComplete` | `(event: ToolCompleteEvent) => void` | - | 工具执行完成回调 |
|
|
63
|
+
|
|
64
|
+
#### stepsExpandedType 说明
|
|
65
|
+
|
|
66
|
+
控制工具执行步骤的默认展开/折叠行为:
|
|
67
|
+
|
|
68
|
+
| 值 | 说明 |
|
|
69
|
+
|---|------|
|
|
70
|
+
| `'open'` | 始终展开所有步骤 |
|
|
71
|
+
| `'close'` | 始终折叠所有步骤 |
|
|
72
|
+
| `'auto'` | 正在执行的步骤展开,执行完毕自动折叠 |
|
|
73
|
+
|
|
74
|
+
#### autoRunConfig 说明
|
|
75
|
+
|
|
76
|
+
自动运行配置用于控制 Agent 的工具执行行为:
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
interface AutoRunConfig {
|
|
80
|
+
mode?: 'run-everything' | 'manual'; // 自动运行模式
|
|
81
|
+
}
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**配置项说明:**
|
|
85
|
+
|
|
86
|
+
- **mode**: 自动运行模式
|
|
87
|
+
- `'run-everything'`: 运行所有内容(自动执行)
|
|
88
|
+
- `'manual'`: 手动批准模式(每次执行前询问)
|
|
89
|
+
|
|
90
|
+
**使用示例:**
|
|
91
|
+
|
|
92
|
+
```tsx
|
|
93
|
+
<ChatPanel
|
|
94
|
+
adapter={adapter}
|
|
95
|
+
workingDir={workingDir}
|
|
96
|
+
autoRunConfig={{
|
|
97
|
+
mode: 'run-everything',
|
|
98
|
+
}}
|
|
99
|
+
/>
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
### WelcomeMessage
|
|
103
|
+
|
|
104
|
+
欢迎页组件,支持自定义配置。
|
|
105
|
+
|
|
106
|
+
```tsx
|
|
107
|
+
<WelcomeMessage config={welcomeConfig} onQuickAction={handleQuickAction} />
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
## 欢迎页配置
|
|
111
|
+
|
|
112
|
+
可以通过 `welcomeConfig` 自定义欢迎页的标题、功能列表和快捷任务。
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
import type { WelcomeConfig } from '@huyooo/ai-chat-frontend-react'
|
|
116
|
+
|
|
117
|
+
const welcomeConfig: Partial<WelcomeConfig> = {
|
|
118
|
+
// 标题区域
|
|
119
|
+
title: '文件助手',
|
|
120
|
+
subtitle: '智能文件管理 · 代码分析',
|
|
121
|
+
icon: 'lucide:folder',
|
|
122
|
+
|
|
123
|
+
// 功能列表
|
|
124
|
+
features: [
|
|
125
|
+
{ name: '执行命令', icon: 'lucide:terminal' },
|
|
126
|
+
{ name: '文件分析', icon: 'lucide:file-search' },
|
|
127
|
+
{ name: '代码生成', icon: 'lucide:code' },
|
|
128
|
+
],
|
|
129
|
+
|
|
130
|
+
// 快捷任务
|
|
131
|
+
tasks: [
|
|
132
|
+
{
|
|
133
|
+
name: '列出文件',
|
|
134
|
+
desc: '查看目录内容',
|
|
135
|
+
prompt: '列出当前目录的文件',
|
|
136
|
+
icon: 'lucide:list',
|
|
137
|
+
},
|
|
138
|
+
{
|
|
139
|
+
name: '代码分析',
|
|
140
|
+
desc: '分析代码结构',
|
|
141
|
+
prompt: '分析这个项目的代码结构',
|
|
142
|
+
icon: 'lucide:code',
|
|
143
|
+
},
|
|
144
|
+
],
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
### 配置接口
|
|
149
|
+
|
|
150
|
+
```typescript
|
|
151
|
+
interface WelcomeConfig {
|
|
152
|
+
/** 标题 */
|
|
153
|
+
title: string
|
|
154
|
+
/** 副标题 */
|
|
155
|
+
subtitle: string
|
|
156
|
+
/** 图标 (Iconify 格式) */
|
|
157
|
+
icon: string
|
|
158
|
+
/** 功能列表 */
|
|
159
|
+
features: WelcomeFeature[]
|
|
160
|
+
/** 快捷任务 */
|
|
161
|
+
tasks: WelcomeTask[]
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
interface WelcomeFeature {
|
|
165
|
+
name: string
|
|
166
|
+
icon: string
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
interface WelcomeTask {
|
|
170
|
+
name: string
|
|
171
|
+
desc: string
|
|
172
|
+
prompt: string
|
|
173
|
+
icon: string
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### 默认配置
|
|
178
|
+
|
|
179
|
+
如果不传 `welcomeConfig`,将使用内置的默认配置。也可以只覆盖部分字段:
|
|
180
|
+
|
|
181
|
+
```typescript
|
|
182
|
+
// 只修改标题,其他使用默认
|
|
183
|
+
const welcomeConfig = {
|
|
184
|
+
title: '我的 AI 助手',
|
|
185
|
+
subtitle: '智能对话工具',
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
可以导入默认配置作为基础:
|
|
190
|
+
|
|
191
|
+
```typescript
|
|
192
|
+
import { defaultWelcomeConfig } from '@huyooo/ai-chat-frontend-react'
|
|
193
|
+
|
|
194
|
+
const welcomeConfig = {
|
|
195
|
+
...defaultWelcomeConfig,
|
|
196
|
+
title: '自定义标题',
|
|
197
|
+
}
|
|
198
|
+
```
|
|
199
|
+
|
|
200
|
+
## 自定义工具结果渲染器
|
|
201
|
+
|
|
202
|
+
可以为特定工具注入自定义渲染组件,替代默认的 JSON 显示:
|
|
203
|
+
|
|
204
|
+
```tsx
|
|
205
|
+
import { useMemo } from 'react'
|
|
206
|
+
import { ChatPanel, ToolRenderers } from '@huyooo/ai-chat-frontend-react'
|
|
207
|
+
import { CustomWeatherCard } from './components/CustomWeatherCard'
|
|
208
|
+
|
|
209
|
+
function App() {
|
|
210
|
+
// 工具名称 -> 渲染组件映射
|
|
211
|
+
const toolRenderers = useMemo<ToolRenderers>(() => ({
|
|
212
|
+
get_weather: CustomWeatherCard,
|
|
213
|
+
// search_web: CustomSearchResults,
|
|
214
|
+
}), [])
|
|
215
|
+
|
|
216
|
+
return (
|
|
217
|
+
<ChatPanel
|
|
218
|
+
adapter={adapter}
|
|
219
|
+
toolRenderers={toolRenderers}
|
|
220
|
+
/>
|
|
221
|
+
)
|
|
222
|
+
}
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
### 创建自定义渲染组件
|
|
226
|
+
|
|
227
|
+
```tsx
|
|
228
|
+
// CustomWeatherCard.tsx
|
|
229
|
+
import { FC, useMemo } from 'react'
|
|
230
|
+
import type { ToolRendererProps, WeatherData } from '@huyooo/ai-chat-shared'
|
|
231
|
+
import './CustomWeatherCard.css'
|
|
232
|
+
|
|
233
|
+
export const CustomWeatherCard: FC<ToolRendererProps> = ({ toolResult }) => {
|
|
234
|
+
const weather = useMemo<WeatherData>(() => {
|
|
235
|
+
if (typeof toolResult === 'object' && toolResult !== null) {
|
|
236
|
+
return toolResult as WeatherData
|
|
237
|
+
}
|
|
238
|
+
return { city: '未知', temperature: 0, condition: '未知' }
|
|
239
|
+
}, [toolResult])
|
|
240
|
+
|
|
241
|
+
return (
|
|
242
|
+
<div className="weather-card">
|
|
243
|
+
<div className="city">{weather.city}</div>
|
|
244
|
+
<div className="temp">{weather.temperature}°C</div>
|
|
245
|
+
<div className="condition">{weather.condition}</div>
|
|
246
|
+
<div className="details">
|
|
247
|
+
{weather.humidity && <span>湿度 {weather.humidity}%</span>}
|
|
248
|
+
{weather.wind && <span>{weather.wind}</span>}
|
|
249
|
+
</div>
|
|
250
|
+
</div>
|
|
251
|
+
)
|
|
252
|
+
}
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### ToolRendererProps 接口
|
|
256
|
+
|
|
257
|
+
```typescript
|
|
258
|
+
interface ToolRendererProps {
|
|
259
|
+
toolName: string // 工具名称
|
|
260
|
+
toolArgs: object // 工具调用参数
|
|
261
|
+
toolResult: unknown // 工具返回结果
|
|
262
|
+
status: 'running' | 'done' | 'error' // 执行状态
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### 内置数据类型
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
// 天气数据
|
|
270
|
+
interface WeatherData {
|
|
271
|
+
city: string
|
|
272
|
+
temperature: number
|
|
273
|
+
condition: string
|
|
274
|
+
humidity?: number
|
|
275
|
+
wind?: string
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// 搜索结果
|
|
279
|
+
interface SearchResultItem {
|
|
280
|
+
title: string
|
|
281
|
+
url: string
|
|
282
|
+
snippet: string
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
## 自定义内容块渲染器
|
|
287
|
+
|
|
288
|
+
可以为特定内容类型注入自定义渲染组件:
|
|
289
|
+
|
|
290
|
+
```tsx
|
|
291
|
+
import { useMemo } from 'react'
|
|
292
|
+
import { ChatPanel, BlockRenderers } from '@huyooo/ai-chat-frontend-react'
|
|
293
|
+
import { CustomMathBlock } from './components/CustomMathBlock'
|
|
294
|
+
|
|
295
|
+
function App() {
|
|
296
|
+
const blockRenderers = useMemo<BlockRenderers>(() => ({
|
|
297
|
+
math: CustomMathBlock,
|
|
298
|
+
}), [])
|
|
299
|
+
|
|
300
|
+
return (
|
|
301
|
+
<ChatPanel
|
|
302
|
+
adapter={adapter}
|
|
303
|
+
blockRenderers={blockRenderers}
|
|
304
|
+
/>
|
|
305
|
+
)
|
|
306
|
+
}
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## useChat
|
|
310
|
+
|
|
311
|
+
Hook 函数,用于自定义 UI。
|
|
312
|
+
|
|
313
|
+
```typescript
|
|
314
|
+
import { useChat } from '@huyooo/ai-chat-frontend-react'
|
|
315
|
+
|
|
316
|
+
const {
|
|
317
|
+
messages,
|
|
318
|
+
isLoading,
|
|
319
|
+
sendMessage,
|
|
320
|
+
regenerateMessage,
|
|
321
|
+
abort,
|
|
322
|
+
clearHistory,
|
|
323
|
+
} = useChat({ adapter })
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
## 导出
|
|
327
|
+
|
|
328
|
+
```typescript
|
|
329
|
+
// 主组件
|
|
330
|
+
export { ChatPanel, WelcomeMessage, ChatInput, ChatHeader, MessageBubble }
|
|
331
|
+
|
|
332
|
+
// 内容渲染组件
|
|
333
|
+
export { ContentRenderer, TextBlock, CodeBlock }
|
|
334
|
+
|
|
335
|
+
// 工具结果渲染组件
|
|
336
|
+
export { ToolResultRenderer, DefaultToolResult, WeatherCard, SearchResults }
|
|
337
|
+
|
|
338
|
+
// Context Provider
|
|
339
|
+
export { RenderersProvider, BlockRenderersContext, ToolRenderersContext }
|
|
340
|
+
|
|
341
|
+
// Hook
|
|
342
|
+
export { useChat }
|
|
343
|
+
|
|
344
|
+
// 类型 (来自 @huyooo/ai-chat-shared)
|
|
345
|
+
export type {
|
|
346
|
+
WelcomeConfig,
|
|
347
|
+
WelcomeFeature,
|
|
348
|
+
WelcomeTask,
|
|
349
|
+
ToolRendererProps,
|
|
350
|
+
ToolRenderers,
|
|
351
|
+
BlockRenderers,
|
|
352
|
+
WeatherData,
|
|
353
|
+
SearchResultItem,
|
|
354
|
+
ContentBlock,
|
|
355
|
+
TextBlock,
|
|
356
|
+
CodeBlock
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
// 工具函数 (来自 @huyooo/ai-chat-shared)
|
|
360
|
+
export { parseContent, highlightCode, getLanguageDisplayName }
|
|
361
|
+
|
|
362
|
+
// 默认配置
|
|
363
|
+
export { defaultWelcomeConfig }
|
|
364
|
+
```
|
|
365
|
+
|
|
366
|
+
## License
|
|
367
|
+
|
|
368
|
+
MIT
|