# ai-boss Agent SDK（Flutter）· 对接说明

> 把「商家经营 AI 专家」（营销专家 / 数据专家）的对话与业务卡片，以 **drop-in 视图** 嵌入任意 Flutter app。
>
> 版本：`aiboss_agent_client` 0.1.0（纯 Dart 核心）+ `aiboss_agent_flutter` 0.1.0（Flutter UI）。

---

## 0. 三档集成，按需选择

| 档 | 适合 | 你写多少代码 | 看哪节 |
|---|---|---|---|
| **① 一键集成** | 想最快嵌入，默认 UI 即可 | 一个 widget、一行 | [§3](#3-一键集成基础) |
| **② 可定制 UI** | 要套自己品牌主题、把卡片拆进自有页面 | 自管会话 + 主题 + 回调 | [§5](#5-可定制-ui)–[§8](#8-会话与历史) |
| **③ 完全自定义** | 不用 Flutter / 自建 UI（Web、RN、原生…） | 直连后端 HTTP/SSE | [后端 API 参考](../../docs/api/agent-backend-http-api.md) |

档 ① ② 都基于本 Flutter SDK；档 ③ 跳过 SDK 直连后端，见独立的《后端 Agent HTTP/SSE API 参考》。三档共用同一套后端，可混用（如主流程用 ①，某个页面用 ② 自绘卡片）。

---

## 1. SDK 是什么

两个包，分层：

| 包 | 作用 | 依赖 |
|---|---|---|
| **`aiboss_agent_client`**（agent-client-dart） | 纯 Dart 核心：SSE 流式解码 + 事件/ActionCard 协议 + 会话/历史/反馈/记忆 REST + 营销 commit/action | 仅 `http`，无 Flutter |
| **`aiboss_agent_flutter`**（agent-client-flutter） | Flutter UI：一键门面 `AiBossAgentChat` + drop-in `AgentChatView` + 自适应主题 + 全套业务卡件。**重导出** Dart 核心 | `flutter` + 上者 |

一次接入即得：流式消息、内联 HITL（人审 / 澄清 / 补答）、营销活动卡（设计→编辑→发布→列表→详情→生命周期）、数据指标卡 + 趋势图、历史会话、三语（zh / en / ar，阿语自动 RTL）。

**两个专家**：

| agentId | 专家 | 能力 |
|---|---|---|
| `promo-designer` | 营销专家 | 设计并创建营销活动（秒杀 / 直减 / 全单折扣 / 首单），全生命周期管理 |
| `data-analyst` | 数据专家 | 经营数据问答与报表（净收入 / 成功交易 / 退款 + 趋势图、环同比） |

> `agentId` 省略（null）= 走**统一入口**，后端路由器按用户意图自动分流到对的专家。

---

## 2. 安装

SDK 以源码包发布。`pubspec.yaml` 三选一：

```yaml
dependencies:
  # ① 本地解压后 path 依赖（下载 tar 包解压到项目同级）
  aiboss_agent_flutter:
    path: ../packages/agent-client-flutter

  # ② git 依赖（私有仓库）
  # aiboss_agent_flutter:
  #   git:
  #     url: <repo-url>
  #     path: packages/agent-client-flutter

  # ③ 私有 pub 服务器
  # aiboss_agent_flutter: ^0.1.0
```

`aiboss_agent_flutter` 已重导出 `aiboss_agent_client`，**只需引一个**：

```dart
import 'package:aiboss_agent_flutter/aiboss_agent_flutter.dart';
```

- **Flutter / Dart 版本**：Flutter ≥ 3.x（Dart ≥ 3.0）。
- **本地化**：内置 zh/en/ar 文案，无需额外配置。
- **字体**：宿主自备；要正确显示中文/阿拉伯文，建议在宿主 `ThemeData` 配 `NotoSansSC` / `NotoSansArabic`。
- **平台**：纯 Dart + Flutter widget，无平台通道；Android / iOS / Web 均可。

---

## 3. 一键集成（基础）

一个 widget，传后端地址 + 商家身份即得到完整对话页。SDK 内部托管会话生命周期，并把营销卡的**确认 / 暂停 / 终止默认接到后端**——宿主无需写任何 HTTP，活动「设计→编辑→发布→管理」开箱即闭环。

```dart
import 'package:aiboss_agent_flutter/aiboss_agent_flutter.dart';
import 'package:flutter/material.dart';

class PromoPage extends StatelessWidget {
  const PromoPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('营销专家')),
      body: const AiBossAgentChat(
        baseUrl: 'https://api.example.com',   // ai-boss 后端根地址
        merchantId: 'M7676177520607',          // 商家 ID
        storeId: 'B17752062199591055',         // 门店 ID（可选）
        role: 'boss',                          // 角色（默认 boss）
        agentId: 'promo-designer',             // 省略 = 统一入口自动分流
        suggestions: ['做个全单9折活动', '我有哪些活动', '搞个招牌秒杀'],
        emptyHint: '和「营销专家」对话',
      ),
    );
  }
}
```

**就这些。** `AiBossAgentChat` 自己负责：建 `AgentSdk` + 会话、流式渲染、营销/数据卡渲染、commit/action 调后端、`dispose` 清理。

数据专家同理，换 `agentId: 'data-analyst'` + 对应 suggestions（如 `['本月净收入多少', '近7天净收入趋势']`）。

> 想覆盖某个默认行为（如自定义普通按钮处理、或自接 commit）？`AiBossAgentChat` 暴露同名可选回调 `onAction` / `onNbCampaign` / `onCampaignAction`，传了就用你的、不传用 SDK 默认。需要更深的控制（主题、历史抽屉、卡片拆分）请用档 ②。

---

## 4. 认证与后端地址

- **`baseUrl`**：ai-boss 后端根地址（**非**直连 minipos / NearBoss 网关；SDK 打 ai-boss 后端，后端经连接器透传到真实业务网关）。
- **租户头**：SDK 每个请求自动注入 `X-Merchant-Id` / `X-Store-Id`（scope=门店）/ `X-User-Id` / `X-Role`。`merchantId` = org，`storeId` = 门店 scope。
- **自定义鉴权**（如 JWT 透传）：档 ② 实现 `AuthProvider` 接口注入（见 §5）。

SDK 调用的后端端点（完整请求/响应见[后端 API 参考](../../docs/api/agent-backend-http-api.md)）：

| 端点 | 用途 |
|---|---|
| `POST /api/v1/agent/chat`（SSE） | 流式对话（conversation / token / step / action_card / final 事件） |
| `POST /api/v1/agent/nearboss/commit` | 营销活动 preview→commit（确认发布 / 存草稿） |
| `POST /api/v1/agent/nearboss/campaign/action` | 活动生命周期（暂停 / 恢复 / 终止） |
| `POST /api/v1/feedback` | 卡片反馈（有用 / 无用） |
| `GET /api/v1/conversations[/{id}/messages]` | 历史会话 / 消息 |

---

## 5. 可定制 UI

需要套品牌主题、把会话生命周期握在自己手里、或把业务卡片拆进自有页面时，用底层组件自行装配。

```dart
class _PromoPageState extends State<PromoPage> {
  late final AgentSdk _sdk;
  late final ChatController _controller;

  @override
  void initState() {
    super.initState();
    _sdk = AgentSdk(
      config: const SdkConfig(baseUrl: 'https://api.example.com'),
      auth: HeaderAuthProvider(merchantId: 'M123', storeId: 'B1', role: 'boss'),
    );
    _controller = ChatController(_sdk.newSession(agentId: 'promo-designer'));
  }

  @override
  void dispose() {
    _controller.dispose();
    _sdk.api.close();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return AgentChatView(
      controller: _controller,
      theme: const AgentTheme(            // ← 品牌主题（见下）
        userBubble: Color(0xFF111111),
        assistantBubble: Color(0xFFF4F4F5),
        userText: Color(0xFFFFFFFF),
        assistantText: Color(0xFF111111),
        accent: Color(0xFF111111),
        cardBackground: Color(0xFFFAFAFA),
        border: Color(0xFFE4E4E7),
        radius: 14,
      ),
      l10n: AgentL10n.zh,
      suggestions: const ['做个全单9折活动', '我有哪些活动'],
      // 营销卡确认 / 动作：调 SDK 核心方法（鉴权头自动注入）
      onNbCampaign: (r) async {
        final res = await _sdk.api.nearbossCommit(
            {'surface': 'campaign', 'action': r.action, 'params': r.params});
        return res.ok
            ? NbCommitOutcome.success(res.detail)
            : NbCommitOutcome.failure(res.message ?? '提交失败');
      },
      onCampaignAction: (r) async {
        final res = await _sdk.api.nearbossCampaignAction(
            {'op': r.op, 'id': r.id, if (r.confirmed) 'confirmed': true});
        return res.ok
            ? NbCommitOutcome.success(res.detail)
            : NbCommitOutcome.failure(res.message ?? '操作失败');
      },
    );
  }
}
```

### 主题

**自适应**：`AgentChatView` 省略 `theme` 时，自动从宿主 `Theme.of(context).colorScheme` 派生 `AgentTheme.fromContext(context)`——跟随宿主品牌色 / 深浅模式。

**显式覆盖**：传 `AgentTheme(...)`，8 个 token：

| token | 含义 |
|---|---|
| `userBubble` / `userText` | 用户气泡底 / 字 |
| `assistantBubble` / `assistantText` | 助手气泡底 / 字 |
| `accent` | 重点色（按钮、卡片强调） |
| `cardBackground` | 卡片容器底 |
| `border` | 分割线 |
| `radius` | 圆角（默认 12） |

### 国际化 + RTL

`AgentChatView(l10n: AgentL10n.zh | .en | .ar)`。传 `.ar` 自动 RTL 镜像。省略则取 `AgentLocalizations.of(context)`，回退 zh。

### 自定义鉴权

```dart
class JwtAuthProvider implements AuthProvider {
  @override
  Future<Map<String, String>> headers() async => {
    'Content-Type': 'application/json',
    'Authorization': 'Bearer ${await fetchToken()}',
  };
  @override String chatPath() => '/api/v1/agent/chat';
  @override String userTextKey() => 'message';
  @override String agentIdKey() => 'agent_id';
}
```

### 业务卡片单独使用

9 个卡件均可脱离 `AgentChatView` 单独嵌入自有页面：`ActionCardView`（按 `form.kind` 自动路由分发）、`NbCampaignFormView`（可编辑草稿）、`NbTypePickerView`（类型选择）、`NbCampaignListView`（活动列表）、`NbCampaignDetailView`（详情 + 生命周期）、`ChartView`、`MessageBubble`、`AgentHistoryDrawer`、`Composer`。各自接收对应协议对象 + `AgentTheme` + 回调。

---

## 6. 业务卡系统（营销专家）

营销活动全流程由 SDK 卡件渲染，对话里出现哪种卡由后端按 `form.kind` 决定：

| form.kind | 卡件 | 场景 |
|---|---|---|
| `nb_type_picker` | 类型选择卡 | 模糊「做个活动」→ 选 4 类之一 |
| `nb_campaign` | 可编辑草稿卡 | 设计好的草稿（可改字段、选商品、确认发布） |
| `nb_campaign_list` | 活动列表卡 | 「我有哪些活动」→ 点选看详情 |
| `nb_campaign_detail` | 详情卡 | 单个活动详情 + 生命周期按钮 |

**4 类活动**（注意枚举名与直觉相反，权威定义见[后端 API 参考](../../docs/api/agent-backend-http-api.md) 活动类型节）：

| 枚举 | 含义 | 关键参数 |
|---|---|---|
| `FLASH_SALE` | 秒杀 | 选品 + 秒杀价 |
| `DIRECT_AMOUNT_OFF` | 订单直减 | `directAmount` 1–999（Save AED N）+ 门槛 |
| `ORDER_DISCOUNT` | 全单折扣 | `discountValue` 10–99（**实付** X%，即 9 折 = 90） |
| `FIRST_ORDER_DISCOUNT` | 首单优惠 | `discountType` 固定/折扣 + 值 + 门槛 |

**确认 / 动作的两种接法**：

- **档 ①（一键）**：`AiBossAgentChat` 已默认接好，无需写代码。
- **档 ②（可定制）**：传 `onNbCampaign` / `onCampaignAction`，内部调 `sdk.api.nearbossCommit(...)` / `nearbossCampaignAction(...)`（见 §5 代码）。返回 `NbCommitOutcome` 决定卡片切「已发布」态或就地红字报错。

> 生命周期按钮由后端返回的 `availableActions` 驱动（按状态 DRAFT / PENDING / ACTIVE / PAUSED / ENDED）。SDK 只渲染开放的 PAUSE / RESUME / TERMINATE；TERMINATE 须二次确认（首次返回 `AIGENT_CONFIRM_REQUIRED`，带 `confirmed: true` 重提）。

---

## 7. 数据卡（数据专家）

数据专家返回的卡含 `indicators`（指标行）+ 可选 `chart`（趋势折线 / 环比柱）。SDK `ActionCardView` 自动渲染，**无需宿主回调**。

- 指标全部来自接口（**零推算**原则，SDK 与后端都不自算数字）。
- 数据专家答 3 指标域：净收入 / 成功交易 / 退款；趋势走 `chart`（line，7 点）。

---

## 8. 会话与历史

```dart
sdk.newSession(agentId: ..., conversationId: ...); // 新会话
sdk.resumeSession(conversationId, agentId: ...);   // 带 id 续聊（不预载）
await sdk.openConversation(conversationId);          // 拉历史消息种入新会话，可继续追问
sdk.api.listConversations();                         // 历史会话列表 REST
sdk.api.listMessages(conversationId);                // 历史消息 REST
```

`AgentHistoryDrawer`（`history_list.dart`）可直接放进 `Scaffold.endDrawer` 做历史会话抽屉。

---

## 9. 错误处理

| 来源 | 表现 | 处理 |
|---|---|---|
| 卡片操作失败 | `NbCommitResult.ok=false` / `NbCommitOutcome.failure(message)` | 卡片就地红字展示 `message`（已是可读中文） |
| 业务校验 | `error_code`：`MKT_*`（如「全单折扣须 10–99」）、`AIGENT_INVALID_ACTIVITY_TYPE` | 转述给商家、引导改参数重提 |
| 预览失效 | `AIGENT_PREVIEW_EXPIRED` / `TOKEN_EXPIRED` | 让用户重发一次（重走 preview） |
| 需二次确认 | `AIGENT_CONFIRM_REQUIRED` | 带 `confirmed: true` 重提（终止活动 / 删除会员） |
| LLM 不可用 | SSE `error` 事件 | `AgentChatView` 渲染错误气泡，不击穿 UI |
| 网络异常 | `NbCommitResult.statusCode == 0` | `message` 含「网络错误」，提示重试 |

完整错误码表见[后端 API 参考](../../docs/api/agent-backend-http-api.md)。

---

## 10. 故障排查（FAQ）

**Q：卡片不出，只有纯文字回答？**
A：确认 `agentId` 传对（`promo-designer` / `data-analyst`），且后端 `AIBOSS_BIZ_PROFILE=nearboss`（否则走 mock 档，字段/语言不同）。

**Q：活动「确认发布」点了没反应 / 报「网络错误」？**
A：档 ① 已内置 commit；档 ② 检查 `onNbCampaign` 是否真的调了 `sdk.api.nearbossCommit`。`statusCode==0` 表示根本没连上后端——查 `baseUrl` 与网络可达性。

**Q：返回 401 / 无权限？**
A：缺 `X-Merchant-Id`。一键档确认传了 `merchantId`；自定义 `AuthProvider` 确认 `headers()` 带齐租户头。

**Q：中文 / 阿拉伯文显示成方框？**
A：宿主未配覆盖该字符集的字体。在 `ThemeData` 里配 `NotoSansSC` / `NotoSansArabic`。

**Q：流式回答中途断了？**
A：SSE 长连接受代理 / 网关超时影响。后端 `/agent/chat` 读超时建议 ≥ 300s；若经 nginx 反代，关 `proxy_buffering`。

**Q：阿语界面没有 RTL？**
A：传 `l10n: AgentL10n.ar`（一键档传 `l10n` 参数）。SDK 据此自动 `Directionality.rtl`。

---

## 11. 公开 API 速查

**`aiboss_agent_client`**（纯 Dart）：`AgentSdk` · `SdkConfig` · `AuthProvider` / `HeaderAuthProvider` / `BearerAuthProvider` · `ChatSession`（`.send` / `.states` / `.phase`）· `AgentApi`（`nearbossCommit` / `nearbossCampaignAction` / `listConversations` / `listMessages` / `sendFeedback` / `recallMemory`）· `NbCommitResult` · `ActionCard` / `ActionButton` / `Indicator` / `ChartSpec` · 协议事件模型。

**`aiboss_agent_flutter`**（含上者全部）：**`AiBossAgentChat`**（一键门面）· `AgentChatView`（drop-in）· `ChatController` · `AgentTheme` · `AgentL10n` / `AgentLocalizations` · 卡件 `ActionCardView` / `NbCampaignFormView` / `NbCampaignListView` / `NbCampaignDetailView` / `NbTypePickerView` / `NbProductPickerSheet` / `ChartView` / `ClarifyView` / `MessageBubble` / `Composer` / `AgentHistoryDrawer` / `MarkdownText`。回调结果：`NbCampaignResult` / `NbCampaignActionResult` / `NbCommitOutcome` / `CampaignFormResult`。

---

## 12. 版本

| 包 | 版本 |
|---|---|
| aiboss_agent_client | 0.1.0 |
| aiboss_agent_flutter | 0.1.0 |

0.1.0 起新增一键门面 `AiBossAgentChat` + 核心 `AgentApi.nearbossCommit` / `nearbossCampaignAction`。

不用 Flutter？完全自定义 UI 直连后端见《[后端 Agent HTTP/SSE API 参考](../../docs/api/agent-backend-http-api.md)》。问题 / 对接支持联系 ai-boss 团队。
