@puyinkai/xiaobao-cli 0.1.0 → 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.
Files changed (44) hide show
  1. package/dist/{api-Ccj5dLMo.mjs → api-CX99_4K7.mjs} +22 -5
  2. package/dist/{api-client-DwySN6x-.mjs → api-client-zDBFgk0y.mjs} +5 -3
  3. package/dist/{audio-VmDQMq59.mjs → audio-ShfvRomP.mjs} +2 -2
  4. package/dist/{auth-ChHvqjCS.mjs → auth-DpK81Vp5.mjs} +3 -3
  5. package/dist/cli.mjs +15 -11
  6. package/dist/{consultant-ABFTL_jx.mjs → consultant-CS9B42d3.mjs} +1 -1
  7. package/dist/current-CfDExInT.mjs +33 -0
  8. package/dist/{customer-DtSnQqy_.mjs → customer-B1cxRbJ9.mjs} +1 -1
  9. package/dist/{focus-BDYuP2vZ.mjs → focus-DfNPPhm5.mjs} +1 -1
  10. package/dist/{format-BZvv8lYc.mjs → format-yjmxrbNm.mjs} +15 -7
  11. package/dist/{list-Bkyi95YO.mjs → list-CD08BRLk.mjs} +6 -6
  12. package/dist/{list-CzB9_Jho.mjs → list-CKlx8YuL.mjs} +6 -6
  13. package/dist/{list-DW6KAAaC.mjs → list-CnlFIFiY.mjs} +6 -6
  14. package/dist/{list-iwd9cH1I.mjs → list-Cu6WzPpA.mjs} +5 -5
  15. package/dist/{list-CVKSGNu4.mjs → list-D56gEqiB.mjs} +6 -6
  16. package/dist/{list--o5Q_PI8.mjs → list-DCcCS6LM.mjs} +6 -6
  17. package/dist/{list-CGACp0y-.mjs → list-DI1OD95x.mjs} +3 -3
  18. package/dist/login-CUUcjWPd.mjs +156 -0
  19. package/dist/{logout-BJm9pjje.mjs → logout-DP7REhCd.mjs} +10 -7
  20. package/dist/{project-Ba05YzJ5.mjs → project-BuQQewOs.mjs} +3 -2
  21. package/dist/{project-store-Bz5kf-EI.mjs → project-store-CKVJa54T.mjs} +4 -3
  22. package/dist/{qa-D-B9FV9W.mjs → qa-CKsKiQIm.mjs} +5 -5
  23. package/dist/{resistance-Cf7zsdB3.mjs → resistance-DsE-Ha6Y.mjs} +1 -1
  24. package/dist/{text-BLH4R3xv.mjs → text-C3jhdPoe.mjs} +5 -5
  25. package/dist/{token-store-CHZ_rJQk.mjs → token-store-CXizLE2_.mjs} +46 -6
  26. package/dist/{use-DV9Ii3Tn.mjs → use-BZES4FZC.mjs} +2 -2
  27. package/dist/{visit-Ct3Vea8I.mjs → visit-CX0Mc1n6.mjs} +1 -1
  28. package/dist/{whoami-DwTHvI4B.mjs → whoami-CZVez-rm.mjs} +2 -2
  29. package/package.json +2 -2
  30. package/skills/wangxiaobao-audio-query/SKILL.md +51 -106
  31. package/skills/wangxiaobao-audio-wiki/SKILL.md +31 -77
  32. package/skills/wangxiaobao-audio-wiki/references/audio-wiki-schema.md +386 -0
  33. package/skills/wangxiaobao-audio-wiki/references/llm-wiki-ingest.md +450 -0
  34. package/skills/wangxiaobao-customer-focus-query/SKILL.md +37 -87
  35. package/skills/wangxiaobao-customer-query/SKILL.md +41 -90
  36. package/skills/wangxiaobao-customer-resistance-query/SKILL.md +32 -86
  37. package/skills/wangxiaobao-quick-qa/SKILL.md +41 -92
  38. package/skills/wangxiaobao-shared/SKILL.md +194 -0
  39. package/skills/wangxiaobao-switch-project/SKILL.md +51 -77
  40. package/skills/wangxiaobao-visit-query/SKILL.md +41 -88
  41. package/dist/login-BwkrByMm.mjs +0 -91
  42. package/dist/{device-flow-BgsZipYA.mjs → device-flow-D6JVcEap.mjs} +1 -1
  43. /package/dist/{headers-D79npewp.mjs → headers-DSnR4sjk.mjs} +0 -0
  44. /package/dist/{util-DgwkUfV9.mjs → util-CaPQBlNa.mjs} +0 -0
@@ -0,0 +1,194 @@
1
+ ---
2
+ name: wangxiaobao-shared
3
+ version: 0.1.0
4
+ description: "旺小宝 CLI 共享规则:安装方式(npm / npx),认证(OAuth device flow),激活项目,全局 flags(--format json/toon),输出协议(stdout JSON / stderr 错误 / exit code),错误码语义(NO_ACTIVE_PROJECT / NOT_AUTHENTICATED 含 hint 字段),权限隔离原则,token / active-project 文件位置(含 ~/.openclaw fallback)。任何旺小宝 skill 在执行命令前应先用 Read tool 读取本文件 —— 它定义了所有 xiaobao-cli 命令共享的前置约定。"
5
+ metadata:
6
+ requires:
7
+ bins: ["xiaobao-cli"]
8
+ cliHelp: "xiaobao-cli --help"
9
+ ---
10
+
11
+ # 旺小宝 CLI 共享规则
12
+
13
+ 本 skill 定义所有 `xiaobao-cli` 命令通用的前置约束 + 协议,**其他旺小宝 skill
14
+ 开始执行前 MUST 先用 Read tool 完整读取本文件**。
15
+
16
+ ## 安装
17
+
18
+ ```bash
19
+ # 全局安装(推荐,长期用)
20
+ npm install -g @puyinkai/xiaobao-cli
21
+
22
+ # 或一次性用(不污染全局)
23
+ npx -y @puyinkai/xiaobao-cli <subcommand>...
24
+ ```
25
+
26
+ 装好后 `xiaobao-cli --version` 应返回 `0.1.x`。Node 22+。
27
+
28
+ ## 三步走基础流程
29
+
30
+ 任何 xiaobao-cli 命令的**前置 3 步**:
31
+
32
+ ```bash
33
+ # 1. 登录(OAuth device flow 非阻塞 split-flow,token 自动缓存)—— 见下方
34
+ xiaobao-cli auth login --no-wait
35
+
36
+ # 2. 选激活项目(多租户 / 多项目场景必做;旺小宝是多租户业务)
37
+ xiaobao-cli project list # 列可选
38
+ xiaobao-cli project use --tenant-id ... --tenant-name ... \
39
+ --project-id ... --project-name ...
40
+
41
+ # 3. 跑业务命令(这一步往后所有 list/text/qa 命令都从激活项目读 tenant/project)
42
+ xiaobao-cli audio list --from ... --to ...
43
+ xiaobao-cli customer list --portrait 高意向
44
+ # ...
45
+ ```
46
+
47
+ ### 登录 —— 用 `--no-wait` split-flow(两步、不阻塞)
48
+
49
+ 登录走 OAuth device flow,固定用下面的两步、全程不阻塞。**不要跑裸
50
+ `xiaobao-cli auth login`** —— 它会阻塞轮询、卡满一整轮对话。
51
+
52
+ ```bash
53
+ # 步骤 A:发起,立即返回(约 0.5s),拿到 verification_uri
54
+ xiaobao-cli auth login --no-wait
55
+ # stdout: { "awaiting_authorization": true, "verification_uri": "...",
56
+ # "user_code": "...", "expires_in": 300, "interval": 5, ... }
57
+ # device_code 不在 stdout —— 已安全存到 ~/.xiaobao/pending-auth.json(0600)
58
+ ```
59
+
60
+ agent 拿到后:把 `verification_uri` **原样**发给用户(放进只含 URL 的代码块,
61
+ 不要改写不要做 URL 编码),让用户浏览器打开授权,然后**结束本轮**,把控制权
62
+ 交还用户。
63
+
64
+ ```bash
65
+ # 步骤 B:用户回复"授权完成"后,直接换 token(秒级)——
66
+ # device_code 已由步骤 A 存在本地,--resume 自动读取,agent 无需持有 / 传递它
67
+ xiaobao-cli auth login --resume
68
+ # stdout: { "source": "device-flow", "expires_at": ..., "scope": "..." }
69
+ ```
70
+
71
+ device_code 有效期 `expires_in` 秒(约 5 分钟)。超时就重跑步骤 A。
72
+ 若 token 仍有效 / refresh_token 可用,`--no-wait` 会直接走 cache/refresh
73
+ 快速返回(`source: cache` / `refresh`),不发起新的 device flow,也无需步骤 B。
74
+
75
+ 查身份 / 当前激活项目(任何时候都可以):
76
+
77
+ ```bash
78
+ xiaobao-cli auth whoami # 显示 logged_in + user 信息 + token 剩余有效期
79
+ xiaobao-cli project current # 显示当前激活的 tenant/project + updatedAt
80
+ ```
81
+
82
+ ## 输出协议
83
+
84
+ 所有命令统一协议:
85
+
86
+ | 流 | 内容 |
87
+ | --- | --- |
88
+ | **stdout** | 结果 / 错误对象,**JSON 格式**(默认)或 TOON 格式(`--format toon`),都是有效 JSON / 可机器解析 |
89
+ | **stderr** | 进度 / 人类友好错误提示 / verification URL 等。Agent 一般忽略 |
90
+ | **exit code** | 0 = 成功;非 0 = 失败(业务错误 / 参数错 / 网络错) |
91
+
92
+ Agent 消费时**只 parse stdout JSON**,stderr 是辅助。
93
+
94
+ ### `--format` 全局 flag
95
+
96
+ | 值 | 用途 |
97
+ | --- | --- |
98
+ | `json`(默认) | pretty JSON,agent / 人类都能读 |
99
+ | `toon` | TOON 格式,uniform array of objects 省 30-50% token(LLM 上下文优化) |
100
+
101
+ ## 错误对象结构
102
+
103
+ 失败时 stdout 输出结构化错误(仍是合法 JSON,agent 直接 parse):
104
+
105
+ ```json
106
+ {
107
+ "error": "NO_ACTIVE_PROJECT",
108
+ "message": "当前未设置激活项目",
109
+ "hint": "先用 `xiaobao-cli project list [--keyword <kw>]` 查看可选项目,再用 `xiaobao-cli project use ...` 激活。"
110
+ }
111
+ ```
112
+
113
+ 字段语义:
114
+
115
+ - `error`:**机器可读错误码**(常量字符串,agent 用它做分支判断)
116
+ - `message`:**短描述**(一句话讲发生了什么)
117
+ - `hint`:**actionable 命令引导**(agent 直接照这条命令解决,不要再让用户自己想)
118
+
119
+ ### 常见错误码
120
+
121
+ | code | 触发场景 | hint 内 actionable 命令 |
122
+ | --- | --- | --- |
123
+ | `NOT_AUTHENTICATED` | 未登录 / token 过期且 refresh_token 也失效 | `xiaobao-cli auth login` |
124
+ | `NO_ACTIVE_PROJECT` | 没设激活项目就跑了需要 tenant/project 的命令 | `xiaobao-cli project list` + `xiaobao-cli project use ...` |
125
+ | `API_ERROR` | 上游 ai-open / saas API 返非 2xx | 看 `details.status` 和 `details.body`,可能 token scope 不够 / 上游临时挂 |
126
+ | `BAD_METHOD` | `api` 命令传错 HTTP method | 用 GET / POST / PUT / PATCH / DELETE |
127
+
128
+ 遇到 `NOT_AUTHENTICATED` 或 `NO_ACTIVE_PROJECT` 时**立即按 hint 走**,不要追问用户。
129
+
130
+ ## state 文件位置
131
+
132
+ | 文件 | 用途 | 路径 | 权限 |
133
+ | --- | --- | --- | --- |
134
+ | OAuth tokens | access_token + refresh_token + id_token + expires_at | `~/.xiaobao/token.json` | 0600 |
135
+ | Active project | tenantId / tenantName / projectId / projectName / updatedAt | `~/.xiaobao/active-project.json` | 0600 |
136
+ | User config(可选) | 覆盖 authBase / apiBase / scopes | `~/.xiaobao/config.json` | 0600 |
137
+ | Pending auth(临时) | `--no-wait` split-flow 进行中的 device_code / user_code / 过期时间 | `~/.xiaobao/pending-auth.json` | 0600 |
138
+
139
+ `pending-auth.json` 是 split-flow 的临时凭据中转:`--no-wait` 写入、`--resume`
140
+ 成功换到 token 后删除,`auth logout` 或 device_code 过期时也会清掉。device_code
141
+ 属凭据级数据,**只落本地文件、绝不进 stdout / agent 上下文**。
142
+
143
+ ### `~/.openclaw/state/wangxiaobao/` fallback(向后兼容 openclaw-xiaobao plugin 用户)
144
+
145
+ 读 token / active-project 时如果 `~/.xiaobao/` 没有,会**自动 fallback** 读
146
+ `~/.openclaw/state/wangxiaobao/{token,active-project}.json`。这是 plugin 用户
147
+ 迁移到 CLI 的零摩擦机制:装上 CLI 直接 `auth whoami` / `project current`
148
+ 就有数据,不用重新登录 / 重新选项目。
149
+
150
+ **写**操作(login / logout / project use)**永远写到 `~/.xiaobao/`**,不动
151
+ openclaw 的副本(保留 plugin session 完整性)。`auth logout` 例外 ——
152
+ 会主动清掉两边的 token,否则 fallback 读 legacy 会让"登出后 whoami 仍显示已登录"。
153
+
154
+ ## 数据权限隔离
155
+
156
+ `audio list` / `customer list` / `visit list` / `focus list` / `resistance list` /
157
+ `consultant list` 所有业务命令的后端都按**当前登录用户的授权范围**过滤数据:
158
+
159
+ - 普通顾问:只看自己名下
160
+ - 团队长:看本团队
161
+ - 项目管理员:看本项目全部
162
+
163
+ `total: 0` 不一定是"没数据",也可能是**当前账号无权访问**。看不到的客户 / 顾问
164
+ 不是 bug,是设计如此。要扩权限找管理员。
165
+
166
+ ## 时间格式
167
+
168
+ 所有 `--from` / `--to` 用 `yyyy-MM-dd HH:mm:ss`(空格分隔,**不带时区**)。
169
+ ISO 8601 形式 `2026-05-12T00:00:00+08:00` 也支持,CLI 内部转换为空格形式。
170
+
171
+ 时区按服务端默认(中国时区)解释,**不要**在 prompt 里手动换算。
172
+
173
+ ## generic `api` 命令
174
+
175
+ `xiaobao-cli api <METHOD> <PATH>` 是 escape hatch:调任意 wangxiaobao endpoint。
176
+ 默认从 active-project 自动注入 `X-Tenant-Id` / `X-Project-Id` 等 4 个 headers
177
+ (跟 dedicated 命令一致);要 opt-out 加 `--no-default-headers`。
178
+
179
+ ```bash
180
+ # 跟 `consultant list` 等价(自动注入 tenant/project headers)
181
+ xiaobao-cli api GET /ai-open/consultants
182
+
183
+ # 调不需要 tenant 上下文的端点
184
+ xiaobao-cli api GET /saas/v2/estate/tenant-and-estate/by-user-id --no-default-headers
185
+
186
+ # POST + body
187
+ xiaobao-cli api POST /ai-open/audio/page --body '{"fromDate":"...","toDate":"..."}'
188
+ ```
189
+
190
+ ## 切勿在 prompt / agent 上下文里贴 token
191
+
192
+ `access_token` / `refresh_token` 是凭据,泄露到对话 / 公开仓库 / 截图都是事故。
193
+ agent 永远不要 `cat ~/.xiaobao/token.json` 打印给用户看。要查身份用
194
+ `xiaobao-cli auth whoami`(只显示 user info + expires,不显示 token 本身)。
@@ -1,65 +1,27 @@
1
1
  ---
2
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 精确收敛后再确认
3
+ version: 0.1.0
4
+ description: "旺小宝多租户/项目切换。列出当前账号有权限的租户与项目(可按 keyword 模糊过滤收敛),让用户选择后激活到 ~/.xiaobao/active-project.json(0600);后续所有 xiaobao-cli 命令从该文件读 tenant/project 上下文,不再需要传 tenantId/projectId 入参。高频命令: xiaobao-cli project list [--keyword <kw>]、xiaobao-cli project use --tenant-id ... --tenant-name ... --project-id ... --project-name ...。何时用:用户说切项目/选项目/换项目/项目列表/切到 XX 项目;任意 xiaobao-cli 命令返回 NO_ACTIVE_PROJECT 错误;用户准备查录音/客户/来访但还没设激活项目;用户想看自己有权限访问哪些租户和项目。"
5
+ metadata:
6
+ requires:
7
+ bins: ["xiaobao-cli"]
8
+ cliHelp: "xiaobao-cli project --help"
17
9
  ---
18
10
 
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
11
  # 旺小宝项目切换
52
12
 
13
+ > **CRITICAL** —— 跑命令前 MUST 先用 Read tool 读取 [`../wangxiaobao-shared/SKILL.md`](../wangxiaobao-shared/SKILL.md)(一份共享文档讲清安装 / 登录 / 选项目 / 错误码 / 输出协议等所有 xiaobao-cli 命令通用的前置约定)。
14
+
53
15
  把当前账号下的「租户 + 项目」枚举出来让用户挑一个,确认后调
54
- `xiaobao_switch_project` tool 写入 plugin 全局状态文件,供后续 tool 读取。
16
+ `xiaobao-cli project use` 写入 CLI 全局状态文件,供后续 命令 读取。
55
17
 
56
18
  ## 执行前必读
57
19
 
58
- - 必须先通过 `xiaobao_authorize` 完成 OAuth 登录;token 没拿到时本 skill 不能继续
20
+ - 必须先通过 `xiaobao-cli auth login` 完成 OAuth 登录;token 没拿到时本 skill 不能继续
59
21
  - **不要**自己 fs.writeFile 写 `.env` 或任何文件——状态落地走
60
- `xiaobao_switch_project` tool,由 plugin 统一管理权限和路径
22
+ `xiaobao-cli project use`,由 CLI 统一管理权限和路径
61
23
  - 多个项目时**必须让用户挑**,绝对不要自动选择第一个;只有一个项目时才可以自动选
62
- - 用户确认前不要调 switch-project tool
24
+ - 用户确认前不要跑 wangxiaobao-switch-project skill
63
25
 
64
26
  ---
65
27
 
@@ -67,14 +29,16 @@ description: |
67
29
 
68
30
  ### 第 1 步:拿到项目列表
69
31
 
70
- 调用 plugin tool `xiaobao_list_projects`。**可选 `keyword` 参数**对租户名/
71
- 项目名做包含模糊过滤(大小写不敏感):
32
+ 跑命令 `xiaobao-cli project list`,可选 `--keyword <kw>` 对租户名/项目名做
33
+ 包含模糊过滤(大小写不敏感):
72
34
 
73
- - 用户已经说了想要哪个项目(如"切到盛世禧悦")→ **直接带 `keyword`**:
74
- `xiaobao_list_projects { keyword: "盛世禧悦" }`,收敛后通常只剩 1-2 条,
75
- 省去让用户从一长串里挑
76
- - 用户只说"换个项目""看看有哪些" → 不带 keyword,拉全量
77
- - 账号项目很多、全量列表太长 → 提示用户给个关键字,再带 `keyword` 重查
35
+ - 用户已经说了想要哪个项目(如"切到盛世禧悦")→ **直接带 `--keyword`**:
36
+ ```bash
37
+ xiaobao-cli project list --keyword 盛世禧悦
38
+ ```
39
+ 收敛后通常只剩 1-2 条,省去让用户从一长串里挑
40
+ - 用户只说"换个项目""看看有哪些" → 不带 `--keyword`,拉全量
41
+ - 账号项目很多、全量列表太长 → 提示用户给个关键字,再带 `--keyword` 重查
78
42
 
79
43
  返回结构:
80
44
  ```json
@@ -90,11 +54,11 @@ description: |
90
54
 
91
55
  如果 `count == 0`:
92
56
 
93
- - **带了 `keyword`** → 是关键字没命中,不是没权限。提示用户换更短的关键字、
57
+ - **带了 `--keyword`** → 是关键字没命中,不是没权限。提示用户换更短的关键字、
94
58
  或不带 keyword 看全量;**不要**直接说"没有项目"
95
- - **没带 `keyword`** → 账号确实没有可访问的项目,结束
59
+ - **没带 `--keyword`** → 账号确实没有可访问的项目,结束
96
60
 
97
- 如果 tool 报错(401 / token 过期等),先调 `xiaobao_authorize { force: true }` 重新登录,再重试一次。
61
+ 如果 命令 报错(401 / token 过期等),先调 `xiaobao-cli auth login --force` 重新登录,再重试一次。
98
62
 
99
63
  ### 第 2 步:展示并让用户选
100
64
 
@@ -110,21 +74,20 @@ description: |
110
74
  ```
111
75
 
112
76
  - **多个项目**:让用户回复编号或项目名。用户回复后,**再显示一次「即将激活的
113
- 租户/项目信息」并请用户确认 y/n**,确认后才调 `xiaobao_switch_project` tool
77
+ 租户/项目信息」并请用户确认 y/n**,确认后才跑 `xiaobao-cli project use`
114
78
  - **仅一个项目**:直接告诉用户"账号下只有一个项目 X,是否激活?"等用户确认即可
115
79
 
116
- ### 第 3 步:调 `xiaobao_switch_project` tool 落地
80
+ ### 第 3 步:跑 `xiaobao-cli project use` 落地
117
81
 
118
- ```json
119
- {
120
- "tenantId": "<选中条目的 tenantId>",
121
- "tenantName": "<选中条目的 tenantName>",
122
- "projectId": "<选中条目的 projectId>",
123
- "projectName": "<选中条目的 projectName>"
124
- }
82
+ ```bash
83
+ xiaobao-cli project use \
84
+ --tenant-id "<选中条目的 tenantId>" \
85
+ --tenant-name "<选中条目的 tenantName>" \
86
+ --project-id "<选中条目的 projectId>" \
87
+ --project-name "<选中条目的 projectName>"
125
88
  ```
126
89
 
127
- 成功返回:
90
+ 4 个 flag 都是必填。成功 stdout 返回:
128
91
 
129
92
  ```json
130
93
  {
@@ -140,7 +103,7 @@ description: |
140
103
  }
141
104
  ```
142
105
 
143
- 状态写到 `~/.openclaw/state/wangxiaobao/active-project.json`,权限 0600。
106
+ 状态写到 `~/.xiaobao/active-project.json`,权限 0600。
144
107
 
145
108
  ---
146
109
 
@@ -152,7 +115,7 @@ description: |
152
115
  ✅ 已切换到「示例租户A / 示例项目甲」
153
116
  租户 ID: 1234
154
117
  项目 ID: 9001
155
- 状态保存在 ~/.openclaw/state/wangxiaobao/active-project.json
118
+ 状态保存在 ~/.xiaobao/active-project.json
156
119
 
157
120
  下一步可以:
158
121
  - 查录音:让我帮你跑 wangxiaobao-audio-query / wangxiaobao-audio-wiki skill
@@ -161,10 +124,21 @@ description: |
161
124
 
162
125
  ---
163
126
 
164
- ## 仅查看不切换
127
+ ## 仅查看 / 查当前激活
128
+
129
+ | 场景 | 命令 |
130
+ | --- | --- |
131
+ | 看自己有哪些项目可选 | `xiaobao-cli project list` (必要时带 `--keyword <kw>` 收敛) |
132
+ | **查当前激活的是哪个项目** | `xiaobao-cli project current` |
133
+ | 切到新项目 | 走「流程」三步 |
134
+
135
+ `project current` 直接读 `~/.xiaobao/active-project.json`(fallback
136
+ `~/.openclaw/state/wangxiaobao/active-project.json`),返回当前激活的
137
+ tenant/project + `updatedAt`。如果用户问"现在是哪个项目""当前激活的是啥",
138
+ **优先**用 `project current`,不要全量 `project list` 再让用户辨认。
165
139
 
166
- 用户只想"看看有哪些项目"而**不切换**时,调 `xiaobao_list_projects`(必要时带
167
- `keyword` 收敛)渲染列表后停下来,不要调 `xiaobao_switch_project` tool。
140
+ 没激活过时 `project current` 返 `NO_ACTIVE_PROJECT` 错(同时 stdout 含
141
+ `hint` 字段告诉怎么激活)。
168
142
 
169
143
  ---
170
144
 
@@ -172,8 +146,8 @@ description: |
172
146
 
173
147
  | 错误现象 | 根本原因 | 解决方案 |
174
148
  |---|---|---|
175
- | `xiaobao_list_projects` 返回 401 / token 过期 | 没登录或 refresh 失败 | 调 `xiaobao_authorize { force: true }` 重新走 device flow |
149
+ | `xiaobao-cli project list` 返回 401 / token 过期 | 没登录或 refresh 失败 | 调 `xiaobao-cli auth login --force` 重新走 device flow |
176
150
  | `count == 0`(没带 keyword) | 账号无任何租户/项目权限 | 让用户找管理员加权限,本 skill 不继续 |
177
151
  | `count == 0`(带了 keyword) | 关键字没匹配到任何项目 | 换更短关键字 / 不带 keyword 看全量,别直接说"没项目" |
178
152
  | 用户输入的编号超出范围 | 选错了 | 重新提示当前可选编号区间 |
179
- | 其他 tool 仍返回 `NO_ACTIVE_PROJECT` | 没调 switch-project tool 落地 | 检查 `~/.openclaw/state/wangxiaobao/active-project.json` 是否存在,重新走本 skill |
153
+ | 其他 命令 仍返回 `NO_ACTIVE_PROJECT` | 没跑 wangxiaobao-switch-project skill 落地 | 检查 `~/.xiaobao/active-project.json` 是否存在,重新走本 skill |
@@ -1,83 +1,38 @@
1
1
  ---
2
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`
3
+ version: 0.1.0
4
+ description: "旺小宝客户来访分页查询:按 客户 ID / 客户姓名(模糊触发后端 JOIN)/ 来访时间窗 过滤,排序固定 visit_time DESC。每条 visit 直接带 audios 录音列表(含 audioId / fileId / startTime / duration / 签名 fileUrl),问这次来访打了几条录音 / 录音多长 / fileUrl 时不必再调 audio list。只读、不写文件、无副作用。高频命令: xiaobao-cli visit list [--customer-id <id>] [--customer-name <n>] [--from <date>] [--to <date>] [--page N] [--size N]。何时用:用户问今天到访/本周来访列表/最近来访/某客户最近几次来访/上周哪些客户来访/姓张客户什么时候来过/某次到访打了几条录音/录音 fileUrl/盘客完成没;任何看到访名单/接待记录/话术命中的开放式查询。注:customer-id 比 customer-name 精确,先用 xiaobao-cli customer list 反查 wang_id;要客户画像走 customer-query;要录音元数据走 audio-query。"
5
+ metadata:
6
+ requires:
7
+ bins: ["xiaobao-cli"]
8
+ cliHelp: "xiaobao-cli visit --help"
24
9
  ---
25
10
 
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
11
  # 旺小宝来访分页查询
59
12
 
60
- `xiaobao_list_visits` tool 查当前激活项目的来访记录。
13
+ > **CRITICAL** —— 跑命令前 MUST 先用 Read tool 读取 [`../wangxiaobao-shared/SKILL.md`](../wangxiaobao-shared/SKILL.md)(一份共享文档讲清安装 / 登录 / 选项目 / 错误码 / 输出协议等所有 xiaobao-cli 命令通用的前置约定)。
14
+
15
+ 跑 `xiaobao-cli visit list` 查当前激活项目的来访记录。
61
16
 
62
17
  ## 执行前必读
63
18
 
64
- - 必须有有效 token:先调 `xiaobao_whoami`;未登录就 `xiaobao_authorize`
65
- - **必须有激活项目**:tool 内部自动读,缺失返回 `NO_ACTIVE_PROJECT`
19
+ - 必须有有效 token:先调 `xiaobao-cli auth whoami`;未登录就 `xiaobao-cli auth login`
20
+ - **必须有激活项目**:命令内部自动读,缺失返回 `NO_ACTIVE_PROJECT`
66
21
  - **数据权限隔离**:跟客户接口一样,按当前用户授权可见顾问范围过滤
67
- - LocalDateTime 格式:`yyyy-MM-dd HH:mm:ss`(空格分隔),plugin 自动转
22
+ - LocalDateTime 格式:`yyyy-MM-dd HH:mm:ss`(空格分隔),CLI 自动转
68
23
  - **不要**写文件、出报告
69
24
 
70
25
  ---
71
26
 
72
27
  ## 快速索引:意图 → 工具
73
28
 
74
- | 用户意图 | plugin tool | 关键参数 |
29
+ | 用户意图 | 命令 | 关键参数 |
75
30
  | ------------------------------ | ----------------------- | --------------------------------------- |
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` |
31
+ | 列时间窗内的全部来访 | `xiaobao-cli visit list` | `--from` / `--to` |
32
+ | 看某客户的来访历史 | `xiaobao-cli customer list` → `xiaobao-cli visit list` | `--customer-id 反查的 wang_id` |
33
+ | 按客户名字模糊找来访 | `xiaobao-cli visit list` | `--customer-name 张` |
34
+ | **看某次来访的录音详情** | `xiaobao-cli visit list` | 直接读返回里的 `audios[]`(含 fileUrl) |
35
+ | 估算总数 | `xiaobao-cli visit list` | `--page 1 --size 1`,只读 `total` |
81
36
 
82
37
  ---
83
38
 
@@ -87,10 +42,10 @@ description: |
87
42
 
88
43
  用户说"李女士最近几次来访"——**优先**走两步:
89
44
 
90
- 1. 调 `xiaobao_list_customers { customerName: "李女士" }` 反查到 `customerId`
91
- 2. 调 `xiaobao_list_visits { customerId: <wang_id> }` 拿来访历史
45
+ 1. 调 `xiaobao-cli customer list { customerName: "李女士" }` 反查到 `--customer-id`
46
+ 2. 调 `xiaobao-cli visit list { customerId: <wang_id> }` 拿来访历史
92
47
 
93
- 直接传 `customerName` 也能用(后端 JOIN customer_profile 模糊匹配),但:
48
+ 直接传 `--customer-name` 也能用(后端 JOIN customer_profile 模糊匹配),但:
94
49
  - 同名客户可能有多个(重名 "李女士"),结果混在一起不好辨认
95
50
  - JOIN 慢于纯 visit 表查询
96
51
 
@@ -152,7 +107,7 @@ description: |
152
107
  }
153
108
  ```
154
109
 
155
- plugin tool 又外包一层 → `resp.data.data.content`。
110
+ CLI 又包一层 → `resp.data.data.content`。
156
111
 
157
112
  `requireSpeechHitDetail` / `salesSpeechHitDetail` 是 JSON 文本,**默认不展示给用户**
158
113
  (除非用户明确问"具体哪条话术命中了")。
@@ -167,7 +122,7 @@ plugin tool 又外包一层 → `resp.data.data.content`。
167
122
  - 客户重新分配过
168
123
 
169
124
  用户问"张三接待了几个"——按 `userId == 张三`;问"张三名下客户来访"——按 `belongUserId == 张三`
170
- (**但本 tool 当前不支持按 belongUserId 过滤**,需先用 customers 反查再 customerId 过滤)。
125
+ (**但本 命令当前不支持按 belongUserId 过滤**,需先用 customers 反查再 customerId 过滤)。
171
126
 
172
127
  ---
173
128
 
@@ -175,8 +130,8 @@ plugin tool 又外包一层 → `resp.data.data.content`。
175
130
 
176
131
  ### 场景 1:今天到访列表
177
132
 
178
- ```jsonc
179
- { "fromDate": "2026-05-13 00:00:00", "toDate": "2026-05-14 00:00:00" }
133
+ ```bash
134
+ xiaobao-cli visit list --from "2026-05-13 00:00:00" --to "2026-05-14 00:00:00"
180
135
  ```
181
136
 
182
137
  渲染:
@@ -190,40 +145,38 @@ plugin tool 又外包一层 → `resp.data.data.content`。
190
145
 
191
146
  ### 场景 2:李女士最近 3 次来访
192
147
 
193
- ```jsonc
194
- // step 1: 反查 wang_id
195
- // xiaobao_list_customers
196
- { "customerName": "李女士", "size": 20 }
148
+ ```bash
149
+ # step 1: 反查 wang_id
150
+ xiaobao-cli customer list --customer-name 李女士 --size 20
197
151
 
198
- // step 2: 假设找到 customerId = 270072120829026305
199
- // xiaobao_list_visits
200
- { "customerId": "270072120829026305", "page": 1, "size": 3 }
152
+ # step 2: 假设找到 customerId = 270072120829026305
153
+ xiaobao-cli visit list --customer-id 270072120829026305 --page 1 --size 3
201
154
  ```
202
155
 
203
156
  ### 场景 3:上周末来访高峰
204
157
 
205
- ```jsonc
206
- { "fromDate": "2026-05-10 00:00:00", "toDate": "2026-05-12 00:00:00", "page": 1, "size": 50 }
158
+ ```bash
159
+ xiaobao-cli visit list --from "2026-05-10 00:00:00" --to "2026-05-12 00:00:00" --page 1 --size 50
207
160
  ```
208
161
 
209
162
  后处理:按 hour 聚合 → 报告"周日下午 14-16 点是峰值"。
210
163
 
211
164
  ### 场景 4:用客户名直接模糊
212
165
 
213
- ```jsonc
214
- // 不知道具体客户 ID,先用名字模糊
215
- { "customerName": "", "fromDate": "2026-05-01 00:00:00", "size": 20 }
166
+ ```bash
167
+ # 不知道具体客户 ID,先用名字模糊
168
+ xiaobao-cli visit list --customer-name --from "2026-05-01 00:00:00" --size 20
216
169
  ```
217
170
 
218
171
  回复:"姓张的客户 5 月来访共 8 次,分布在 3 位客户:张先生(133****0692) 来 3 次..."
219
172
 
220
173
  ### 场景 5:直接看某次到访的录音详情
221
174
 
222
- ```jsonc
223
- { "customerId": "1685535452481236993", "page": 1, "size": 5 }
175
+ ```bash
176
+ xiaobao-cli visit list --customer-id 1685535452481236993 --page 1 --size 5
224
177
  ```
225
178
 
226
- 每条 visit 已带 `audios[]`,**不必再调** `xiaobao_list_audio`:
179
+ 每条 visit 已带 `audios[]`,**不必再调** `xiaobao-cli audio list`:
227
180
 
228
181
  ```
229
182
  屈哥 · 2023-07-30 14:01:03 · 接待:兰鸿建 · 12 分 · 3 条录音:
@@ -233,7 +186,7 @@ plugin tool 又外包一层 → `resp.data.data.content`。
233
186
  3. audioId=9003 · 14:12:00 ~ 14:15:30 · 3 分 · 状态:分析完成
234
187
  ```
235
188
 
236
- > 想看某条录音的**转录文本**还是要单独调 `xiaobao_get_audio_text`,
189
+ > 想看某条录音的**转录文本**还是要单独调 `xiaobao-cli audio text`,
237
190
  > `audios[]` 里只有元数据 + 签名 URL,没有 transcript。
238
191
 
239
192
  ---
@@ -241,9 +194,9 @@ plugin tool 又外包一层 → `resp.data.data.content`。
241
194
  ## 常见错误与排查
242
195
 
243
196
  - **`error: 'NO_ACTIVE_PROJECT'`** — 跑 `wangxiaobao-switch-project` skill
244
- - **401 / token 过期** — 调 `xiaobao_authorize { force: true }` 重登
197
+ - **401 / token 过期** — 调 `xiaobao-cli auth login --force` 重登
245
198
  - **`total: 0`** — 时间窗内确实没数据,或当前用户授权范围内没有匹配的接待顾问
246
199
  - **customerName 模糊但没匹到** — 客户名拼写差异("李女士" vs "李小姐");
247
- 改用 `xiaobao_list_customers` 反查精确 customerId
200
+ 改用 `xiaobao-cli customer list` 反查精确 customerId
248
201
  - **接待顾问跟归属顾问不一致** — 正常业务情况(同事代接待),不是 bug;
249
202
  必要时跟用户解释