npm package: @skillpet/chat-react
Description: React SSE 流式 AI 对话面板组件 — 内置 i18n（7 语言）、品牌色主题、子智能体支持
Latest version: 0.5.0

# @skillpet/chat-react

<p align="center">
  <strong>React SSE 流式 AI 对话面板组件 — 内置 i18n（7 语言）、品牌色主题、子智能体支持。</strong>
</p>

<p align="center">
  <a href="https://www.npmjs.com/package/@skillpet/chat-react"><img src="https://img.shields.io/npm/v/@skillpet/chat-react.svg" alt="npm version"></a>
  <a href="https://github.com/skillpet/skillpet-chat/blob/main/LICENSE"><img src="https://img.shields.io/npm/l/@skillpet/chat-react.svg" alt="license"></a>
</p>

---

## 功能特性

- SSE 流式对话，实时显示 AI 思考过程与工具调用
- 子智能体（consult agent）多轮对话与工具步骤展示
- 结构化提问（ask_user）表单交互
- 斜杠指令面板
- 内置 7 种语言（zh-CN、zh-TW、en、ja、ko、es、fr）
- 蓝色品牌色默认主题，支持深色/浅色模式
- CSS 变量完全自定义配色
- Markdown 渲染（GFM 语法）
- React 18+ 兼容

## 安装

```bash
npm install @skillpet/chat-react
```

自动安装 `@skillpet/chat-core`（类型/SSE/i18n）及 `lucide-react`、`react-markdown` 等依赖。

## 快速开始

```tsx
import { ChatPanel } from "@skillpet/chat-react";
import "@skillpet/chat-core/styles.css";

function App() {
  return (
    <ChatPanel
      projectId="my-project"
      config={{
        api: {
          baseUrl: "/api/chat",
          deleteConversationUrl: "/api/chat/conversation",
        },
        getAccessToken: () => localStorage.getItem("token"),
      }}
    />
  );
}
```

## 三层 API

### Layer 1: 开箱即用

| 导出 | 说明 |
|------|------|
| `ChatPanel` | 主组件，包含完整聊天 UI |
| `ChatProvider` | 通过 Context 注入配置 |
| `useChatConfig` | 读取 Context 配置 |
| `setChatLanguage` | 切换 i18n 语言 |

### Layer 2: 自定义组合

| 导出 | 说明 |
|------|------|
| `useChatPanel` | Headless hook，返回所有状态和操作 |
| `MessageBubble` | 消息气泡组件 |
| `AskUserBlock` | 结构化表单组件 |
| `ThinkingBlock` | AI 思考过程组件 |
| `SlashCommandPalette` | 斜杠指令面板组件 |

### Layer 3: 底层原语

| 导出 | 说明 |
|------|------|
| `processSSEStream` | SSE 流处理（从 core 重导出） |
| `parseHistoryMessages` | 历史消息解析（从 core 重导出） |

## ChatPanel Props

| Prop | 类型 | 必选 | 说明 |
|------|------|------|------|
| `projectId` | `string` | 是 | 项目/会话 ID |
| `config` | `ChatPanelConfig` | | API 地址、鉴权等配置 |
| `quickStarters` | `string[]` | | 空状态快捷开场文案 |
| `emptyState` | `ChatPanelEmptyState` | | 自定义空状态图标/标题/副标题 |
| `extraSlashCommands` | `SlashCommand[]` | | 追加斜杠指令 |
| `onStatusChange` | `() => void` | | SSE 流结束回调 |
| `onResourceUpdated` | `(key, snapshot?) => void` | | 资源更新回调 |
| `className` | `string` | | 追加 CSS 类名 |

## ChatPanelConfig

| 字段 | 类型 | 必选 | 说明 |
|------|------|------|------|
| `api.baseUrl` | `string` | 是 | SSE / 历史接口基础 URL |
| `api.deleteConversationUrl` | `string` | 是 | 删除对话 URL |
| `getAccessToken` | `() => string \| null \| Promise` | 是 | 获取 Bearer token |
| `accessToken` | `string \| null` | | token 标识（变化时重载历史） |
| `lang` | `string` | | 语言代码 |
| `components` | `ChatPanelComponents` | | UI 组件开关 |

## 多配置共享

```tsx
import { ChatProvider, ChatPanel } from "@skillpet/chat-react";

<ChatProvider config={config}>
  <ChatPanel projectId="project-a" />
  <ChatPanel projectId="project-b" />
</ChatProvider>
```

## 自定义 UI

```tsx
import { useChatPanel, MessageBubble } from "@skillpet/chat-react";
import "@skillpet/chat-core/styles.css";

function CustomChat({ config }) {
  const chat = useChatPanel({ projectId: "xxx", config });
  return (
    <div className="skillpet-chat">
      {chat.messages.map((msg) => (
        <MessageBubble key={msg.id} msg={msg} />
      ))}
    </div>
  );
}
```

## 主题定制

包自带蓝色品牌色默认主题。深色模式通过 `.dark` 类或 `[data-theme="dark"]` 自动切换。

```css
.skillpet-chat {
  --skillpet-chat-primary: oklch(0.6 0.22 145); /* 自定义主色 */
}
```

### shadcn 桥接

```css
.skillpet-chat {
  --skillpet-chat-primary: var(--primary);
  --skillpet-chat-background: var(--background);
  --skillpet-chat-foreground: var(--foreground);
  --skillpet-chat-muted: var(--muted);
  --skillpet-chat-muted-foreground: var(--muted-foreground);
  --skillpet-chat-border: var(--border);
  --skillpet-chat-radius: var(--radius);
}
```

## i18n

```ts
import { setChatLanguage } from "@skillpet/chat-react";
setChatLanguage("en"); // zh-CN | zh-TW | en | ja | ko | es | fr
```

## CDN 使用

```html
<script crossorigin src="https://unpkg.com/react@18/umd/react.production.min.js"></script>
<script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.production.min.js"></script>
<script src="https://unpkg.com/@skillpet/chat-core/dist/index.umd.js"></script>
<script src="https://unpkg.com/@skillpet/chat-react/dist/index.umd.js"></script>
<link rel="stylesheet" href="https://unpkg.com/@skillpet/chat-core/dist/skillpet-chat.css" />

<script>
  const { ChatPanel } = SkillpetChatReact;
  // ...
</script>
```

## License

[MIT](https://github.com/skillpet/skillpet-chat/blob/main/LICENSE)