@puyinkai/wow-xiaobao-cli 0.0.0-stage → 1.0.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 (89) hide show
  1. package/README.md +42 -2
  2. package/dist/add-Da4a88Dn.mjs +21 -0
  3. package/dist/admin-nr9IIF2K.mjs +14 -0
  4. package/dist/alerts-DjMCQESW.mjs +71 -0
  5. package/dist/analyze-BJATzFtI.mjs +67 -0
  6. package/dist/api-C1s2co2-.mjs +113 -0
  7. package/dist/audio-BYm3m77S.mjs +15 -0
  8. package/dist/auth-JZ34ksvF.mjs +14 -0
  9. package/dist/beautx-D5y2iytj.mjs +16 -0
  10. package/dist/call-BfT4uEa7.mjs +67 -0
  11. package/dist/cli.d.mts +1 -0
  12. package/dist/cli.mjs +47 -0
  13. package/dist/config-DipFfMio.mjs +11 -0
  14. package/dist/config-DqUxKQ3m.mjs +131 -0
  15. package/dist/consultant-CJ0tH11c.mjs +11 -0
  16. package/dist/current-Di1OImPn.mjs +33 -0
  17. package/dist/customer-Bpfdfh0U.mjs +15 -0
  18. package/dist/date-C9LQUbfA.mjs +21 -0
  19. package/dist/deal-analysis-Q4GMijIy.mjs +10 -0
  20. package/dist/detail-Df2eLTSN.mjs +69 -0
  21. package/dist/detail-k-zGzX4n.mjs +71 -0
  22. package/dist/diff-DkyjJG49.mjs +21 -0
  23. package/dist/doc-content-DlRfFk_V.mjs +54 -0
  24. package/dist/doc-e7Hu-v3F.mjs +42 -0
  25. package/dist/docs-C2ukQfbY.mjs +41 -0
  26. package/dist/fields-CNQUQ3BI.mjs +49 -0
  27. package/dist/focus-BNA14pxJ.mjs +11 -0
  28. package/dist/follow-BYYbUVCh.mjs +15 -0
  29. package/dist/format-bDFUVuDQ.mjs +622 -0
  30. package/dist/get-ZFU7CjqO.mjs +61 -0
  31. package/dist/headers-Dy5gROBB.mjs +11 -0
  32. package/dist/intent-DF8cH6nw.mjs +63 -0
  33. package/dist/json-CXENUkN_.mjs +13 -0
  34. package/dist/kb-n84Hl0uL.mjs +16 -0
  35. package/dist/last-7-days-WPinYIJi.mjs +5 -0
  36. package/dist/list-BVk58WIy.mjs +30 -0
  37. package/dist/list-BwhH-ZlP.mjs +87 -0
  38. package/dist/list-CJx_zclT.mjs +68 -0
  39. package/dist/list-CL5W1jMc.mjs +75 -0
  40. package/dist/list-Cb2q7k36.mjs +36 -0
  41. package/dist/list-Cl0VBo_Z.mjs +71 -0
  42. package/dist/list-D27lkRNJ.mjs +86 -0
  43. package/dist/list-D7iMacYA.mjs +71 -0
  44. package/dist/list-DTiXpPZF.mjs +38 -0
  45. package/dist/list-Dv2BGPQa.mjs +71 -0
  46. package/dist/list-KTc5uu5P.mjs +86 -0
  47. package/dist/now-Rn6gT4Bn.mjs +9 -0
  48. package/dist/panke-_HDbr3xq.mjs +14 -0
  49. package/dist/plan-c3BW0aCB.mjs +10 -0
  50. package/dist/portrait-BopNLEQX.mjs +14 -0
  51. package/dist/portrait-tags-Dhwy6-6U.mjs +10 -0
  52. package/dist/project-CIOk-2wk.mjs +15 -0
  53. package/dist/project-store-B-2rqrgM.mjs +63 -0
  54. package/dist/qa-CxQZgKRF.mjs +59 -0
  55. package/dist/quantum-BSlMUFk6.mjs +178 -0
  56. package/dist/range-BsL08fkP.mjs +18 -0
  57. package/dist/resistance-CzbXP4Mj.mjs +11 -0
  58. package/dist/sales-report-BbNoueUk.mjs +65 -0
  59. package/dist/score-CVu51n3k.mjs +5 -0
  60. package/dist/score-yakz2AnG.mjs +5 -0
  61. package/dist/search-kLJrFOVI.mjs +70 -0
  62. package/dist/service-score-CiIxFGJ8.mjs +91 -0
  63. package/dist/shared-BCf9YDEa.mjs +11 -0
  64. package/dist/shared-COOwe14d.mjs +87 -0
  65. package/dist/shared-CdUFV4rc.mjs +277 -0
  66. package/dist/staff-DasX8vTs.mjs +14 -0
  67. package/dist/staff-client-B3hnEyNi.mjs +59 -0
  68. package/dist/status-BFJYeL2I.mjs +24 -0
  69. package/dist/subtract-wUG7Jzdu.mjs +21 -0
  70. package/dist/summary-Dgt4Wm5k.mjs +79 -0
  71. package/dist/summary-DtLL_XW3.mjs +60 -0
  72. package/dist/text-Dj9OFG5s.mjs +44 -0
  73. package/dist/this-month-BsrOeTBH.mjs +5 -0
  74. package/dist/this-week-tCzGJfrf.mjs +5 -0
  75. package/dist/today-Br-4_qMr.mjs +9 -0
  76. package/dist/today-CqrcQCGQ.mjs +5 -0
  77. package/dist/today-so-far-CSGFhwkN.mjs +5 -0
  78. package/dist/token-store-BGLVc825.mjs +33 -0
  79. package/dist/token-usage-BK5JIJKx.mjs +97 -0
  80. package/dist/tomorrow-DYhV_kGk.mjs +9 -0
  81. package/dist/use-89I-jHty.mjs +61 -0
  82. package/dist/util-BuoFIeLS.mjs +46 -0
  83. package/dist/visit-ChOnvK8M.mjs +16 -0
  84. package/dist/visit-evaluate-BnxsFnQc.mjs +9 -0
  85. package/dist/weekday-7aGLxWaZ.mjs +14 -0
  86. package/dist/whoami-Ci6-uJJd.mjs +51 -0
  87. package/dist/yesterday-BzT2U1_f.mjs +9 -0
  88. package/dist/yesterday-DgYoUKYd.mjs +5 -0
  89. package/package.json +35 -4
@@ -0,0 +1,79 @@
1
+ import { n as xbApiFetch, t as resolveConfig } from "./config-DqUxKQ3m.mjs";
2
+ import { n as requireActiveProject } from "./project-store-B-2rqrgM.mjs";
3
+ import { t as tenantProjectHeaders } from "./headers-Dy5gROBB.mjs";
4
+ import { n as writeResult, t as writeError } from "./format-bDFUVuDQ.mjs";
5
+ import { r as toLocalDateTime } from "./util-BuoFIeLS.mjs";
6
+ import { defineCommand } from "citty";
7
+ //#region src/commands/visit/summary.ts
8
+ /**
9
+ * `wow-xiaobao visit summary` — page visit reception-summaries via
10
+ * POST /ai-open/visits/summary.
11
+ *
12
+ * Returns customer × visit × template-summary nesting, paged by visit_id.
13
+ * `--template` selects a specific reception-summary template (exact match on
14
+ * the template name, not a free-text question). When `--visit-id` is omitted,
15
+ * `--from`/`--to` are required and the window must be ≤ 7 days (enforced
16
+ * downstream by wang-ai-mcp).
17
+ */
18
+ var summary_default = defineCommand({
19
+ meta: {
20
+ name: "summary",
21
+ description: "来访接待总结分页查询(客户×来访×模板总结,按 visit_id 分页)"
22
+ },
23
+ args: {
24
+ "customer-id": {
25
+ type: "string",
26
+ description: "客户 ID(wang_id)精确过滤"
27
+ },
28
+ "visit-id": {
29
+ type: "string",
30
+ description: "来访 ID 精确过滤;传了它 from/to 可省略"
31
+ },
32
+ from: {
33
+ type: "string",
34
+ description: "来访时间下限(含);visit-id 为空时必填"
35
+ },
36
+ to: {
37
+ type: "string",
38
+ description: "来访时间上限(不含);visit-id 为空时必填"
39
+ },
40
+ template: {
41
+ type: "string",
42
+ description: "指定查询某个接待总结模板的结果(精确匹配模板名,非自由问句)"
43
+ },
44
+ page: {
45
+ type: "string",
46
+ default: "1"
47
+ },
48
+ size: {
49
+ type: "string",
50
+ default: "10"
51
+ },
52
+ "api-base": { type: "string" },
53
+ format: {
54
+ type: "string",
55
+ default: "toon"
56
+ }
57
+ },
58
+ async run({ args }) {
59
+ try {
60
+ writeResult(await xbApiFetch(resolveConfig({ apiBase: args["api-base"] }), "POST", "/ai-open/visits/summary", {
61
+ headers: tenantProjectHeaders(await requireActiveProject()),
62
+ body: {
63
+ wangId: args["customer-id"],
64
+ visitId: args["visit-id"],
65
+ fromDate: toLocalDateTime(args.from),
66
+ toDate: toLocalDateTime(args.to),
67
+ template: args.template,
68
+ page: Number(args.page),
69
+ size: Number(args.size)
70
+ }
71
+ }), args.format);
72
+ } catch (err) {
73
+ writeError(err, args.format);
74
+ process.exit(1);
75
+ }
76
+ }
77
+ });
78
+ //#endregion
79
+ export { summary_default as default };
@@ -0,0 +1,60 @@
1
+ import { n as xbApiFetch, t as resolveConfig } from "./config-DqUxKQ3m.mjs";
2
+ import { n as requireActiveProject } from "./project-store-B-2rqrgM.mjs";
3
+ import { t as tenantProjectHeaders } from "./headers-Dy5gROBB.mjs";
4
+ import { n as writeResult, t as writeError } from "./format-bDFUVuDQ.mjs";
5
+ import { r as toLocalDateTime, t as csvToArray } from "./util-BuoFIeLS.mjs";
6
+ import { defineCommand } from "citty";
7
+ //#region src/commands/follow/summary.ts
8
+ /**
9
+ * `wow-xiaobao follow summary` — 旺跟进汇总(电话/微信指标)。
10
+ *
11
+ * 同 follow list 的筛选条件,返回电话呼入/呼出次数与接通率、通话时长、
12
+ * 微信通话与消息数等指标(不分页)。调 POST /ai-open/follows/summary。
13
+ */
14
+ var summary_default = defineCommand({
15
+ meta: {
16
+ name: "summary",
17
+ description: "旺跟进汇总:电话呼入/呼出/接通率/时长、微信通话与消息数"
18
+ },
19
+ args: {
20
+ "user-ids": {
21
+ type: "string",
22
+ description: "CSV: 跟进人 userId 过滤;不传按当前授权范围"
23
+ },
24
+ "customer-ids": {
25
+ type: "string",
26
+ description: "CSV: 客户 wang_id 过滤"
27
+ },
28
+ from: {
29
+ type: "string",
30
+ description: "开始时间(含)"
31
+ },
32
+ to: {
33
+ type: "string",
34
+ description: "结束时间(不含)"
35
+ },
36
+ "api-base": { type: "string" },
37
+ format: {
38
+ type: "string",
39
+ default: "toon"
40
+ }
41
+ },
42
+ async run({ args }) {
43
+ try {
44
+ writeResult(await xbApiFetch(resolveConfig({ apiBase: args["api-base"] }), "POST", "/ai-open/follows/summary", {
45
+ headers: tenantProjectHeaders(await requireActiveProject()),
46
+ body: {
47
+ userIds: csvToArray(args["user-ids"]),
48
+ customerIds: csvToArray(args["customer-ids"]),
49
+ fromDate: toLocalDateTime(args.from),
50
+ toDate: toLocalDateTime(args.to)
51
+ }
52
+ }), args.format);
53
+ } catch (err) {
54
+ writeError(err, args.format);
55
+ process.exit(1);
56
+ }
57
+ }
58
+ });
59
+ //#endregion
60
+ export { summary_default as default };
@@ -0,0 +1,44 @@
1
+ import { n as xbApiFetch, t as resolveConfig } from "./config-DqUxKQ3m.mjs";
2
+ import { n as requireActiveProject } from "./project-store-B-2rqrgM.mjs";
3
+ import { t as tenantProjectHeaders } from "./headers-Dy5gROBB.mjs";
4
+ import { n as writeResult, t as writeError } from "./format-bDFUVuDQ.mjs";
5
+ import { defineCommand } from "citty";
6
+ //#region src/commands/audio/text.ts
7
+ /**
8
+ * `wow-xiaobao audio text <audio-id>` — fetch a single recording's transcript
9
+ * via GET /ai-open/audio/text/{audioId}.
10
+ *
11
+ * Returns talkRatios (per-speaker speaking ratios) + texts (segmented ASR
12
+ * with role / beginTime / endTime / text / commentaryNum per item).
13
+ */
14
+ var text_default = defineCommand({
15
+ meta: {
16
+ name: "text",
17
+ description: "查询单条录音转录文本(含说话人占比 + 分段文本)"
18
+ },
19
+ args: {
20
+ audioId: {
21
+ type: "positional",
22
+ required: true,
23
+ description: "录音 ID(来自 audio list 的 content[].audioId)"
24
+ },
25
+ "api-base": { type: "string" },
26
+ format: {
27
+ type: "string",
28
+ default: "toon"
29
+ }
30
+ },
31
+ async run({ args }) {
32
+ try {
33
+ const config = resolveConfig({ apiBase: args["api-base"] });
34
+ const active = await requireActiveProject();
35
+ const audioId = String(args.audioId);
36
+ writeResult(await xbApiFetch(config, "GET", `/ai-open/audio/text/${encodeURIComponent(audioId)}`, { headers: tenantProjectHeaders(active) }), args.format);
37
+ } catch (err) {
38
+ writeError(err, args.format);
39
+ process.exit(1);
40
+ }
41
+ }
42
+ });
43
+ //#endregion
44
+ export { text_default as default };
@@ -0,0 +1,5 @@
1
+ import { t as defineRangePresetCommand } from "./shared-BCf9YDEa.mjs";
2
+ //#region src/commands/date/range/this-month.ts
3
+ var this_month_default = defineRangePresetCommand("this-month", "本月:from=本月 1 日 00:00,to=下月 1 日 00:00");
4
+ //#endregion
5
+ export { this_month_default as default };
@@ -0,0 +1,5 @@
1
+ import { t as defineRangePresetCommand } from "./shared-BCf9YDEa.mjs";
2
+ //#region src/commands/date/range/this-week.ts
3
+ var this_week_default = defineRangePresetCommand("this-week", "本周:from=本周一 00:00,to=下周一 00:00");
4
+ //#endregion
5
+ export { this_week_default as default };
@@ -0,0 +1,9 @@
1
+ import { c as getRelativeDay, t as defineDateCommand } from "./shared-CdUFV4rc.mjs";
2
+ //#region src/commands/date/today.ts
3
+ var today_default = defineDateCommand({
4
+ name: "today",
5
+ description: "今天日期与星期",
6
+ run: ({ args }) => getRelativeDay(0, args.timezone)
7
+ });
8
+ //#endregion
9
+ export { today_default as default };
@@ -0,0 +1,5 @@
1
+ import { t as defineRangePresetCommand } from "./shared-BCf9YDEa.mjs";
2
+ //#region src/commands/date/range/today.ts
3
+ var today_default = defineRangePresetCommand("today", "今天全天:from=今天 00:00,to=明天 00:00");
4
+ //#endregion
5
+ export { today_default as default };
@@ -0,0 +1,5 @@
1
+ import { t as defineRangePresetCommand } from "./shared-BCf9YDEa.mjs";
2
+ //#region src/commands/date/range/today-so-far.ts
3
+ var today_so_far_default = defineRangePresetCommand("today-so-far", "今天至今:from=今天 00:00,to=当前时刻");
4
+ //#endregion
5
+ export { today_so_far_default as default };
@@ -0,0 +1,33 @@
1
+ import { join } from "node:path";
2
+ import { readFile } from "node:fs/promises";
3
+ /** 读取平台放置的令牌;未设置目录、文件不存在或为空时返回 null。 */
4
+ async function readToken() {
5
+ const dir = process.env.WOW_XIAOBAO_TOKEN_DIR;
6
+ if (!dir) return null;
7
+ let raw;
8
+ try {
9
+ raw = await readFile(join(dir, "token.json"), "utf-8");
10
+ } catch (e) {
11
+ if (e.code === "ENOENT") return null;
12
+ throw e;
13
+ }
14
+ if (!raw.trim()) return null;
15
+ return JSON.parse(raw);
16
+ }
17
+ /** 访问令牌存在且未临近过期。 */
18
+ function isAccessTokenValid(token) {
19
+ return Boolean(token?.access_token && token.expires_at > Date.now() + 6e4);
20
+ }
21
+ /** 解析 JWT 的 payload,失败返回 null。 */
22
+ function decodeJwtPayload(jwt) {
23
+ if (!jwt) return null;
24
+ const parts = jwt.split(".");
25
+ if (parts.length !== 3) return null;
26
+ try {
27
+ return JSON.parse(Buffer.from(parts[1], "base64url").toString("utf-8"));
28
+ } catch {
29
+ return null;
30
+ }
31
+ }
32
+ //#endregion
33
+ export { isAccessTokenValid as n, readToken as r, decodeJwtPayload as t };
@@ -0,0 +1,97 @@
1
+ import { n as xbApiFetch, t as resolveConfig } from "./config-DqUxKQ3m.mjs";
2
+ import { t as loadActiveProject } from "./project-store-B-2rqrgM.mjs";
3
+ import { t as tenantProjectHeaders } from "./headers-Dy5gROBB.mjs";
4
+ import { n as writeResult, t as writeError } from "./format-bDFUVuDQ.mjs";
5
+ import { defineCommand } from "citty";
6
+ //#region src/commands/admin/token-usage.ts
7
+ /**
8
+ * `wow-xiaobao admin token-usage` — 旺小宝 LLM token 用量汇总。
9
+ *
10
+ * super-admin 能力:返回指定日期区间(闭区间)的输入 / 输出 / 总量 tokens,可按
11
+ * 模型、供应商、API Key、接入点、标签、状态过滤。数据来自内网 AI Portal,经
12
+ * ai-open `POST /super-admin/token-usage` 代理;访问由独立白名单控制(空名单 =
13
+ * 全拒),不在名单会收到引导文案。
14
+ *
15
+ * 公司级数据:不要求激活项目(有激活项目则顺带传 tenant headers)。
16
+ */
17
+ var token_usage_default = defineCommand({
18
+ meta: {
19
+ name: "token-usage",
20
+ description: "LLM token 用量:输入/输出/总量,可按模型/供应商/Key 过滤(独立白名单)"
21
+ },
22
+ args: {
23
+ from: {
24
+ type: "string",
25
+ required: true,
26
+ description: "开始日期 yyyy-MM-dd(闭区间)"
27
+ },
28
+ to: {
29
+ type: "string",
30
+ required: true,
31
+ description: "结束日期 yyyy-MM-dd(闭区间)"
32
+ },
33
+ model: {
34
+ type: "string",
35
+ description: "模型过滤,如 gpt-4.1-mini"
36
+ },
37
+ provider: {
38
+ type: "string",
39
+ description: "供应商过滤,如 openai"
40
+ },
41
+ upstream: {
42
+ type: "string",
43
+ description: "上游过滤"
44
+ },
45
+ "api-key": {
46
+ type: "string",
47
+ description: "API Key 过滤"
48
+ },
49
+ endpoint: {
50
+ type: "string",
51
+ description: "接入点过滤"
52
+ },
53
+ "tag-key": {
54
+ type: "string",
55
+ description: "标签 key"
56
+ },
57
+ "tag-value": {
58
+ type: "string",
59
+ description: "标签 value"
60
+ },
61
+ status: {
62
+ type: "string",
63
+ description: "状态过滤,如 error(只看失败请求)"
64
+ },
65
+ "api-base": { type: "string" },
66
+ format: {
67
+ type: "string",
68
+ default: "toon"
69
+ }
70
+ },
71
+ async run({ args }) {
72
+ try {
73
+ const config = resolveConfig({ apiBase: args["api-base"] });
74
+ const active = await loadActiveProject();
75
+ writeResult(await xbApiFetch(config, "POST", "/ai-open/super-admin/token-usage", {
76
+ headers: active ? tenantProjectHeaders(active) : void 0,
77
+ body: {
78
+ startDate: args.from,
79
+ endDate: args.to,
80
+ model: args.model,
81
+ provider: args.provider,
82
+ upstream: args.upstream,
83
+ apiKey: args["api-key"],
84
+ endpoint: args.endpoint,
85
+ tagKey: args["tag-key"],
86
+ tagValue: args["tag-value"],
87
+ status: args.status
88
+ }
89
+ }), args.format);
90
+ } catch (err) {
91
+ writeError(err, args.format);
92
+ process.exit(1);
93
+ }
94
+ }
95
+ });
96
+ //#endregion
97
+ export { token_usage_default as default };
@@ -0,0 +1,9 @@
1
+ import { c as getRelativeDay, t as defineDateCommand } from "./shared-CdUFV4rc.mjs";
2
+ //#region src/commands/date/tomorrow.ts
3
+ var tomorrow_default = defineDateCommand({
4
+ name: "tomorrow",
5
+ description: "明天日期与星期",
6
+ run: ({ args }) => getRelativeDay(1, args.timezone)
7
+ });
8
+ //#endregion
9
+ export { tomorrow_default as default };
@@ -0,0 +1,61 @@
1
+ import { r as saveActiveProject } from "./project-store-B-2rqrgM.mjs";
2
+ import { n as writeResult, t as writeError } from "./format-bDFUVuDQ.mjs";
3
+ import { defineCommand } from "citty";
4
+ //#region src/commands/project/use.ts
5
+ /**
6
+ * `wow-xiaobao project use` — persist active tenant/project to
7
+ * ~/.xiaobao/active-project.json (mode 0600). Mirrors openclaw-xiaobao's
8
+ * `xiaobao_switch_project` tool.
9
+ */
10
+ var use_default = defineCommand({
11
+ meta: {
12
+ name: "use",
13
+ description: "激活指定租户/项目(先用 `project list` 拿候选)"
14
+ },
15
+ args: {
16
+ "tenant-id": {
17
+ type: "string",
18
+ required: true,
19
+ description: "租户 ID"
20
+ },
21
+ "tenant-name": {
22
+ type: "string",
23
+ required: true,
24
+ description: "租户显示名"
25
+ },
26
+ "project-id": {
27
+ type: "string",
28
+ required: true,
29
+ description: "项目 ID(estateId)"
30
+ },
31
+ "project-name": {
32
+ type: "string",
33
+ required: true,
34
+ description: "项目显示名"
35
+ },
36
+ format: {
37
+ type: "string",
38
+ default: "toon"
39
+ }
40
+ },
41
+ async run({ args }) {
42
+ try {
43
+ const saved = await saveActiveProject({
44
+ tenantId: args["tenant-id"],
45
+ tenantName: args["tenant-name"],
46
+ projectId: args["project-id"],
47
+ projectName: args["project-name"]
48
+ });
49
+ writeResult({
50
+ success: true,
51
+ activeProject: saved,
52
+ message: `已切换到「${saved.tenantName} / ${saved.projectName}」`
53
+ }, args.format);
54
+ } catch (err) {
55
+ writeError(err, args.format);
56
+ process.exit(1);
57
+ }
58
+ }
59
+ });
60
+ //#endregion
61
+ export { use_default as default };
@@ -0,0 +1,46 @@
1
+ //#region src/core/util.ts
2
+ /**
3
+ * Shared utilities for CLI commands.
4
+ *
5
+ * Mirrors the helpers scattered across openclaw-xiaobao tool files
6
+ * (toLocalDateTime / mergeUserIds), consolidated here so commands stay slim.
7
+ */
8
+ /**
9
+ * Normalize an LLM/human-provided datetime string to the format pierre's
10
+ * Jackson deserializer expects (`yyyy-MM-dd HH:mm:ss`):
11
+ *
12
+ * `2026-05-09T12:34:56` → `2026-05-09 12:34:56`
13
+ * `2026-05-09T12:34:56.789` → `2026-05-09 12:34:56`
14
+ * `2026-05-09T12:34:56+08:00` → `2026-05-09 12:34:56`
15
+ * `2026-05-09 12:34:56` → unchanged
16
+ */
17
+ function toLocalDateTime(input) {
18
+ if (!input) return input;
19
+ return input.replace("T", " ").replace(/\.\d+/, "").replace(/[+-]\d{2}:?\d{2}$/, "").replace(/Z$/, "").trim();
20
+ }
21
+ /**
22
+ * Merge a single id + a list of ids, de-dup. Returns undefined when empty so
23
+ * the upstream API treats it as "no filter" (not "filter to nothing").
24
+ */
25
+ function mergeUserIds(single, list) {
26
+ const merged = [];
27
+ const seen = /* @__PURE__ */ new Set();
28
+ const push = (v) => {
29
+ if (!v) return;
30
+ if (!seen.has(v)) {
31
+ seen.add(v);
32
+ merged.push(v);
33
+ }
34
+ };
35
+ if (single) push(single);
36
+ if (list) for (const v of list) push(v);
37
+ return merged.length > 0 ? merged : void 0;
38
+ }
39
+ /** Split `"a,b,c"` → `["a", "b", "c"]`, trimmed, empties dropped. */
40
+ function csvToArray(input) {
41
+ if (!input) return void 0;
42
+ const arr = input.split(",").map((x) => x.trim()).filter(Boolean);
43
+ return arr.length > 0 ? arr : void 0;
44
+ }
45
+ //#endregion
46
+ export { mergeUserIds as n, toLocalDateTime as r, csvToArray as t };
@@ -0,0 +1,16 @@
1
+ import { defineCommand } from "citty";
2
+ //#region src/commands/visit/index.ts
3
+ var visit_default = defineCommand({
4
+ meta: {
5
+ name: "visit",
6
+ description: "来访列表 / 接待总结 / 逼单与风险提醒 / 服务分"
7
+ },
8
+ subCommands: {
9
+ score: () => import("./score-CVu51n3k.mjs").then((m) => m.default),
10
+ alerts: () => import("./alerts-DjMCQESW.mjs").then((m) => m.default),
11
+ list: () => import("./list-Cl0VBo_Z.mjs").then((m) => m.default),
12
+ summary: () => import("./summary-Dgt4Wm5k.mjs").then((m) => m.default)
13
+ }
14
+ });
15
+ //#endregion
16
+ export { visit_default as default };
@@ -0,0 +1,9 @@
1
+ import { t as defineBeautxCommand } from "./shared-COOwe14d.mjs";
2
+ //#region src/commands/beautx/visit-evaluate.ts
3
+ var visit_evaluate_default = defineBeautxCommand({
4
+ name: "visit-evaluate",
5
+ description: "医美接诊评价分页(总分/总评 + 5 项能力分与建议)",
6
+ path: "/ai-open/beautx/visit-evaluates"
7
+ });
8
+ //#endregion
9
+ export { visit_evaluate_default as default };
@@ -0,0 +1,14 @@
1
+ import { a as getDateInfo, t as defineDateCommand } from "./shared-CdUFV4rc.mjs";
2
+ //#region src/commands/date/weekday.ts
3
+ var weekday_default = defineDateCommand({
4
+ name: "weekday",
5
+ description: "查询指定日期是星期几",
6
+ args: { date: {
7
+ type: "string",
8
+ description: "YYYY-MM-DD",
9
+ required: true
10
+ } },
11
+ run: ({ args }) => getDateInfo(args.date, args.timezone)
12
+ });
13
+ //#endregion
14
+ export { weekday_default as default };
@@ -0,0 +1,51 @@
1
+ import { r as readToken, t as decodeJwtPayload } from "./token-store-BGLVc825.mjs";
2
+ import { n as writeResult, t as writeError } from "./format-bDFUVuDQ.mjs";
3
+ import { defineCommand } from "citty";
4
+ //#region src/commands/auth/whoami.ts
5
+ /**
6
+ * `wow-xiaobao auth whoami` — print currently logged-in 旺小宝 user.
7
+ *
8
+ * Pure local op: reads the platform-managed id_token and
9
+ * decodes the JWT payload. No HTTP call.
10
+ */
11
+ var whoami_default = defineCommand({
12
+ meta: {
13
+ name: "whoami",
14
+ description: "查看当前登录的旺小宝用户(解析缓存 id_token)"
15
+ },
16
+ args: { format: {
17
+ type: "string",
18
+ default: "toon"
19
+ } },
20
+ async run({ args }) {
21
+ try {
22
+ const token = await readToken();
23
+ if (!token) {
24
+ writeResult({
25
+ logged_in: false,
26
+ message: "未授权:请在旺喔 App 的连接器里授权旺小宝。"
27
+ }, args.format);
28
+ return;
29
+ }
30
+ const claims = decodeJwtPayload(token.id_token);
31
+ writeResult({
32
+ logged_in: true,
33
+ user: claims ? {
34
+ sub: claims.sub,
35
+ name: claims.name,
36
+ phone_number: claims.phone_number,
37
+ email: claims.email,
38
+ preferred_username: claims.preferred_username
39
+ } : null,
40
+ token_expires_at: token.expires_at,
41
+ token_expires_in_seconds: Math.max(0, Math.floor((token.expires_at - Date.now()) / 1e3)),
42
+ scope: token.scope
43
+ }, args.format);
44
+ } catch (err) {
45
+ writeError(err, args.format);
46
+ process.exit(1);
47
+ }
48
+ }
49
+ });
50
+ //#endregion
51
+ export { whoami_default as default };
@@ -0,0 +1,9 @@
1
+ import { c as getRelativeDay, t as defineDateCommand } from "./shared-CdUFV4rc.mjs";
2
+ //#region src/commands/date/yesterday.ts
3
+ var yesterday_default = defineDateCommand({
4
+ name: "yesterday",
5
+ description: "昨天日期与星期",
6
+ run: ({ args }) => getRelativeDay(-1, args.timezone)
7
+ });
8
+ //#endregion
9
+ export { yesterday_default as default };
@@ -0,0 +1,5 @@
1
+ import { t as defineRangePresetCommand } from "./shared-BCf9YDEa.mjs";
2
+ //#region src/commands/date/range/yesterday.ts
3
+ var yesterday_default = defineRangePresetCommand("yesterday", "昨天全天:from=昨天 00:00,to=今天 00:00");
4
+ //#endregion
5
+ export { yesterday_default as default };
package/package.json CHANGED
@@ -1,6 +1,37 @@
1
1
  {
2
2
  "name": "@puyinkai/wow-xiaobao-cli",
3
- "version": "0.0.0-stage",
4
- "stub": true,
5
- "description": "Temporary package placeholder for staged publishing"
6
- }
3
+ "version": "1.0.0",
4
+ "description": "旺喔(WoW)云电脑专用的旺小宝 CLI:只读平台放置的访问令牌,不登录、不刷新",
5
+ "type": "module",
6
+ "bin": {
7
+ "wow-xiaobao": "dist/cli.mjs"
8
+ },
9
+ "files": [
10
+ "dist/**/*.mjs",
11
+ "dist/**/*.d.mts",
12
+ "README.md"
13
+ ],
14
+ "engines": {
15
+ "node": ">=22"
16
+ },
17
+ "packageManager": "pnpm@10.32.1",
18
+ "scripts": {
19
+ "build": "tsdown",
20
+ "test": "pnpm build && node --test tests/*.test.mjs",
21
+ "typecheck": "tsc --noEmit",
22
+ "dev": "node --import tsx src/cli.ts",
23
+ "connector:pack": "python3 scripts/connector-pack.py"
24
+ },
25
+ "dependencies": {
26
+ "citty": "^0.1.6"
27
+ },
28
+ "devDependencies": {
29
+ "@toon-format/toon": "^2.2.0",
30
+ "@types/node": "^25.2.3",
31
+ "tsdown": "^0.21.4",
32
+ "typescript": "^5.9.3"
33
+ },
34
+ "publishConfig": {
35
+ "access": "public"
36
+ }
37
+ }