@hgt-weprotalk/mira-client 0.1.8
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.dev.md +194 -0
- package/README.md +112 -0
- package/dist/components/chat-widget/AgentAvatar.d.ts +9 -0
- package/dist/components/chat-widget/AgentAvatar.d.ts.map +1 -0
- package/dist/components/chat-widget/ChatHeader.d.ts +25 -0
- package/dist/components/chat-widget/ChatHeader.d.ts.map +1 -0
- package/dist/components/chat-widget/ChatInput.d.ts +23 -0
- package/dist/components/chat-widget/ChatInput.d.ts.map +1 -0
- package/dist/components/chat-widget/ChatMessage.d.ts +20 -0
- package/dist/components/chat-widget/ChatMessage.d.ts.map +1 -0
- package/dist/components/chat-widget/ChatMessageList.d.ts +59 -0
- package/dist/components/chat-widget/ChatMessageList.d.ts.map +1 -0
- package/dist/components/chat-widget/ChatPanel.d.ts +122 -0
- package/dist/components/chat-widget/ChatPanel.d.ts.map +1 -0
- package/dist/components/chat-widget/ChatToast.d.ts +10 -0
- package/dist/components/chat-widget/ChatToast.d.ts.map +1 -0
- package/dist/components/chat-widget/ChatToastContext.d.ts +15 -0
- package/dist/components/chat-widget/ChatToastContext.d.ts.map +1 -0
- package/dist/components/chat-widget/ChatWidget.d.ts +23 -0
- package/dist/components/chat-widget/ChatWidget.d.ts.map +1 -0
- package/dist/components/chat-widget/CollectQuestionForm.d.ts +15 -0
- package/dist/components/chat-widget/CollectQuestionForm.d.ts.map +1 -0
- package/dist/components/chat-widget/ConfirmDialog.d.ts +11 -0
- package/dist/components/chat-widget/ConfirmDialog.d.ts.map +1 -0
- package/dist/components/chat-widget/FeedbackSheet.d.ts +11 -0
- package/dist/components/chat-widget/FeedbackSheet.d.ts.map +1 -0
- package/dist/components/chat-widget/HandoffForm.d.ts +21 -0
- package/dist/components/chat-widget/HandoffForm.d.ts.map +1 -0
- package/dist/components/chat-widget/ImagePreviewContext.d.ts +17 -0
- package/dist/components/chat-widget/ImagePreviewContext.d.ts.map +1 -0
- package/dist/components/chat-widget/MessageBody.d.ts +8 -0
- package/dist/components/chat-widget/MessageBody.d.ts.map +1 -0
- package/dist/components/chat-widget/MessageFeedback.d.ts +18 -0
- package/dist/components/chat-widget/MessageFeedback.d.ts.map +1 -0
- package/dist/components/chat-widget/MiniNodeRenderer.d.ts +8 -0
- package/dist/components/chat-widget/MiniNodeRenderer.d.ts.map +1 -0
- package/dist/components/chat-widget/QuickEntryZone.d.ts +13 -0
- package/dist/components/chat-widget/QuickEntryZone.d.ts.map +1 -0
- package/dist/components/chat-widget/SessionList.d.ts +21 -0
- package/dist/components/chat-widget/SessionList.d.ts.map +1 -0
- package/dist/components/chat-widget/ThinkingStages.d.ts +8 -0
- package/dist/components/chat-widget/ThinkingStages.d.ts.map +1 -0
- package/dist/components/chat-widget/Tooltip.d.ts +10 -0
- package/dist/components/chat-widget/Tooltip.d.ts.map +1 -0
- package/dist/components/chat-widget/formatMessageTime.d.ts +3 -0
- package/dist/components/chat-widget/formatMessageTime.d.ts.map +1 -0
- package/dist/components/chat-widget/icons/Icon.d.ts +9 -0
- package/dist/components/chat-widget/icons/Icon.d.ts.map +1 -0
- package/dist/components/chat-widget/icons/LauncherIcon.d.ts +4 -0
- package/dist/components/chat-widget/icons/LauncherIcon.d.ts.map +1 -0
- package/dist/components/chat-widget/icons/icons.generated.d.ts +14 -0
- package/dist/components/chat-widget/icons/icons.generated.d.ts.map +1 -0
- package/dist/components/chat-widget/icons.d.ts +5 -0
- package/dist/components/chat-widget/icons.d.ts.map +1 -0
- package/dist/components/chat-widget/useMessageFeedback.d.ts +27 -0
- package/dist/components/chat-widget/useMessageFeedback.d.ts.map +1 -0
- package/dist/config/chat.d.ts +7 -0
- package/dist/config/chat.d.ts.map +1 -0
- package/dist/config/hostUser.d.ts +10 -0
- package/dist/config/hostUser.d.ts.map +1 -0
- package/dist/config/runtime.d.ts +22 -0
- package/dist/config/runtime.d.ts.map +1 -0
- package/dist/config/zendesk.d.ts +5 -0
- package/dist/config/zendesk.d.ts.map +1 -0
- package/dist/embed/assets/frame--s-0VxXj.js +99 -0
- package/dist/embed/assets/lib-B5x6C9n9.js +14 -0
- package/dist/embed/assets/style-L9oqpUIO.css +2 -0
- package/dist/embed/assets/zh-CN-Bb9qbg6E.js +1 -0
- package/dist/embed/chat-widget.js +133 -0
- package/dist/embed/embedDialogLayout.d.ts +10 -0
- package/dist/embed/embedDialogLayout.d.ts.map +1 -0
- package/dist/embed/embedDialogTokens.d.ts +29 -0
- package/dist/embed/embedDialogTokens.d.ts.map +1 -0
- package/dist/embed/favicon.svg +1 -0
- package/dist/embed/frame.html +13 -0
- package/dist/embed/icons.svg +24 -0
- package/dist/embed/messages.d.ts +88 -0
- package/dist/embed/messages.d.ts.map +1 -0
- package/dist/embed/mira-chat-host.js +1 -0
- package/dist/embed/sdkMethods.d.ts +18 -0
- package/dist/embed/sdkMethods.d.ts.map +1 -0
- package/dist/embed/useEmbedDialogLayout.d.ts +3 -0
- package/dist/embed/useEmbedDialogLayout.d.ts.map +1 -0
- package/dist/embed/useEmbedHostBridge.d.ts +6 -0
- package/dist/embed/useEmbedHostBridge.d.ts.map +1 -0
- package/dist/favicon.svg +1 -0
- package/dist/hooks/useChat.d.ts +48 -0
- package/dist/hooks/useChat.d.ts.map +1 -0
- package/dist/hooks/useChatWidgetWindowTabSync.d.ts +16 -0
- package/dist/hooks/useChatWidgetWindowTabSync.d.ts.map +1 -0
- package/dist/hooks/useHandoff.d.ts +67 -0
- package/dist/hooks/useHandoff.d.ts.map +1 -0
- package/dist/hooks/useMarkdownNodes.d.ts +10 -0
- package/dist/hooks/useMarkdownNodes.d.ts.map +1 -0
- package/dist/hooks/useZendesk.d.ts +43 -0
- package/dist/hooks/useZendesk.d.ts.map +1 -0
- package/dist/i18n/I18nProvider.d.ts +18 -0
- package/dist/i18n/I18nProvider.d.ts.map +1 -0
- package/dist/i18n/createTranslator.d.ts +4 -0
- package/dist/i18n/createTranslator.d.ts.map +1 -0
- package/dist/i18n/detectLocale.d.ts +9 -0
- package/dist/i18n/detectLocale.d.ts.map +1 -0
- package/dist/i18n/index.d.ts +6 -0
- package/dist/i18n/index.d.ts.map +1 -0
- package/dist/i18n/types.d.ts +11 -0
- package/dist/i18n/types.d.ts.map +1 -0
- package/dist/icons.svg +24 -0
- package/dist/index.cjs.js +104 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.es.js +8336 -0
- package/dist/mira-client.css +2 -0
- package/dist/services/chat/agentAdapter.d.ts +119 -0
- package/dist/services/chat/agentAdapter.d.ts.map +1 -0
- package/dist/services/chat/agentClient.d.ts +18 -0
- package/dist/services/chat/agentClient.d.ts.map +1 -0
- package/dist/services/chat/embedMedia.d.ts +13 -0
- package/dist/services/chat/embedMedia.d.ts.map +1 -0
- package/dist/services/chat/historyMapper.d.ts +5 -0
- package/dist/services/chat/historyMapper.d.ts.map +1 -0
- package/dist/services/chat/index.d.ts +61 -0
- package/dist/services/chat/index.d.ts.map +1 -0
- package/dist/services/chat/markdownSanitize.d.ts +7 -0
- package/dist/services/chat/markdownSanitize.d.ts.map +1 -0
- package/dist/services/chat/messageClipboard.d.ts +4 -0
- package/dist/services/chat/messageClipboard.d.ts.map +1 -0
- package/dist/services/chat/messageContent.d.ts +4 -0
- package/dist/services/chat/messageContent.d.ts.map +1 -0
- package/dist/services/chat/quickEntryMapper.d.ts +4 -0
- package/dist/services/chat/quickEntryMapper.d.ts.map +1 -0
- package/dist/services/chat/sessionListLocal.d.ts +4 -0
- package/dist/services/chat/sessionListLocal.d.ts.map +1 -0
- package/dist/services/chat/sessionStatus.d.ts +17 -0
- package/dist/services/chat/sessionStatus.d.ts.map +1 -0
- package/dist/services/chat/sessionStatusDisplay.d.ts +25 -0
- package/dist/services/chat/sessionStatusDisplay.d.ts.map +1 -0
- package/dist/services/chat/streamParser.d.ts +4 -0
- package/dist/services/chat/streamParser.d.ts.map +1 -0
- package/dist/services/chat/unread.d.ts +8 -0
- package/dist/services/chat/unread.d.ts.map +1 -0
- package/dist/services/feedback/storage.d.ts +6 -0
- package/dist/services/feedback/storage.d.ts.map +1 -0
- package/dist/services/handoff/signals.d.ts +5 -0
- package/dist/services/handoff/signals.d.ts.map +1 -0
- package/dist/services/tabSync/createTabSync.d.ts +4 -0
- package/dist/services/tabSync/createTabSync.d.ts.map +1 -0
- package/dist/services/tabSync/index.d.ts +10 -0
- package/dist/services/tabSync/index.d.ts.map +1 -0
- package/dist/services/tabSync/tabId.d.ts +3 -0
- package/dist/services/tabSync/tabId.d.ts.map +1 -0
- package/dist/services/tabSync/types.d.ts +40 -0
- package/dist/services/tabSync/types.d.ts.map +1 -0
- package/dist/services/zendesk/appUser.d.ts +16 -0
- package/dist/services/zendesk/appUser.d.ts.map +1 -0
- package/dist/services/zendesk/configApi.d.ts +4 -0
- package/dist/services/zendesk/configApi.d.ts.map +1 -0
- package/dist/services/zendesk/conversationStatus.d.ts +12 -0
- package/dist/services/zendesk/conversationStatus.d.ts.map +1 -0
- package/dist/services/zendesk/initWidgetSdk.d.ts +17 -0
- package/dist/services/zendesk/initWidgetSdk.d.ts.map +1 -0
- package/dist/services/zendesk/message.d.ts +21 -0
- package/dist/services/zendesk/message.d.ts.map +1 -0
- package/dist/services/zendesk/sessionListPreview.d.ts +15 -0
- package/dist/services/zendesk/sessionListPreview.d.ts.map +1 -0
- package/dist/services/zendesk/smoochClient.d.ts +10 -0
- package/dist/services/zendesk/smoochClient.d.ts.map +1 -0
- package/dist/services/zendesk/visitor.d.ts +11 -0
- package/dist/services/zendesk/visitor.d.ts.map +1 -0
- package/dist/store/chatWidgetState.d.ts +58 -0
- package/dist/store/chatWidgetState.d.ts.map +1 -0
- package/dist/store/chatWidgetStore.d.ts +20 -0
- package/dist/store/chatWidgetStore.d.ts.map +1 -0
- package/dist/store/index.d.ts +10 -0
- package/dist/store/index.d.ts.map +1 -0
- package/dist/store/messageHelpers.d.ts +36 -0
- package/dist/store/messageHelpers.d.ts.map +1 -0
- package/dist/store/runtime.d.ts +51 -0
- package/dist/store/runtime.d.ts.map +1 -0
- package/dist/store/slices/chatSlice.d.ts +157 -0
- package/dist/store/slices/chatSlice.d.ts.map +1 -0
- package/dist/store/slices/syncSlice.d.ts +59 -0
- package/dist/store/slices/syncSlice.d.ts.map +1 -0
- package/dist/store/syncTypes.d.ts +83 -0
- package/dist/store/syncTypes.d.ts.map +1 -0
- package/dist/store/tabSyncBridge.d.ts +29 -0
- package/dist/store/tabSyncBridge.d.ts.map +1 -0
- package/dist/types/agent.d.ts +74 -0
- package/dist/types/agent.d.ts.map +1 -0
- package/dist/types/chat.d.ts +53 -0
- package/dist/types/chat.d.ts.map +1 -0
- package/dist/types/embed.d.ts +57 -0
- package/dist/types/embed.d.ts.map +1 -0
- package/dist/types/feedback.d.ts +17 -0
- package/dist/types/feedback.d.ts.map +1 -0
- package/dist/types/handoff.d.ts +18 -0
- package/dist/types/handoff.d.ts.map +1 -0
- package/dist/types/history.d.ts +44 -0
- package/dist/types/history.d.ts.map +1 -0
- package/dist/types/quickEntry.d.ts +22 -0
- package/dist/types/quickEntry.d.ts.map +1 -0
- package/dist/types/zendesk.d.ts +19 -0
- package/dist/types/zendesk.d.ts.map +1 -0
- package/dist/utils/generateId.d.ts +3 -0
- package/dist/utils/generateId.d.ts.map +1 -0
- package/package.json +70 -0
package/README.dev.md
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
# mira-client(内部开发说明)
|
|
2
|
+
|
|
3
|
+
> **仓库维护者请看本文档。** npm 包页面与 GitHub 首页默认展示 [`README.md`](./README.md)(对外接入说明)。
|
|
4
|
+
|
|
5
|
+
Mira 用户侧 **Chat Widget(聊天挂件)** 前端工程。
|
|
6
|
+
|
|
7
|
+
本仓库用 **React 19 + Vite 8 + TypeScript** 搭建开发基座,用于本地预览与联调;**生产交付物**通过 npm 包 `@hgt-weprotalk/mira-client` 发布,宿主(Next.js 独立站)按场景选择三种接入方式之一。
|
|
8
|
+
|
|
9
|
+
需求文档见 [docs/mira-v1/](./docs/mira-v1/README.md)。
|
|
10
|
+
|
|
11
|
+
| 层级 | 说明 |
|
|
12
|
+
|------|------|
|
|
13
|
+
| **npm 交付物** | `@hgt-weprotalk/mira-client` — React 库 + Embed 静态资源(`dist/` 仅发布 npm,不进 GitHub) |
|
|
14
|
+
| **基座(Demo Shell)** | `Layout`、`pages/`、`index.html` / `use-cases*.html` — 仅开发预览,非生产交付 |
|
|
15
|
+
| **服务层** | `src/services/` — Java Agent API、Zendesk、反馈、转人工等适配 |
|
|
16
|
+
|
|
17
|
+
## 架构概览
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
┌──────────────────────────────────────────────────────────┐
|
|
21
|
+
│ Demo Shell(本地预览) │
|
|
22
|
+
│ 首页:React 组件直接挂载 ChatWidget(= 方式 1 生产接入) │
|
|
23
|
+
│ 用例A / 用例B:模拟独立站 script / iframe 接入 │
|
|
24
|
+
└──────────────────────────────────────────────────────────┘
|
|
25
|
+
|
|
26
|
+
┌──────────────────────────────────────────────────────────┐
|
|
27
|
+
│ Chat Widget │
|
|
28
|
+
│ ChatWidget → useHandoff / useChat → chatApi │
|
|
29
|
+
│ ↓ │
|
|
30
|
+
│ agentAdapter ←→ /client/agentChat/* (SSE + REST) │
|
|
31
|
+
│ zendesk/* ←→ Smooch Web Messenger(转人工) │
|
|
32
|
+
└──────────────────────────────────────────────────────────┘
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**分层原则**:UI / Hook 只依赖 `services/` 门面(如 `chatApi`),切换后端时改 adapter 与导出入口即可,Widget UI 无需改动。
|
|
36
|
+
|
|
37
|
+
## 宿主接入(三种方式)
|
|
38
|
+
|
|
39
|
+
安装 npm 包:
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
pnpm add @hgt-weprotalk/mira-client
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
| # | 方式 | 适用 | 说明 |
|
|
46
|
+
|---|------|------|------|
|
|
47
|
+
| **1** | **React 组件** | Next.js App Router(**推荐**) | `import { ChatWidget } from "@hgt-weprotalk/mira-client"`,与本地 Home 页一致 |
|
|
48
|
+
| **2** | **Script Embed(用例 A)** | launcher 弹窗、非 React 页 | 同步 `dist/embed/` → `public/embed/`,加载 `chat-widget.js` + `mira-chat-host.js` |
|
|
49
|
+
| **3** | **Inline iframe(用例 B)** | 宿主自控布局(抽屉/侧栏) | 自行放置 `<iframe src="/embed/frame.html?...">` + host bridge |
|
|
50
|
+
|
|
51
|
+
详细文档:[20-npm包发布与三种接入方式](./docs/mira-v1/chat-widget/20-npm包发布与三种接入方式.md) · [19-宿主SDK接口](./docs/mira-v1/chat-widget/19-宿主SDK接口.md)(Embed 模式 SDK)
|
|
52
|
+
|
|
53
|
+
### 方式 1 — React 组件(Next.js 推荐)
|
|
54
|
+
|
|
55
|
+
参考 `src/reference/nextjs/MiraChatLauncher.tsx`(Valerion 独立站真实接入):
|
|
56
|
+
|
|
57
|
+
```tsx
|
|
58
|
+
"use client";
|
|
59
|
+
|
|
60
|
+
import { ChatWidget, type Locale } from "@hgt-weprotalk/mira-client";
|
|
61
|
+
import "@hgt-weprotalk/mira-client/style.css";
|
|
62
|
+
|
|
63
|
+
export function MiraChat({ site = "en" }: { site?: string }) {
|
|
64
|
+
return (
|
|
65
|
+
<ChatWidget
|
|
66
|
+
agentName="after_sales_assistant"
|
|
67
|
+
site={site}
|
|
68
|
+
apiBaseUrl={process.env.NEXT_PUBLIC_AGENT_API_BASE ?? "/prod-api"}
|
|
69
|
+
locale={"en-US" satisfies Locale}
|
|
70
|
+
/>
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### 方式 2 — Script Embed(用例 A:launcher 弹窗)
|
|
76
|
+
|
|
77
|
+
npm 安装后,将 embed 资源同步至 `public/embed/`(推荐 postinstall,见 [20 文档 §1.2](./docs/mira-v1/chat-widget/20-npm包发布与三种接入方式.md#12-方式-2--script-embed用例-alauncher-弹窗)),然后:
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<script
|
|
81
|
+
src="/embed/chat-widget.js"
|
|
82
|
+
data-agent-name="after_sales_assistant"
|
|
83
|
+
data-site="en"
|
|
84
|
+
defer
|
|
85
|
+
></script>
|
|
86
|
+
<script src="/embed/mira-chat-host.js" defer></script>
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
用例 A 采用**分离渲染**:宿主页 `chat-widget.js` 负责右下角 launcher 按钮,iframe 内仅渲染聊天面板(`panelOnly`)。本地演示:[use-cases.html](./use-cases.html)
|
|
90
|
+
|
|
91
|
+
### 方式 3 — Inline iframe(用例 B)
|
|
92
|
+
|
|
93
|
+
```html
|
|
94
|
+
<iframe
|
|
95
|
+
id="mira-chat-inline-frame"
|
|
96
|
+
src="/embed/frame.html?agentName=after_sales_assistant&site=en&parentOrigin={ORIGIN}&layout=inline"
|
|
97
|
+
style="width: 100%; height: 100%; min-height: 700px; border: 0"
|
|
98
|
+
allow="clipboard-write"
|
|
99
|
+
></iframe>
|
|
100
|
+
<script src="/embed/mira-chat-host.js" defer></script>
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
本地演示:[use-cases-b.html](./use-cases-b.html)
|
|
104
|
+
|
|
105
|
+
### `window.MiraChat` SDK(方式 2 / 3)
|
|
106
|
+
|
|
107
|
+
| 方法 | 说明 |
|
|
108
|
+
|------|------|
|
|
109
|
+
| `bindUser({ loginUserId, userNickname? })` | 登录后绑定 visitor 历史(`POST /bindUser`) |
|
|
110
|
+
| `setContext({ loginUserId?, userNickname?, product? })` | 传递用户 / 商品上下文 |
|
|
111
|
+
| `open()` / `close()` | 打开 / 关闭聊天容器 |
|
|
112
|
+
| `on("ready" \| "navigate" \| "error", handler)` | 监听 iframe 事件 |
|
|
113
|
+
|
|
114
|
+
方式 1 直接使用 `setMiraChatUser` / `bindMiraChatUser` 等 import,无需 `window.MiraChat`。
|
|
115
|
+
|
|
116
|
+
## 目录结构
|
|
117
|
+
|
|
118
|
+
```
|
|
119
|
+
mira-client/
|
|
120
|
+
├── README.md # npm / GitHub 首页(对外)
|
|
121
|
+
├── README.dev.md # 本文件(内部)
|
|
122
|
+
├── index.html # 首页基座(方式 1 预览)
|
|
123
|
+
├── use-cases.html # 用例A:launcher 弹窗(方式 2)
|
|
124
|
+
├── use-cases-b.html # 用例B:inline iframe(方式 3)
|
|
125
|
+
├── vite.config.ts # 开发基座 + /agent-api 代理
|
|
126
|
+
├── vite.lib.config.ts # npm 库构建
|
|
127
|
+
├── vite.embed*.config.ts # embed 脚本构建
|
|
128
|
+
│
|
|
129
|
+
├── src/
|
|
130
|
+
│ ├── index.ts # ★ npm 包公共入口
|
|
131
|
+
│ ├── components/chat-widget/ # ★ Widget UI 源码
|
|
132
|
+
│ ├── embed/ # launcher / host-bridge / frame 源码
|
|
133
|
+
│ ├── reference/nextjs/ # Next.js 宿主接入参考
|
|
134
|
+
│ ├── hooks/ # useChat、useHandoff、useZendesk
|
|
135
|
+
│ ├── services/ # chat、zendesk、feedback、handoff
|
|
136
|
+
│ └── pages/ # Home、UseCases、UseCasesB(基座)
|
|
137
|
+
│
|
|
138
|
+
├── dist/ # 构建产物(.gitignore,npm publish 时上传)
|
|
139
|
+
└── docs/mira-v1/ # 需求与接口文档
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
## 配置与环境变量
|
|
143
|
+
|
|
144
|
+
**重要**:npm 包与 embed 交付物**不依赖**宿主项目的 `.env`。生产环境由独立站通过 **React props**(方式 1)或 **script `data-*` / iframe URL 参数**(方式 2/3)传入运行时配置;本仓库 `.env` **仅用于本地 Demo Shell 开发联调**。
|
|
145
|
+
|
|
146
|
+
### 开发 vs 生产
|
|
147
|
+
|
|
148
|
+
| 配置项 | 本地开发(`.env`) | 生产(宿主传参) |
|
|
149
|
+
|--------|-------------------|------------------|
|
|
150
|
+
| Agent 名称 | `VITE_AGENT_NAME` | `agentName` prop 或 `data-agent-name` / URL `agentName` |
|
|
151
|
+
| 站点 | `VITE_AGENT_SITE` | `site` prop 或 `data-site` / URL `site` |
|
|
152
|
+
| Agent API 前缀 | `VITE_AGENT_API_BASE` | `apiBaseUrl` prop 或 `data-api-base-url` / URL `apiBaseUrl` |
|
|
153
|
+
| 代理到 Java 后端 | `VITE_AGENT_API_TARGET`(仅 Vite dev) | **不适用** — 由宿主自行处理 |
|
|
154
|
+
|
|
155
|
+
### 本地开发 `.env`(示例)
|
|
156
|
+
|
|
157
|
+
```env
|
|
158
|
+
VITE_AGENT_NAME=after_sales_assistant
|
|
159
|
+
VITE_AGENT_SITE=en
|
|
160
|
+
VITE_AGENT_API_BASE=/agent-api
|
|
161
|
+
VITE_AGENT_API_TARGET=http://localhost:8080
|
|
162
|
+
```
|
|
163
|
+
|
|
164
|
+
### 生产:后端请求由宿主负责
|
|
165
|
+
|
|
166
|
+
Widget 内所有 Agent API 请求发往 **`{apiBaseUrl}/client/agentChat/*`**。**如何连到 Java C 端 API 完全由独立站决定**(同域名反代 / BFF / 绝对路径等)。
|
|
167
|
+
|
|
168
|
+
## 常用命令
|
|
169
|
+
|
|
170
|
+
```bash
|
|
171
|
+
npm install # 安装依赖
|
|
172
|
+
npm run dev # 启动开发服务器
|
|
173
|
+
npm run build # 类型检查 + 库构建 + embed 构建
|
|
174
|
+
npm run build:lib # 仅 React 库
|
|
175
|
+
npm run build:embed # 仅 embed 脚本
|
|
176
|
+
npm run typecheck # TypeScript 检查
|
|
177
|
+
npm run lint # oxlint
|
|
178
|
+
npm run test:chat-handoff # 转人工 Playwright 冒烟
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**发版(维护者):**
|
|
182
|
+
|
|
183
|
+
```bash
|
|
184
|
+
node scripts/release-version.mjs # bump → npm publish → tag → push
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**用例页本地验证**:先 `npm run build:embed`,再 `npm run dev`,访问 `/use-cases.html` 或 `/use-cases-b.html`。
|
|
188
|
+
|
|
189
|
+
## 生产部署注意
|
|
190
|
+
|
|
191
|
+
- 宿主通过 `pnpm add @hgt-weprotalk/mira-client@x.y.z` 安装;`dist/` 在 npm 包内,不在 GitHub 仓库。
|
|
192
|
+
- Next.js 推荐 **方式 1**(React 组件),接入与本地 Home 页一致。
|
|
193
|
+
- 方式 2/3 需 postinstall 将 `node_modules/@hgt-weprotalk/mira-client/dist/embed/` 同步至 `public/embed/`。
|
|
194
|
+
- `agentName`、`site`、`apiBaseUrl` 由宿主在接入时传参,**不要在生产依赖本仓库 `.env`**。
|
package/README.md
ADDED
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# @hgt-weprotalk/mira-client
|
|
2
|
+
|
|
3
|
+
Mira Chat Widget — embeddable AI chat for React / Next.js sites.
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pnpm add @hgt-weprotalk/mira-client
|
|
9
|
+
# or
|
|
10
|
+
npm install @hgt-weprotalk/mira-client
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
**Peer dependencies:** `react` ^18 || ^19, `react-dom` ^18 || ^19
|
|
14
|
+
|
|
15
|
+
## Integration options
|
|
16
|
+
|
|
17
|
+
| Mode | Use case |
|
|
18
|
+
|------|----------|
|
|
19
|
+
| **React component** (recommended) | Next.js App Router — import `ChatWidget` directly |
|
|
20
|
+
| **Script embed** | Floating launcher + iframe panel |
|
|
21
|
+
| **Inline iframe** | Host-controlled layout (drawer, sidebar, etc.) |
|
|
22
|
+
|
|
23
|
+
### React component (Next.js)
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
"use client";
|
|
27
|
+
|
|
28
|
+
import { ChatWidget, type Locale } from "@hgt-weprotalk/mira-client";
|
|
29
|
+
import "@hgt-weprotalk/mira-client/style.css";
|
|
30
|
+
|
|
31
|
+
export function MiraChat({ site = "en" }: { site?: string }) {
|
|
32
|
+
return (
|
|
33
|
+
<ChatWidget
|
|
34
|
+
agentName="your_agent_name"
|
|
35
|
+
site={site}
|
|
36
|
+
apiBaseUrl="/prod-api"
|
|
37
|
+
locale={"en-US" satisfies Locale}
|
|
38
|
+
/>
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
For logged-in users, use the exported helpers:
|
|
44
|
+
|
|
45
|
+
```tsx
|
|
46
|
+
import { setMiraChatUser } from "@hgt-weprotalk/mira-client";
|
|
47
|
+
|
|
48
|
+
await setMiraChatUser({
|
|
49
|
+
loginUserId: customer.id,
|
|
50
|
+
name: customer.name,
|
|
51
|
+
email: customer.email,
|
|
52
|
+
});
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Use `dynamic(..., { ssr: false })` if the host page is server-rendered.
|
|
56
|
+
|
|
57
|
+
### Script embed (launcher)
|
|
58
|
+
|
|
59
|
+
Copy embed assets from the package to your static directory (e.g. `public/embed/`):
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
cp -r node_modules/@hgt-weprotalk/mira-client/dist/embed public/embed
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
```html
|
|
66
|
+
<script
|
|
67
|
+
src="/embed/chat-widget.js"
|
|
68
|
+
data-agent-name="your_agent_name"
|
|
69
|
+
data-site="en"
|
|
70
|
+
defer
|
|
71
|
+
></script>
|
|
72
|
+
<script src="/embed/mira-chat-host.js" defer></script>
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
Host SDK: `window.MiraChat` (bindUser, setUser, open, close, on).
|
|
76
|
+
|
|
77
|
+
### Inline iframe
|
|
78
|
+
|
|
79
|
+
```html
|
|
80
|
+
<iframe
|
|
81
|
+
src="/embed/frame.html?agentName=your_agent_name&site=en&parentOrigin=https://example.com&layout=inline"
|
|
82
|
+
style="width: 100%; height: 100%; min-height: 700px; border: 0"
|
|
83
|
+
allow="clipboard-write"
|
|
84
|
+
></iframe>
|
|
85
|
+
<script src="/embed/mira-chat-host.js" defer></script>
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
## Exports
|
|
89
|
+
|
|
90
|
+
| Import | Description |
|
|
91
|
+
|--------|-------------|
|
|
92
|
+
| `@hgt-weprotalk/mira-client` | `ChatWidget`, runtime helpers, types |
|
|
93
|
+
| `@hgt-weprotalk/mira-client/style.css` | Widget styles |
|
|
94
|
+
| `@hgt-weprotalk/mira-client/embed/*` | Static embed files |
|
|
95
|
+
|
|
96
|
+
## Configuration (runtime)
|
|
97
|
+
|
|
98
|
+
The widget does **not** read the host app's `.env`. Pass config via props or embed attributes:
|
|
99
|
+
|
|
100
|
+
| Prop / attribute | Description |
|
|
101
|
+
|------------------|-------------|
|
|
102
|
+
| `agentName` / `data-agent-name` | Agent identifier |
|
|
103
|
+
| `site` / `data-site` | Site code (e.g. `en`, `de`) |
|
|
104
|
+
| `apiBaseUrl` / `data-api-base-url` | Base URL for `{apiBaseUrl}/client/agentChat/*` |
|
|
105
|
+
| `locale` | UI locale (`en-US`, `zh-CN`) |
|
|
106
|
+
|
|
107
|
+
## Links
|
|
108
|
+
|
|
109
|
+
- [Repository](https://github.com/HGT-Weprotalk/mira-client)
|
|
110
|
+
- [Issues](https://github.com/HGT-Weprotalk/mira-client/issues)
|
|
111
|
+
|
|
112
|
+
> Maintainers: see [README.dev.md](./README.dev.md) for internal architecture and release docs.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
interface AgentAvatarProps {
|
|
2
|
+
avatar?: string;
|
|
3
|
+
name: string;
|
|
4
|
+
className?: string;
|
|
5
|
+
}
|
|
6
|
+
/** Agent 头像:支持 URL 图片或首字 fallback */
|
|
7
|
+
declare const AgentAvatar: ({ avatar, name, className }: AgentAvatarProps) => import("react").JSX.Element;
|
|
8
|
+
export default AgentAvatar;
|
|
9
|
+
//# sourceMappingURL=AgentAvatar.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"AgentAvatar.d.ts","sourceRoot":"","sources":["../../../src/components/chat-widget/AgentAvatar.tsx"],"names":[],"mappings":"AAAA,UAAU,gBAAgB;IACxB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;IACb,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAQD,qCAAqC;AACrC,QAAA,MAAM,WAAW,GAAI,6BAA6B,gBAAgB,gCAoBjE,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import type { HeaderStatusBadge } from "../../hooks/useHandoff";
|
|
2
|
+
interface ChatHeaderProps {
|
|
3
|
+
/** 当前视图:list 列表页 / chat 对话页 */
|
|
4
|
+
panelView: "list" | "chat";
|
|
5
|
+
/** Agent 名称 */
|
|
6
|
+
agentName: string;
|
|
7
|
+
/** Agent 头像 URL */
|
|
8
|
+
agentAvatar?: string;
|
|
9
|
+
/** 副标题文案(无状态徽标时展示) */
|
|
10
|
+
subtitle: string;
|
|
11
|
+
/** 状态徽标(优先于 subtitle) */
|
|
12
|
+
statusBadge?: HeaderStatusBadge | null;
|
|
13
|
+
/** 是否展示返回按钮 */
|
|
14
|
+
showBackButton?: boolean;
|
|
15
|
+
/** 返回按钮是否带未读红点 */
|
|
16
|
+
hasBackUnread?: boolean;
|
|
17
|
+
/** 返回回调 */
|
|
18
|
+
onBack?: () => void;
|
|
19
|
+
/** 关闭面板回调 */
|
|
20
|
+
onClose: () => void;
|
|
21
|
+
}
|
|
22
|
+
/** 面板顶栏:列表页居中 meta;对话页 leading 头像 + 名称 + 关闭 */
|
|
23
|
+
declare const ChatHeader: ({ panelView, agentName, agentAvatar, subtitle, statusBadge, showBackButton, hasBackUnread, onBack, onClose, }: ChatHeaderProps) => import("react").JSX.Element;
|
|
24
|
+
export default ChatHeader;
|
|
25
|
+
//# sourceMappingURL=ChatHeader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatHeader.d.ts","sourceRoot":"","sources":["../../../src/components/chat-widget/ChatHeader.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,wBAAwB,CAAC;AAKhE,UAAU,eAAe;IACvB,+BAA+B;IAC/B,SAAS,EAAE,MAAM,GAAG,MAAM,CAAC;IAC3B,eAAe;IACf,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB;IACnB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sBAAsB;IACtB,QAAQ,EAAE,MAAM,CAAC;IACjB,yBAAyB;IACzB,WAAW,CAAC,EAAE,iBAAiB,GAAG,IAAI,CAAC;IACvC,eAAe;IACf,cAAc,CAAC,EAAE,OAAO,CAAC;IACzB,kBAAkB;IAClB,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB,WAAW;IACX,MAAM,CAAC,EAAE,MAAM,IAAI,CAAC;IACpB,aAAa;IACb,OAAO,EAAE,MAAM,IAAI,CAAC;CACrB;AAED,+CAA+C;AAC/C,QAAA,MAAM,UAAU,GAAI,+GAUjB,eAAe,gCAoFjB,CAAC;AAEF,eAAe,UAAU,CAAC"}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
interface ChatInputProps {
|
|
3
|
+
/** 输入框当前值 */
|
|
4
|
+
value: string;
|
|
5
|
+
/** 占位文案 */
|
|
6
|
+
placeholder: string;
|
|
7
|
+
/** AI 正在响应(切换为停止按钮) */
|
|
8
|
+
isResponding: boolean;
|
|
9
|
+
/** 输入框禁用(转人工流程 / 关闭态等) */
|
|
10
|
+
isDisabled?: boolean;
|
|
11
|
+
/** 输入值变更回调 */
|
|
12
|
+
onChange: (value: string) => void;
|
|
13
|
+
/** 发送回调(Enter 或点击发送按钮) */
|
|
14
|
+
onSubmit: () => void;
|
|
15
|
+
/** 停止生成回调 */
|
|
16
|
+
onStop: () => void;
|
|
17
|
+
/** 输入框上方插槽(快捷入口等) */
|
|
18
|
+
topSlot?: ReactNode;
|
|
19
|
+
}
|
|
20
|
+
/** 底部输入区:自适应高度 textarea + 圆形发送 / 停止按钮 */
|
|
21
|
+
declare const ChatInput: ({ value, placeholder, isResponding, isDisabled, onChange, onSubmit, onStop, topSlot, }: ChatInputProps) => import("react").JSX.Element;
|
|
22
|
+
export default ChatInput;
|
|
23
|
+
//# sourceMappingURL=ChatInput.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatInput.d.ts","sourceRoot":"","sources":["../../../src/components/chat-widget/ChatInput.tsx"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAIf,UAAU,cAAc;IACtB,aAAa;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW;IACX,WAAW,EAAE,MAAM,CAAC;IACpB,uBAAuB;IACvB,YAAY,EAAE,OAAO,CAAC;IACtB,0BAA0B;IAC1B,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,cAAc;IACd,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,IAAI,CAAC;IAClC,0BAA0B;IAC1B,QAAQ,EAAE,MAAM,IAAI,CAAC;IACrB,aAAa;IACb,MAAM,EAAE,MAAM,IAAI,CAAC;IACnB,qBAAqB;IACrB,OAAO,CAAC,EAAE,SAAS,CAAC;CACrB;AAKD,yCAAyC;AACzC,QAAA,MAAM,SAAS,GAAI,wFAShB,cAAc,gCAiFhB,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ChatMessage as ChatMessageType } from "../../types/chat";
|
|
2
|
+
import type { DislikeReasonKey } from "../../types/feedback";
|
|
3
|
+
interface ChatMessageProps {
|
|
4
|
+
/** 单条消息数据 */
|
|
5
|
+
message: ChatMessageType;
|
|
6
|
+
/** AI 发送者展示名 */
|
|
7
|
+
agentDisplayName: string;
|
|
8
|
+
/** 是否为流式生成中的最后一条 assistant 气泡 */
|
|
9
|
+
isStreaming?: boolean;
|
|
10
|
+
/** 点赞该消息 */
|
|
11
|
+
onLike?: (messageId: string) => Promise<boolean>;
|
|
12
|
+
/** 点踩第一步:创建反馈 */
|
|
13
|
+
onDislikeInit?: (messageId: string) => Promise<boolean>;
|
|
14
|
+
/** 点踩第二步:补充原因(other 可带自定义文本) */
|
|
15
|
+
onDislikeReason?: (messageId: string, reasonKey: DislikeReasonKey, otherText?: string) => Promise<boolean>;
|
|
16
|
+
}
|
|
17
|
+
/** 单条聊天气泡:bubble-stack(sender + bubble + time) */
|
|
18
|
+
declare const ChatMessage: ({ message, agentDisplayName, isStreaming, onLike, onDislikeInit, onDislikeReason, }: ChatMessageProps) => import("react").JSX.Element;
|
|
19
|
+
export default ChatMessage;
|
|
20
|
+
//# sourceMappingURL=ChatMessage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatMessage.d.ts","sourceRoot":"","sources":["../../../src/components/chat-widget/ChatMessage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAK7D,UAAU,gBAAgB;IACxB,aAAa;IACb,OAAO,EAAE,eAAe,CAAC;IACzB,gBAAgB;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,iCAAiC;IACjC,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,YAAY;IACZ,MAAM,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACjD,iBAAiB;IACjB,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,gCAAgC;IAChC,eAAe,CAAC,EAAE,CAChB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,gBAAgB,EAC3B,SAAS,CAAC,EAAE,MAAM,KACf,OAAO,CAAC,OAAO,CAAC,CAAC;CACvB;AAED,kDAAkD;AAClD,QAAA,MAAM,WAAW,GAAI,qFAOlB,gBAAgB,gCA+DlB,CAAC;AAEF,eAAe,WAAW,CAAC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { ChatMessage as ChatMessageItem } from "../../types/chat";
|
|
2
|
+
import type { DislikeReasonKey } from "../../types/feedback";
|
|
3
|
+
import type { HandoffProfile } from "../../types/handoff";
|
|
4
|
+
interface ChatMessageListProps {
|
|
5
|
+
/** 当前展示的消息流(不含开场白 UI) */
|
|
6
|
+
messages: ChatMessageItem[];
|
|
7
|
+
/** Agent 开场白(固定 UI,不计入历史) */
|
|
8
|
+
openingStatement: string;
|
|
9
|
+
/** AI 发送者展示名 */
|
|
10
|
+
agentDisplayName: string;
|
|
11
|
+
/** AI 正在响应(流式生成中) */
|
|
12
|
+
isResponding: boolean;
|
|
13
|
+
/** 思考动画进行中 */
|
|
14
|
+
isThinking: boolean;
|
|
15
|
+
/** 当前思考阶段索引(0/1/2) */
|
|
16
|
+
thinkingStageIndex: number;
|
|
17
|
+
/** 是否展示转人工留资表单 */
|
|
18
|
+
showHandoffForm: boolean;
|
|
19
|
+
/** 是否展示等待条 */
|
|
20
|
+
showWaitingBanner: boolean;
|
|
21
|
+
/** 是否展示转人工失败提示 */
|
|
22
|
+
showHandoffFailed: boolean;
|
|
23
|
+
/** 转人工失败错误文案 */
|
|
24
|
+
handoffError?: string | null;
|
|
25
|
+
/** 是否展示会话已关闭提示 */
|
|
26
|
+
showClosedNotice?: boolean;
|
|
27
|
+
/** 本地缓存的留资信息(表单回填) */
|
|
28
|
+
storedProfile: HandoffProfile | null;
|
|
29
|
+
/** 正在创建 Zendesk 会话 */
|
|
30
|
+
connecting: boolean;
|
|
31
|
+
/** Zendesk SDK 初始化中 */
|
|
32
|
+
sdkLoading: boolean;
|
|
33
|
+
/** Zendesk SDK 已就绪 */
|
|
34
|
+
sdkReady: boolean;
|
|
35
|
+
/** 推荐问题列表(固定 UI,不计入历史) */
|
|
36
|
+
suggestedQuestions: string[];
|
|
37
|
+
/** 点击推荐问题 */
|
|
38
|
+
onSelectSuggestedQuestion: (question: string) => void;
|
|
39
|
+
/** 取消留资表单 / 关闭失败提示 */
|
|
40
|
+
onDismissHandoffForm: () => void;
|
|
41
|
+
/** 提交留资表单 */
|
|
42
|
+
onSubmitHandoffForm: (profile: HandoffProfile) => Promise<boolean | void>;
|
|
43
|
+
/** 转人工失败重试 */
|
|
44
|
+
onRetryHandoff?: () => void;
|
|
45
|
+
/** 点赞某条 AI 消息 */
|
|
46
|
+
onLikeMessage?: (messageId: string) => Promise<boolean>;
|
|
47
|
+
/** 点踩第一步:创建反馈 */
|
|
48
|
+
onDislikeInitMessage?: (messageId: string) => Promise<boolean>;
|
|
49
|
+
/** 点踩第二步:补充原因 */
|
|
50
|
+
onDislikeReasonMessage?: (messageId: string, reasonKey: DislikeReasonKey, otherText?: string) => Promise<boolean>;
|
|
51
|
+
/** 滚动到底部信号(递增计数驱动 effect) */
|
|
52
|
+
scrollToBottomSignal?: number;
|
|
53
|
+
/** 图片预览可见性变化回调 */
|
|
54
|
+
onPhotoPreviewVisibleChange?: (visible: boolean) => void;
|
|
55
|
+
}
|
|
56
|
+
/** 消息列表:顶栏固定开场白 + 推荐问,下方为会话历史与其它 UI */
|
|
57
|
+
declare const ChatMessageList: ({ messages, openingStatement, agentDisplayName, isResponding, isThinking, thinkingStageIndex, showHandoffForm, showWaitingBanner, showHandoffFailed, handoffError, showClosedNotice, storedProfile, connecting, sdkLoading, sdkReady, suggestedQuestions, onSelectSuggestedQuestion, onDismissHandoffForm, onSubmitHandoffForm, onRetryHandoff, onLikeMessage, onDislikeInitMessage, onDislikeReasonMessage, scrollToBottomSignal, onPhotoPreviewVisibleChange, }: ChatMessageListProps) => import("react").JSX.Element;
|
|
58
|
+
export default ChatMessageList;
|
|
59
|
+
//# sourceMappingURL=ChatMessageList.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatMessageList.d.ts","sourceRoot":"","sources":["../../../src/components/chat-widget/ChatMessageList.tsx"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,IAAI,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACvE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,qBAAqB,CAAC;AAO1D,UAAU,oBAAoB;IAC5B,yBAAyB;IACzB,QAAQ,EAAE,eAAe,EAAE,CAAC;IAC5B,6BAA6B;IAC7B,gBAAgB,EAAE,MAAM,CAAC;IACzB,gBAAgB;IAChB,gBAAgB,EAAE,MAAM,CAAC;IACzB,qBAAqB;IACrB,YAAY,EAAE,OAAO,CAAC;IACtB,cAAc;IACd,UAAU,EAAE,OAAO,CAAC;IACpB,sBAAsB;IACtB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,kBAAkB;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,cAAc;IACd,iBAAiB,EAAE,OAAO,CAAC;IAC3B,kBAAkB;IAClB,iBAAiB,EAAE,OAAO,CAAC;IAC3B,gBAAgB;IAChB,YAAY,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC7B,kBAAkB;IAClB,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,sBAAsB;IACtB,aAAa,EAAE,cAAc,GAAG,IAAI,CAAC;IACrC,sBAAsB;IACtB,UAAU,EAAE,OAAO,CAAC;IACpB,uBAAuB;IACvB,UAAU,EAAE,OAAO,CAAC;IACpB,sBAAsB;IACtB,QAAQ,EAAE,OAAO,CAAC;IAClB,0BAA0B;IAC1B,kBAAkB,EAAE,MAAM,EAAE,CAAC;IAC7B,aAAa;IACb,yBAAyB,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,CAAC;IACtD,sBAAsB;IACtB,oBAAoB,EAAE,MAAM,IAAI,CAAC;IACjC,aAAa;IACb,mBAAmB,EAAE,CAAC,OAAO,EAAE,cAAc,KAAK,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC,CAAC;IAC1E,cAAc;IACd,cAAc,CAAC,EAAE,MAAM,IAAI,CAAC;IAC5B,iBAAiB;IACjB,aAAa,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IACxD,iBAAiB;IACjB,oBAAoB,CAAC,EAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAO,CAAC,OAAO,CAAC,CAAC;IAC/D,iBAAiB;IACjB,sBAAsB,CAAC,EAAE,CACvB,SAAS,EAAE,MAAM,EACjB,SAAS,EAAE,gBAAgB,EAC3B,SAAS,CAAC,EAAE,MAAM,KACf,OAAO,CAAC,OAAO,CAAC,CAAC;IACtB,6BAA6B;IAC7B,oBAAoB,CAAC,EAAE,MAAM,CAAC;IAC9B,kBAAkB;IAClB,2BAA2B,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CAC1D;AAcD,uCAAuC;AACvC,QAAA,MAAM,eAAe,GAAI,mcA0BtB,oBAAoB,gCAiLtB,CAAC;AAEF,eAAe,eAAe,CAAC"}
|
|
@@ -0,0 +1,122 @@
|
|
|
1
|
+
import type { HeaderStatusBadge } from "../../hooks/useHandoff";
|
|
2
|
+
import type { ChatMessage } from "../../types/chat";
|
|
3
|
+
import type { DislikeReasonKey } from "../../types/feedback";
|
|
4
|
+
import type { HandoffProfile } from "../../types/handoff";
|
|
5
|
+
import type { PanelView, SessionListItem } from "../../types/history";
|
|
6
|
+
import type { QuickEntry } from "../../types/quickEntry";
|
|
7
|
+
interface ChatPanelProps {
|
|
8
|
+
/** 当前视图:list 会话列表 / chat 对话页 */
|
|
9
|
+
panelView: PanelView;
|
|
10
|
+
/** 顶栏展示的 Agent 名称(来自配置 name,如 Tammy Campbell2) */
|
|
11
|
+
agentName: string;
|
|
12
|
+
/** 消息列表中 AI 发送者展示名(统一为「智能客服」) */
|
|
13
|
+
messageAgentDisplayName: string;
|
|
14
|
+
/** Agent 头像 URL(无则用首字母 fallback) */
|
|
15
|
+
agentAvatar?: string;
|
|
16
|
+
/** 顶栏副标题文案 */
|
|
17
|
+
agentSubtitle: string;
|
|
18
|
+
/** 顶栏状态徽标(online/transferred/closed),优先于 subtitle 展示 */
|
|
19
|
+
headerStatusBadge?: HeaderStatusBadge | null;
|
|
20
|
+
/** 历史会话列表 */
|
|
21
|
+
sessions: SessionListItem[];
|
|
22
|
+
/** 会话列表加载中 */
|
|
23
|
+
isLoadingSessions: boolean;
|
|
24
|
+
/** 当前会话历史消息加载中 */
|
|
25
|
+
isLoadingHistory: boolean;
|
|
26
|
+
/** 是否展示返回按钮(对话页可返回列表时为 true) */
|
|
27
|
+
showBackButton: boolean;
|
|
28
|
+
/** 返回列表是否需二次确认(仅 TRANSFERRING / TRANSFERRED 会话) */
|
|
29
|
+
requiresLeaveHandoffConfirm: boolean;
|
|
30
|
+
/** 当前展示的消息流(AI + Zendesk 合并) */
|
|
31
|
+
messages: ChatMessage[];
|
|
32
|
+
/** 输入框当前值 */
|
|
33
|
+
inputValue: string;
|
|
34
|
+
/** 初始化中(拉取 Agent 配置 / 会话列表) */
|
|
35
|
+
isInitializing: boolean;
|
|
36
|
+
/** AI 正在响应(流式生成中) */
|
|
37
|
+
isResponding: boolean;
|
|
38
|
+
/** 思考动画进行中 */
|
|
39
|
+
isThinking: boolean;
|
|
40
|
+
/** 当前思考阶段索引(0/1/2) */
|
|
41
|
+
thinkingStageIndex: number;
|
|
42
|
+
/** 输入框是否禁用(转人工流程 / 关闭态 / 初始化中等) */
|
|
43
|
+
isInputDisabled: boolean;
|
|
44
|
+
/** 输入框占位文案(随通道 / 状态切换) */
|
|
45
|
+
inputPlaceholder: string;
|
|
46
|
+
/** 错误横幅文案(无则不展示) */
|
|
47
|
+
error: string | null;
|
|
48
|
+
/** 是否展示转人工留资表单 */
|
|
49
|
+
showHandoffForm: boolean;
|
|
50
|
+
/** 是否展示「正在接入人工客服」等待条 */
|
|
51
|
+
showWaitingBanner: boolean;
|
|
52
|
+
/** 是否展示转人工失败提示(含重试按钮) */
|
|
53
|
+
showHandoffFailed: boolean;
|
|
54
|
+
/** 转人工失败时的错误文案 */
|
|
55
|
+
handoffError?: string | null;
|
|
56
|
+
/** 是否展示会话已关闭只读提示 */
|
|
57
|
+
showClosedNotice?: boolean;
|
|
58
|
+
/** 返回按钮是否带未读红点 */
|
|
59
|
+
hasBackUnread?: boolean;
|
|
60
|
+
/** Zendesk 各 conversationId 的未读标记(列表角标用) */
|
|
61
|
+
zendeskUnreadByConversationId?: Record<string, boolean>;
|
|
62
|
+
/** 本地缓存的留资信息(表单回填用) */
|
|
63
|
+
storedProfile: HandoffProfile | null;
|
|
64
|
+
/** 正在创建 Zendesk 会话(转人工提交中) */
|
|
65
|
+
connecting: boolean;
|
|
66
|
+
/** Zendesk SDK 初始化中 */
|
|
67
|
+
sdkLoading: boolean;
|
|
68
|
+
/** Zendesk SDK 已就绪 */
|
|
69
|
+
sdkReady: boolean;
|
|
70
|
+
/** 推荐问题列表(固定 UI,不计入历史) */
|
|
71
|
+
suggestedQuestions: string[];
|
|
72
|
+
/** Agent 开场白(固定 UI,不计入历史) */
|
|
73
|
+
openingStatement: string;
|
|
74
|
+
/** 快捷入口列表(输入区上方,按 rounds 展示) */
|
|
75
|
+
quickEntries: QuickEntry[];
|
|
76
|
+
/** 是否展示快捷入口(AI 对话且未关闭) */
|
|
77
|
+
showQuickEntries: boolean;
|
|
78
|
+
/** 输入框值变更回调 */
|
|
79
|
+
onInputChange: (value: string) => void;
|
|
80
|
+
/** 发送消息回调 */
|
|
81
|
+
onSend: () => void;
|
|
82
|
+
/** 停止生成回调 */
|
|
83
|
+
onStop: () => void;
|
|
84
|
+
/** 关闭面板回调 */
|
|
85
|
+
onClose: () => void;
|
|
86
|
+
/** 新建对话 / 重置回调 */
|
|
87
|
+
onReset: () => void;
|
|
88
|
+
/** 返回列表回调 */
|
|
89
|
+
onBack: () => void;
|
|
90
|
+
/** 选中某个历史会话 */
|
|
91
|
+
onSelectSession: (session: SessionListItem) => void;
|
|
92
|
+
/** 删除某个会话 */
|
|
93
|
+
onDeleteSession: (sessionId: number) => void;
|
|
94
|
+
/** 点击推荐问题 */
|
|
95
|
+
onSelectSuggestedQuestion: (question: string) => void;
|
|
96
|
+
/** 取消留资表单 / 关闭失败提示 */
|
|
97
|
+
onDismissHandoffForm: () => void;
|
|
98
|
+
/** 提交留资表单 */
|
|
99
|
+
onSubmitHandoffForm: (profile: HandoffProfile) => Promise<boolean | void>;
|
|
100
|
+
/** 转人工失败后重试 */
|
|
101
|
+
onRetryHandoff?: () => void;
|
|
102
|
+
/** 点赞某条 AI 消息 */
|
|
103
|
+
onLikeMessage?: (messageId: string) => Promise<boolean>;
|
|
104
|
+
/** 点踩第一步:创建反馈并返回 feedbackId */
|
|
105
|
+
onDislikeInitMessage?: (messageId: string) => Promise<boolean>;
|
|
106
|
+
/** 点踩第二步:补充原因(other 可带自定义文本) */
|
|
107
|
+
onDislikeReasonMessage?: (messageId: string, reasonKey: DislikeReasonKey, otherText?: string) => Promise<boolean>;
|
|
108
|
+
/** iframe 模式下鼠标离开对话框区域回调 */
|
|
109
|
+
onDialogPointerLeave?: () => void;
|
|
110
|
+
/** 滚动到底部信号(递增计数驱动 effect) */
|
|
111
|
+
scrollToBottomSignal?: number;
|
|
112
|
+
/** 面板进入动画信号(递增计数,embed 模式由 panel-open 触发) */
|
|
113
|
+
panelEnterAnimationSignal?: number;
|
|
114
|
+
/** 面板是否正在播放关闭动画 */
|
|
115
|
+
isClosing?: boolean;
|
|
116
|
+
/** 图片预览可见性变化回调(iframe 模式通知宿主页) */
|
|
117
|
+
onPhotoPreviewVisibleChange?: (visible: boolean) => void;
|
|
118
|
+
}
|
|
119
|
+
/** 客服面板:会话列表 / 对话页 + 输入区 */
|
|
120
|
+
declare const ChatPanel: ({ panelView, agentName, messageAgentDisplayName, agentAvatar, agentSubtitle, headerStatusBadge, sessions, isLoadingSessions, isLoadingHistory, showBackButton, requiresLeaveHandoffConfirm, messages, inputValue, isInitializing, isResponding, isThinking, thinkingStageIndex, isInputDisabled, inputPlaceholder, error, showHandoffForm, showWaitingBanner, showHandoffFailed, handoffError, showClosedNotice, hasBackUnread, zendeskUnreadByConversationId, storedProfile, connecting, sdkLoading, sdkReady, suggestedQuestions, openingStatement, quickEntries, showQuickEntries, onInputChange, onSend, onStop, onClose, onReset, onBack, onSelectSession, onDeleteSession, onSelectSuggestedQuestion, onDismissHandoffForm, onSubmitHandoffForm, onRetryHandoff, onLikeMessage, onDislikeInitMessage, onDislikeReasonMessage, onDialogPointerLeave, scrollToBottomSignal, panelEnterAnimationSignal, isClosing, onPhotoPreviewVisibleChange, }: ChatPanelProps) => import("react").JSX.Element;
|
|
121
|
+
export default ChatPanel;
|
|
122
|
+
//# sourceMappingURL=ChatPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatPanel.d.ts","sourceRoot":"","sources":["../../../src/components/chat-widget/ChatPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
interface ChatToastProps {
|
|
2
|
+
/** 提示文案 */
|
|
3
|
+
message: string;
|
|
4
|
+
/** 是否展示 */
|
|
5
|
+
visible: boolean;
|
|
6
|
+
}
|
|
7
|
+
/** 气泡式短提示(如「已复制」) */
|
|
8
|
+
declare const ChatToast: ({ message, visible }: ChatToastProps) => import("react").JSX.Element | null;
|
|
9
|
+
export default ChatToast;
|
|
10
|
+
//# sourceMappingURL=ChatToast.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatToast.d.ts","sourceRoot":"","sources":["../../../src/components/chat-widget/ChatToast.tsx"],"names":[],"mappings":"AAAA,UAAU,cAAc;IACtB,WAAW;IACX,OAAO,EAAE,MAAM,CAAC;IAChB,WAAW;IACX,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,qBAAqB;AACrB,QAAA,MAAM,SAAS,GAAI,sBAAsB,cAAc,uCAUtD,CAAC;AAEF,eAAe,SAAS,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
interface ChatToastContextValue {
|
|
3
|
+
showToast: (message: string) => void;
|
|
4
|
+
toastMessage: string | null;
|
|
5
|
+
}
|
|
6
|
+
interface ChatToastProviderProps {
|
|
7
|
+
children: ReactNode;
|
|
8
|
+
}
|
|
9
|
+
/** 面板级 Toast 状态(供消息复制等场景触发) */
|
|
10
|
+
export declare const ChatToastProvider: ({ children }: ChatToastProviderProps) => import("react").JSX.Element;
|
|
11
|
+
/** 挂载在 ChatHeader 下方,水平居中展示 Toast */
|
|
12
|
+
export declare const ChatToastHost: () => import("react").JSX.Element | null;
|
|
13
|
+
export declare const useChatToast: () => ChatToastContextValue;
|
|
14
|
+
export {};
|
|
15
|
+
//# sourceMappingURL=ChatToastContext.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ChatToastContext.d.ts","sourceRoot":"","sources":["../../../src/components/chat-widget/ChatToastContext.tsx"],"names":[],"mappings":"AAAA,OAAO,EAOL,KAAK,SAAS,EACf,MAAM,OAAO,CAAC;AAKf,UAAU,qBAAqB;IAC7B,SAAS,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAID,UAAU,sBAAsB;IAC9B,QAAQ,EAAE,SAAS,CAAC;CACrB;AAED,+BAA+B;AAC/B,eAAO,MAAM,iBAAiB,GAAI,cAAc,sBAAsB,gCA8BrE,CAAC;AAEF,qCAAqC;AACrC,eAAO,MAAM,aAAa,0CAYzB,CAAC;AAEF,eAAO,MAAM,YAAY,QAAO,qBAQ/B,CAAC"}
|