@puyinkai/xiaobao-cli 0.1.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.
Files changed (41) hide show
  1. package/README.md +81 -0
  2. package/dist/api-Ccj5dLMo.mjs +100 -0
  3. package/dist/api-client-DwySN6x-.mjs +75 -0
  4. package/dist/audio-VmDQMq59.mjs +14 -0
  5. package/dist/auth-ChHvqjCS.mjs +15 -0
  6. package/dist/cli.d.mts +1 -0
  7. package/dist/cli.mjs +30 -0
  8. package/dist/consultant-ABFTL_jx.mjs +11 -0
  9. package/dist/customer-DtSnQqy_.mjs +11 -0
  10. package/dist/device-flow-BgsZipYA.mjs +166 -0
  11. package/dist/focus-BDYuP2vZ.mjs +11 -0
  12. package/dist/format-BZvv8lYc.mjs +610 -0
  13. package/dist/headers-D79npewp.mjs +11 -0
  14. package/dist/list--o5Q_PI8.mjs +80 -0
  15. package/dist/list-Bkyi95YO.mjs +76 -0
  16. package/dist/list-CGACp0y-.mjs +76 -0
  17. package/dist/list-CVKSGNu4.mjs +91 -0
  18. package/dist/list-CzB9_Jho.mjs +91 -0
  19. package/dist/list-DW6KAAaC.mjs +92 -0
  20. package/dist/list-iwd9cH1I.mjs +41 -0
  21. package/dist/login-BwkrByMm.mjs +91 -0
  22. package/dist/logout-BJm9pjje.mjs +49 -0
  23. package/dist/project-Ba05YzJ5.mjs +14 -0
  24. package/dist/project-store-Bz5kf-EI.mjs +62 -0
  25. package/dist/qa-D-B9FV9W.mjs +60 -0
  26. package/dist/resistance-Cf7zsdB3.mjs +11 -0
  27. package/dist/text-BLH4R3xv.mjs +49 -0
  28. package/dist/token-store-CHZ_rJQk.mjs +85 -0
  29. package/dist/use-DV9Ii3Tn.mjs +61 -0
  30. package/dist/util-DgwkUfV9.mjs +46 -0
  31. package/dist/visit-Ct3Vea8I.mjs +11 -0
  32. package/dist/whoami-DwTHvI4B.mjs +51 -0
  33. package/package.json +36 -0
  34. package/skills/wangxiaobao-audio-query/SKILL.md +252 -0
  35. package/skills/wangxiaobao-audio-wiki/SKILL.md +332 -0
  36. package/skills/wangxiaobao-customer-focus-query/SKILL.md +213 -0
  37. package/skills/wangxiaobao-customer-query/SKILL.md +214 -0
  38. package/skills/wangxiaobao-customer-resistance-query/SKILL.md +211 -0
  39. package/skills/wangxiaobao-quick-qa/SKILL.md +238 -0
  40. package/skills/wangxiaobao-switch-project/SKILL.md +179 -0
  41. package/skills/wangxiaobao-visit-query/SKILL.md +249 -0
@@ -0,0 +1,179 @@
1
+ ---
2
+ name: wangxiaobao-switch-project
3
+ description: |
4
+ 查询和切换旺小宝项目。展开当前账号下所有租户与项目,让用户选择,然后调
5
+ `xiaobao_switch_project` tool 把选中条目持久化到 plugin 全局激活项目状态文件
6
+ `~/.openclaw/state/wangxiaobao/active-project.json`(权限 0600)。后续所有
7
+ 需要 tenant/project 上下文的 tool(list-audio / quick-qa 等)
8
+ 都从这个文件读取,**不再需要传 tenantId/projectId 入参**。
9
+
10
+ **当以下情况时使用此 Skill**:
11
+ (1) 用户提到"切换项目"、"选项目"、"换项目"、"项目列表"、"选择租户和项目"
12
+ (2) 任意 tool 返回 `error: 'NO_ACTIVE_PROJECT'` —— 这是 plugin 的标准
13
+ 未激活信号,要求重新走切换项目流程
14
+ (3) 用户准备同步录音 / 出报告 / 调旺小宝租户隔离 API,但还没设置过激活项目
15
+ (4) 用户想看自己有权限访问哪些租户和项目
16
+ (5) 用户直接点名某个项目("切到XX项目")—— 带 keyword 精确收敛后再确认
17
+ ---
18
+
19
+ > **Host-agnostic CLI skill** — 本 skill 假设 `xiaobao-cli` 已装到 PATH
20
+ > (`npm i -g @puyinkai/xiaobao-cli` 或 `npx -y @puyinkai/xiaobao-cli`)。
21
+ > Agent 通过 shell 工具(Bash / Run / Shell)执行命令、读 **stdout JSON** 消费;
22
+ > stderr 是进度/错误提示。退出码 0 = 成功,非 0 = 业务/网络错(错误对象同时打到 stdout 可解析)。
23
+ >
24
+ > CLI 14 个子命令跟 openclaw-xiaobao plugin 14 个 tool **1:1 等价**,返回 JSON
25
+ > 结构完全一致(`{status, ok, data: {...}}`)。skill 里看到的 `resp.data.data.xxx`
26
+ > 取数路径直接对 stdout JSON 用 `jq` / `JSON.parse` 即可。
27
+ >
28
+ > **plugin tool → CLI 命令翻译表(数组参数走逗号分隔)**:
29
+ >
30
+ > | plugin tool | CLI 命令 |
31
+ > | --- | --- |
32
+ > | `xiaobao_authorize { force? }` | `xiaobao-cli auth login [--force]` |
33
+ > | `xiaobao_whoami` | `xiaobao-cli auth whoami` |
34
+ > | `xiaobao_logout` | `xiaobao-cli auth logout` |
35
+ > | `xiaobao_list_projects { keyword? }` | `xiaobao-cli project list [--keyword <kw>]` |
36
+ > | `xiaobao_switch_project { tenantId, tenantName, projectId, projectName }` | `xiaobao-cli project use --tenant-id ... --tenant-name ... --project-id ... --project-name ...` |
37
+ > | `xiaobao_list_consultants` | `xiaobao-cli consultant list` |
38
+ > | `xiaobao_list_audio { fromDate, toDate, userId?, userIdList?, page, size }` | `xiaobao-cli audio list --from "..." --to "..." [--user-id ...] [--user-id-list a,b,c] [--page N] [--size N]` |
39
+ > | `xiaobao_get_audio_text { audioId }` | `xiaobao-cli audio text <audioId>` |
40
+ > | `xiaobao_list_customers { ... }` | `xiaobao-cli customer list [--user-id] [--user-name] [--customer-name] [--customer-phone] [--portrait] [--from] [--to] [--page] [--size]` |
41
+ > | `xiaobao_list_visits { ... }` | `xiaobao-cli visit list [--customer-id] [--customer-name] [--from] [--to] [--page] [--size]` |
42
+ > | `xiaobao_list_customer_focus { visitIds, customerIds, audioIds, category, classification, fromDate, toDate, ... }` | `xiaobao-cli focus list [--visit-ids a,b] [--customer-ids a,b] [--audio-ids a,b] [--category ...] [--classification ...] [--from ...] [--to ...]` |
43
+ > | `xiaobao_list_customer_resistance { ... }` | `xiaobao-cli resistance list [同 focus]` |
44
+ > | `xiaobao_quick_qa { prompt, threadId? }` | `xiaobao-cli qa "<prompt>" [--thread-id ...]` |
45
+ > | `xiaobao_api { method, path, query, body, headers }` | `xiaobao-cli api <METHOD> <PATH> [--query k=v] [--body '<json>'] [--headers k=v]` |
46
+ >
47
+ > 用 `--format toon` 切到 TOON(uniform 数组省 30-50% token,LLM 上下文优化);
48
+ > 用 `--format json`(默认)保持 JSON。state 路径:`~/.xiaobao/`(fallback 读 `~/.openclaw/state/wangxiaobao/`)。
49
+
50
+
51
+ # 旺小宝项目切换
52
+
53
+ 把当前账号下的「租户 + 项目」枚举出来让用户挑一个,确认后调
54
+ `xiaobao_switch_project` tool 写入 plugin 全局状态文件,供后续 tool 读取。
55
+
56
+ ## 执行前必读
57
+
58
+ - 必须先通过 `xiaobao_authorize` 完成 OAuth 登录;token 没拿到时本 skill 不能继续
59
+ - **不要**自己 fs.writeFile 写 `.env` 或任何文件——状态落地走
60
+ `xiaobao_switch_project` tool,由 plugin 统一管理权限和路径
61
+ - 多个项目时**必须让用户挑**,绝对不要自动选择第一个;只有一个项目时才可以自动选
62
+ - 用户确认前不要调 switch-project tool
63
+
64
+ ---
65
+
66
+ ## 流程
67
+
68
+ ### 第 1 步:拿到项目列表
69
+
70
+ 调用 plugin tool `xiaobao_list_projects`。**可选 `keyword` 参数**对租户名/
71
+ 项目名做包含模糊过滤(大小写不敏感):
72
+
73
+ - 用户已经说了想要哪个项目(如"切到盛世禧悦")→ **直接带 `keyword`**:
74
+ `xiaobao_list_projects { keyword: "盛世禧悦" }`,收敛后通常只剩 1-2 条,
75
+ 省去让用户从一长串里挑
76
+ - 用户只说"换个项目""看看有哪些" → 不带 keyword,拉全量
77
+ - 账号项目很多、全量列表太长 → 提示用户给个关键字,再带 `keyword` 重查
78
+
79
+ 返回结构:
80
+ ```json
81
+ {
82
+ "projects": [
83
+ { "tenantId": "1234", "tenantName": "示例租户A", "projectId": "9001", "projectName": "示例项目甲" },
84
+ { "tenantId": "1234", "tenantName": "示例租户A", "projectId": "9002", "projectName": "示例项目乙" },
85
+ { "tenantId": "5678", "tenantName": "示例租户B", "projectId": "9101", "projectName": "示例项目丙" }
86
+ ],
87
+ "count": 3
88
+ }
89
+ ```
90
+
91
+ 如果 `count == 0`:
92
+
93
+ - **带了 `keyword`** → 是关键字没命中,不是没权限。提示用户换更短的关键字、
94
+ 或不带 keyword 看全量;**不要**直接说"没有项目"
95
+ - **没带 `keyword`** → 账号确实没有可访问的项目,结束
96
+
97
+ 如果 tool 报错(401 / token 过期等),先调 `xiaobao_authorize { force: true }` 重新登录,再重试一次。
98
+
99
+ ### 第 2 步:展示并让用户选
100
+
101
+ 按"租户 → 项目"分组渲染,编号从 1 开始:
102
+
103
+ ```
104
+ [示例租户A]
105
+ 1. 示例项目甲 (projectId=9001)
106
+ 2. 示例项目乙 (projectId=9002)
107
+
108
+ [示例租户B]
109
+ 3. 示例项目丙 (projectId=9101)
110
+ ```
111
+
112
+ - **多个项目**:让用户回复编号或项目名。用户回复后,**再显示一次「即将激活的
113
+ 租户/项目信息」并请用户确认 y/n**,确认后才调 `xiaobao_switch_project` tool
114
+ - **仅一个项目**:直接告诉用户"账号下只有一个项目 X,是否激活?"等用户确认即可
115
+
116
+ ### 第 3 步:调 `xiaobao_switch_project` tool 落地
117
+
118
+ ```json
119
+ {
120
+ "tenantId": "<选中条目的 tenantId>",
121
+ "tenantName": "<选中条目的 tenantName>",
122
+ "projectId": "<选中条目的 projectId>",
123
+ "projectName": "<选中条目的 projectName>"
124
+ }
125
+ ```
126
+
127
+ 成功返回:
128
+
129
+ ```json
130
+ {
131
+ "success": true,
132
+ "activeProject": {
133
+ "tenantId": "1234",
134
+ "tenantName": "示例租户A",
135
+ "projectId": "9001",
136
+ "projectName": "示例项目甲",
137
+ "updatedAt": "2026-05-13T..."
138
+ },
139
+ "message": "已切换到「示例租户A / 示例项目甲」"
140
+ }
141
+ ```
142
+
143
+ 状态写到 `~/.openclaw/state/wangxiaobao/active-project.json`,权限 0600。
144
+
145
+ ---
146
+
147
+ ## 输出模板
148
+
149
+ 成功后回复用户(中文):
150
+
151
+ ```
152
+ ✅ 已切换到「示例租户A / 示例项目甲」
153
+ 租户 ID: 1234
154
+ 项目 ID: 9001
155
+ 状态保存在 ~/.openclaw/state/wangxiaobao/active-project.json
156
+
157
+ 下一步可以:
158
+ - 查录音:让我帮你跑 wangxiaobao-audio-query / wangxiaobao-audio-wiki skill
159
+ - 快问 AI:让我帮你跑 wangxiaobao-quick-qa skill
160
+ ```
161
+
162
+ ---
163
+
164
+ ## 仅查看不切换
165
+
166
+ 用户只想"看看有哪些项目"而**不切换**时,调 `xiaobao_list_projects`(必要时带
167
+ `keyword` 收敛)渲染列表后停下来,不要调 `xiaobao_switch_project` tool。
168
+
169
+ ---
170
+
171
+ ## 常见错误与排查
172
+
173
+ | 错误现象 | 根本原因 | 解决方案 |
174
+ |---|---|---|
175
+ | `xiaobao_list_projects` 返回 401 / token 过期 | 没登录或 refresh 失败 | 调 `xiaobao_authorize { force: true }` 重新走 device flow |
176
+ | `count == 0`(没带 keyword) | 账号无任何租户/项目权限 | 让用户找管理员加权限,本 skill 不继续 |
177
+ | `count == 0`(带了 keyword) | 关键字没匹配到任何项目 | 换更短关键字 / 不带 keyword 看全量,别直接说"没项目" |
178
+ | 用户输入的编号超出范围 | 选错了 | 重新提示当前可选编号区间 |
179
+ | 其他 tool 仍返回 `NO_ACTIVE_PROJECT` | 没调 switch-project tool 落地 | 检查 `~/.openclaw/state/wangxiaobao/active-project.json` 是否存在,重新走本 skill |
@@ -0,0 +1,249 @@
1
+ ---
2
+ name: wangxiaobao-visit-query
3
+ description: |
4
+ 旺小宝来访分页查询 skill:按 **客户 ID / 客户姓名 / 来访时间** 分页查
5
+ 来访记录(含接待顾问 / **录音列表 audios** / 盘客状态 / 话术命中等)。
6
+ **只读、不写文件、无副作用**。对应 `xiaobao_list_visits` tool。
7
+ 排序固定 visit_time DESC。每条 visit 已直接带录音列表,问"这次来访打了
8
+ 几条录音 / 录音多长"时**不必再调** `xiaobao_list_audio`。
9
+
10
+ **当以下情况时使用此 Skill**:
11
+ (1) 用户问"今天到访"、"本周来访列表"、"最近来访"
12
+ (2) 用户问"李女士最近几次来访"——**先调 `xiaobao_list_customers` 反查
13
+ customerId(wang_id),再调本 skill 带 customerId 精确过滤**(更准)
14
+ (3) 用户问"上周哪些客户来访"——`fromDate` / `toDate` 时间窗
15
+ (4) 用户问"姓张的客户什么时候来过"——`customerName` 模糊(后端 JOIN 客户表)
16
+ (5) 用户问"某次到访打了几条录音 / 录音多长 / 录音 fileUrl"——看
17
+ `audioCount` + `audios[]`(直接包含录音元数据 + 签名 URL);
18
+ "盘客完成没"——看 `isPankeCompleted` / `pankeStatus`
19
+ (6) 任何"看到访名单 / 接待记录 / 话术命中"的开放式查询
20
+
21
+ **不要用本 skill 的场景**:
22
+ - 用户要的是客户**画像** / 标签 → 走 `wangxiaobao-customer-query`
23
+ - 用户问录音元数据 / 文本 → 走 `wangxiaobao-audio-query`
24
+ ---
25
+
26
+ > **Host-agnostic CLI skill** — 本 skill 假设 `xiaobao-cli` 已装到 PATH
27
+ > (`npm i -g @puyinkai/xiaobao-cli` 或 `npx -y @puyinkai/xiaobao-cli`)。
28
+ > Agent 通过 shell 工具(Bash / Run / Shell)执行命令、读 **stdout JSON** 消费;
29
+ > stderr 是进度/错误提示。退出码 0 = 成功,非 0 = 业务/网络错(错误对象同时打到 stdout 可解析)。
30
+ >
31
+ > CLI 14 个子命令跟 openclaw-xiaobao plugin 14 个 tool **1:1 等价**,返回 JSON
32
+ > 结构完全一致(`{status, ok, data: {...}}`)。skill 里看到的 `resp.data.data.xxx`
33
+ > 取数路径直接对 stdout JSON 用 `jq` / `JSON.parse` 即可。
34
+ >
35
+ > **plugin tool → CLI 命令翻译表(数组参数走逗号分隔)**:
36
+ >
37
+ > | plugin tool | CLI 命令 |
38
+ > | --- | --- |
39
+ > | `xiaobao_authorize { force? }` | `xiaobao-cli auth login [--force]` |
40
+ > | `xiaobao_whoami` | `xiaobao-cli auth whoami` |
41
+ > | `xiaobao_logout` | `xiaobao-cli auth logout` |
42
+ > | `xiaobao_list_projects { keyword? }` | `xiaobao-cli project list [--keyword <kw>]` |
43
+ > | `xiaobao_switch_project { tenantId, tenantName, projectId, projectName }` | `xiaobao-cli project use --tenant-id ... --tenant-name ... --project-id ... --project-name ...` |
44
+ > | `xiaobao_list_consultants` | `xiaobao-cli consultant list` |
45
+ > | `xiaobao_list_audio { fromDate, toDate, userId?, userIdList?, page, size }` | `xiaobao-cli audio list --from "..." --to "..." [--user-id ...] [--user-id-list a,b,c] [--page N] [--size N]` |
46
+ > | `xiaobao_get_audio_text { audioId }` | `xiaobao-cli audio text <audioId>` |
47
+ > | `xiaobao_list_customers { ... }` | `xiaobao-cli customer list [--user-id] [--user-name] [--customer-name] [--customer-phone] [--portrait] [--from] [--to] [--page] [--size]` |
48
+ > | `xiaobao_list_visits { ... }` | `xiaobao-cli visit list [--customer-id] [--customer-name] [--from] [--to] [--page] [--size]` |
49
+ > | `xiaobao_list_customer_focus { visitIds, customerIds, audioIds, category, classification, fromDate, toDate, ... }` | `xiaobao-cli focus list [--visit-ids a,b] [--customer-ids a,b] [--audio-ids a,b] [--category ...] [--classification ...] [--from ...] [--to ...]` |
50
+ > | `xiaobao_list_customer_resistance { ... }` | `xiaobao-cli resistance list [同 focus]` |
51
+ > | `xiaobao_quick_qa { prompt, threadId? }` | `xiaobao-cli qa "<prompt>" [--thread-id ...]` |
52
+ > | `xiaobao_api { method, path, query, body, headers }` | `xiaobao-cli api <METHOD> <PATH> [--query k=v] [--body '<json>'] [--headers k=v]` |
53
+ >
54
+ > 用 `--format toon` 切到 TOON(uniform 数组省 30-50% token,LLM 上下文优化);
55
+ > 用 `--format json`(默认)保持 JSON。state 路径:`~/.xiaobao/`(fallback 读 `~/.openclaw/state/wangxiaobao/`)。
56
+
57
+
58
+ # 旺小宝来访分页查询
59
+
60
+ 调 `xiaobao_list_visits` tool 查当前激活项目的来访记录。
61
+
62
+ ## 执行前必读
63
+
64
+ - 必须有有效 token:先调 `xiaobao_whoami`;未登录就 `xiaobao_authorize`
65
+ - **必须有激活项目**:tool 内部自动读,缺失返回 `NO_ACTIVE_PROJECT`
66
+ - **数据权限隔离**:跟客户接口一样,按当前用户授权可见顾问范围过滤
67
+ - LocalDateTime 格式:`yyyy-MM-dd HH:mm:ss`(空格分隔),plugin 自动转
68
+ - **不要**写文件、出报告
69
+
70
+ ---
71
+
72
+ ## 快速索引:意图 → 工具
73
+
74
+ | 用户意图 | plugin tool | 关键参数 |
75
+ | ------------------------------ | ----------------------- | --------------------------------------- |
76
+ | 列时间窗内的全部来访 | `xiaobao_list_visits` | `fromDate` / `toDate` |
77
+ | 看某客户的来访历史 | `xiaobao_list_customers` → `xiaobao_list_visits` | `customerId: <反查的 wang_id>` |
78
+ | 按客户名字模糊找来访 | `xiaobao_list_visits` | `customerName: "张"` |
79
+ | **看某次来访的录音详情** | `xiaobao_list_visits` | 直接读返回里的 `audios[]`(含 fileUrl) |
80
+ | 估算总数 | `xiaobao_list_visits` | `page: 1, size: 1`,只读 `total` |
81
+
82
+ ---
83
+
84
+ ## 核心约束
85
+
86
+ ### 1. 客户名 vs 客户 ID —— 优先 ID,更准更快
87
+
88
+ 用户说"李女士最近几次来访"——**优先**走两步:
89
+
90
+ 1. 调 `xiaobao_list_customers { customerName: "李女士" }` 反查到 `customerId`
91
+ 2. 调 `xiaobao_list_visits { customerId: <wang_id> }` 拿来访历史
92
+
93
+ 直接传 `customerName` 也能用(后端 JOIN customer_profile 模糊匹配),但:
94
+ - 同名客户可能有多个(重名 "李女士"),结果混在一起不好辨认
95
+ - JOIN 慢于纯 visit 表查询
96
+
97
+ ### 2. 时间窗:用户没明确说就推断
98
+
99
+ | 用户说法 | fromDate / toDate |
100
+ | ------------ | ------------------------------------------------ |
101
+ | "今天到访" | 今天 00:00:00 / 明天 00:00:00 |
102
+ | "本周来访" | 周一 00:00:00 / 今天 23:59:59 |
103
+ | "上周末" | 上周六 00:00:00 / 本周一 00:00:00 |
104
+ | "5 月份" | 2026-05-01 00:00:00 / 2026-06-01 00:00:00 |
105
+ | "最近 3 次" | 不传时间窗,只看 `content[]` 前 3 条 |
106
+
107
+ ### 3. 分页:page 从 **1** 开始;size 上限 500
108
+
109
+ 跟其他接口一样。
110
+
111
+ ### 4. 响应字段重点
112
+
113
+ ```jsonc
114
+ {
115
+ "code": "0",
116
+ "data": {
117
+ "page": 1, "size": 10, "total": 23,
118
+ "content": [
119
+ {
120
+ "visitId": "...",
121
+ "customerId": "1685535452481236993", // = wang_id,可传回 customers 查
122
+ "visitTime": "2023-07-30 14:01:03",
123
+ "visitCount": 1, // 第几次到访
124
+ "visitTimer": 1439184, // 来访总秒数
125
+ "audioCount": 3, // 关联录音条数(= audios.length)
126
+ "audios": [ // ★ 录音详情列表,按 startTime 升序
127
+ {
128
+ "audioId": 9001,
129
+ "fileId": "abc",
130
+ "startTime": "2023-07-30 14:01:15",
131
+ "endTime": "2023-07-30 14:08:42",
132
+ "duration": 447, // 秒
133
+ "fileSize": 3145728,
134
+ "hasValid": 1, // 0 无效 / 1 有效
135
+ "status": 4, // 0 转存中/1 转文本/2 待分析/3 分析中/4 完成
136
+ "userId": 270078834689187840,
137
+ "fileUrl": "https://oss.../abc?sign=..." // 18000 秒过期
138
+ }
139
+ ],
140
+ "userId": 270078834689187840,
141
+ "userName": "兰鸿建", // 实际接待顾问
142
+ "belongUserId": ...,
143
+ "belongUserName": "兰鸿建", // 客户归属顾问(可能跟接待不同)
144
+ "userInfo": { /* 顾问详情 */ },
145
+ "pankeStatus": "已完成", // 盘客状态
146
+ "isPankeCompleted": 1,
147
+ "requireSpeechTotal": 8, "requireSpeechHit": 5,
148
+ "salesSpeechTotal": 12, "salesSpeechHit": 9
149
+ }
150
+ ]
151
+ }
152
+ }
153
+ ```
154
+
155
+ plugin tool 又外包一层 → `resp.data.data.content`。
156
+
157
+ `requireSpeechHitDetail` / `salesSpeechHitDetail` 是 JSON 文本,**默认不展示给用户**
158
+ (除非用户明确问"具体哪条话术命中了")。
159
+
160
+ ### 5. 接待 vs 归属:解释差异
161
+
162
+ - `userId / userName` = **实际接待**(这次来访是谁陪同的)
163
+ - `belongUserId / belongUserName` = **客户归属**(客户档案里登记的归属销售)
164
+
165
+ 正常情况两者一致;不一致时可能是:
166
+ - 销售 A 不在岗,同事 B 帮忙接待 A 的客户
167
+ - 客户重新分配过
168
+
169
+ 用户问"张三接待了几个"——按 `userId == 张三`;问"张三名下客户来访"——按 `belongUserId == 张三`
170
+ (**但本 tool 当前不支持按 belongUserId 过滤**,需先用 customers 反查再 customerId 过滤)。
171
+
172
+ ---
173
+
174
+ ## 使用场景示例
175
+
176
+ ### 场景 1:今天到访列表
177
+
178
+ ```jsonc
179
+ { "fromDate": "2026-05-13 00:00:00", "toDate": "2026-05-14 00:00:00" }
180
+ ```
181
+
182
+ 渲染:
183
+
184
+ ```
185
+ 今天共 18 次到访(按时间倒序):
186
+ 1. 屈哥 · 14:01 · 接待:兰鸿建 · 第 1 次 · 12 分 · 录音 3
187
+ 2. 曹女士 · 13:45 · 接待:陈平 · 第 2 次 · 25 分 · 录音 2
188
+ ...
189
+ ```
190
+
191
+ ### 场景 2:李女士最近 3 次来访
192
+
193
+ ```jsonc
194
+ // step 1: 反查 wang_id
195
+ // xiaobao_list_customers
196
+ { "customerName": "李女士", "size": 20 }
197
+
198
+ // step 2: 假设找到 customerId = 270072120829026305
199
+ // xiaobao_list_visits
200
+ { "customerId": "270072120829026305", "page": 1, "size": 3 }
201
+ ```
202
+
203
+ ### 场景 3:上周末来访高峰
204
+
205
+ ```jsonc
206
+ { "fromDate": "2026-05-10 00:00:00", "toDate": "2026-05-12 00:00:00", "page": 1, "size": 50 }
207
+ ```
208
+
209
+ 后处理:按 hour 聚合 → 报告"周日下午 14-16 点是峰值"。
210
+
211
+ ### 场景 4:用客户名直接模糊
212
+
213
+ ```jsonc
214
+ // 不知道具体客户 ID,先用名字模糊
215
+ { "customerName": "张", "fromDate": "2026-05-01 00:00:00", "size": 20 }
216
+ ```
217
+
218
+ 回复:"姓张的客户 5 月来访共 8 次,分布在 3 位客户:张先生(133****0692) 来 3 次..."
219
+
220
+ ### 场景 5:直接看某次到访的录音详情
221
+
222
+ ```jsonc
223
+ { "customerId": "1685535452481236993", "page": 1, "size": 5 }
224
+ ```
225
+
226
+ 每条 visit 已带 `audios[]`,**不必再调** `xiaobao_list_audio`:
227
+
228
+ ```
229
+ 屈哥 · 2023-07-30 14:01:03 · 接待:兰鸿建 · 12 分 · 3 条录音:
230
+ 1. audioId=9001 · 14:01:15 ~ 14:08:42 · 7 分 · 状态:分析完成
231
+ fileUrl: https://oss.../abc?sign=...
232
+ 2. audioId=9002 · 14:09:00 ~ 14:11:30 · 2 分 · 状态:分析完成
233
+ 3. audioId=9003 · 14:12:00 ~ 14:15:30 · 3 分 · 状态:分析完成
234
+ ```
235
+
236
+ > 想看某条录音的**转录文本**还是要单独调 `xiaobao_get_audio_text`,
237
+ > `audios[]` 里只有元数据 + 签名 URL,没有 transcript。
238
+
239
+ ---
240
+
241
+ ## 常见错误与排查
242
+
243
+ - **`error: 'NO_ACTIVE_PROJECT'`** — 跑 `wangxiaobao-switch-project` skill
244
+ - **401 / token 过期** — 调 `xiaobao_authorize { force: true }` 重登
245
+ - **`total: 0`** — 时间窗内确实没数据,或当前用户授权范围内没有匹配的接待顾问
246
+ - **customerName 模糊但没匹到** — 客户名拼写差异("李女士" vs "李小姐");
247
+ 改用 `xiaobao_list_customers` 反查精确 customerId
248
+ - **接待顾问跟归属顾问不一致** — 正常业务情况(同事代接待),不是 bug;
249
+ 必要时跟用户解释