@puyinkai/xiaobao-cli 0.5.0 → 0.6.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 (75) hide show
  1. package/README.md +6 -0
  2. package/dist/add-CCuWFy1O.mjs +21 -0
  3. package/dist/analyze-mjHjOnz1.mjs +72 -0
  4. package/dist/{audio-DzcmDYVu.mjs → audio-CDt1rpEL.mjs} +3 -2
  5. package/dist/{auth-DvvYyJBK.mjs → auth-sQwZSTNA.mjs} +4 -4
  6. package/dist/beautx-DytYVFvT.mjs +16 -0
  7. package/dist/cli.mjs +16 -11
  8. package/dist/config-GuXMTecJ.mjs +11 -0
  9. package/dist/{consultant-Ccnjnhzz.mjs → consultant-elv5arLG.mjs} +1 -1
  10. package/dist/{customer-D_LctjqX.mjs → customer-CZ-nG9ku.mjs} +1 -1
  11. package/dist/date-BcQMKhIT.mjs +21 -0
  12. package/dist/deal-analysis-Dqz34gLw.mjs +10 -0
  13. package/dist/diff-8I1_L-nU.mjs +21 -0
  14. package/dist/fields-BRE3oWMD.mjs +54 -0
  15. package/dist/{focus-BPPyRCBb.mjs → focus-C4egr05X.mjs} +1 -1
  16. package/dist/follow-LwYQd9Bv.mjs +14 -0
  17. package/dist/get-CbovJWSq.mjs +66 -0
  18. package/dist/{kb-DpBUFdFV.mjs → kb-CyPqbezN.mjs} +4 -4
  19. package/dist/last-7-days-VKMMIzDz.mjs +5 -0
  20. package/dist/{list-CTSX1XuK.mjs → list-CT4t_FJs.mjs} +1 -1
  21. package/dist/{list-DciEIXpx.mjs → list-CiNgcIXS.mjs} +1 -1
  22. package/dist/{list-Ca5Fvq_e.mjs → list-DWv6toPT.mjs} +1 -1
  23. package/dist/list-DXOlqJog.mjs +76 -0
  24. package/dist/{list-xbJZbyGQ.mjs → list-FQpZk3vH.mjs} +1 -1
  25. package/dist/{list-D_8QLOZ1.mjs → list-OYeOGI0g.mjs} +1 -1
  26. package/dist/list-XIIj_ryX.mjs +43 -0
  27. package/dist/now-Ce3ViNOw.mjs +9 -0
  28. package/dist/plan-C35h8U-w.mjs +10 -0
  29. package/dist/portrait-BEDGkOx1.mjs +14 -0
  30. package/dist/portrait-tags-B9hPFDIF.mjs +10 -0
  31. package/dist/{project-CYA9qd8k.mjs → project-urShHaAN.mjs} +3 -3
  32. package/dist/{quantum-Dyhp2Clf.mjs → quantum-Ds7rlag3.mjs} +2 -2
  33. package/dist/range-CSJiXTp3.mjs +18 -0
  34. package/dist/{resistance-BhlYgeUx.mjs → resistance-DMesV4lG.mjs} +1 -1
  35. package/dist/{search-ChFFOKV4.mjs → search-B0wA0YCI.mjs} +1 -1
  36. package/dist/shared-BEkL4JRB.mjs +11 -0
  37. package/dist/shared-Bbxvn4ZI.mjs +92 -0
  38. package/dist/shared-CYALikq5.mjs +277 -0
  39. package/dist/subtract-B4XTXD_X.mjs +21 -0
  40. package/dist/{summary-C3poiB2C.mjs → summary-BIx7F4AE.mjs} +1 -1
  41. package/dist/summary-BkxVcv8a.mjs +65 -0
  42. package/dist/this-month-BRdfmc1s.mjs +5 -0
  43. package/dist/this-week-2GoqEaXU.mjs +5 -0
  44. package/dist/today-BhQnSMJH.mjs +5 -0
  45. package/dist/today-CdlU96lq.mjs +9 -0
  46. package/dist/today-so-far-D2g98rKv.mjs +5 -0
  47. package/dist/tomorrow-BgSEBV69.mjs +9 -0
  48. package/dist/{visit-qf8Lwf_s.mjs → visit-CmEtfs7n.mjs} +2 -2
  49. package/dist/visit-evaluate-LdAg9iP5.mjs +9 -0
  50. package/dist/weekday-CgEg7n7U.mjs +14 -0
  51. package/dist/yesterday-CHAh1DlJ.mjs +5 -0
  52. package/dist/yesterday-DW-YiRTt.mjs +9 -0
  53. package/package.json +1 -1
  54. package/skills/wangxiaobao-audio-analyze/SKILL.md +42 -0
  55. package/skills/wangxiaobao-beautx/SKILL.md +42 -0
  56. package/skills/wangxiaobao-customer-portrait/SKILL.md +45 -0
  57. package/skills/wangxiaobao-customer-query/SKILL.md +1 -1
  58. package/skills/wangxiaobao-follow-query/SKILL.md +45 -0
  59. package/skills/wangxiaobao-quantum-stats/SKILL.md +3 -1
  60. package/skills/wangxiaobao-quantum-stats/references/quantum-metrics.md +3 -2
  61. package/skills/wangxiaobao-shared/SKILL.md +5 -1
  62. /package/dist/{current-CaUOiS5G.mjs → current-ABh6R3vp.mjs} +0 -0
  63. /package/dist/{doc-CC08fj8m.mjs → doc-CJT7BuhU.mjs} +0 -0
  64. /package/dist/{doc-content-DktnDECM.mjs → doc-content-_SCykNvs.mjs} +0 -0
  65. /package/dist/{docs-DtQy3Zoc.mjs → docs-BHtwTAJ4.mjs} +0 -0
  66. /package/dist/{list-Ikc5mo6a.mjs → list-2qqSxkDM.mjs} +0 -0
  67. /package/dist/{list-DPyzRkq4.mjs → list-Ca5uJXDH.mjs} +0 -0
  68. /package/dist/{login-COK74GKN.mjs → login-Bp2W2Hnj.mjs} +0 -0
  69. /package/dist/{logout-BQnDwD5-.mjs → logout-BnoEQxKZ.mjs} +0 -0
  70. /package/dist/{qa-CDYWW-19.mjs → qa-CaV_tDBc.mjs} +0 -0
  71. /package/dist/{status-DR0tFzju.mjs → status-CrpCtf5U.mjs} +0 -0
  72. /package/dist/{text-K7uP8bat.mjs → text-CqmsXzad.mjs} +0 -0
  73. /package/dist/{use-DwoZynR9.mjs → use-rAR4OVC7.mjs} +0 -0
  74. /package/dist/{util-pyTg7qwY.mjs → util-BuoFIeLS.mjs} +0 -0
  75. /package/dist/{whoami-CtuWBu20.mjs → whoami-oRc8gILN.mjs} +0 -0
@@ -0,0 +1,14 @@
1
+ import { defineCommand } from "citty";
2
+ //#region src/commands/portrait/index.ts
3
+ var portrait_default = defineCommand({
4
+ meta: {
5
+ name: "portrait",
6
+ description: "客户画像分布:字段清单(list) / 单字段饼图(get)(按画像筛客户用 customer list --portrait)"
7
+ },
8
+ subCommands: {
9
+ list: () => import("./list-XIIj_ryX.mjs").then((m) => m.default),
10
+ get: () => import("./get-CbovJWSq.mjs").then((m) => m.default)
11
+ }
12
+ });
13
+ //#endregion
14
+ export { portrait_default as default };
@@ -0,0 +1,10 @@
1
+ import { t as defineBeautxCommand } from "./shared-Bbxvn4ZI.mjs";
2
+ //#region src/commands/beautx/portrait-tags.ts
3
+ var portrait_tags_default = defineBeautxCommand({
4
+ name: "portrait-tags",
5
+ description: "医美来访画像标签分页(维度 → 命中标签值;--dimension 过滤维度名)",
6
+ path: "/ai-open/beautx/portrait-tags",
7
+ supportsDimension: true
8
+ });
9
+ //#endregion
10
+ export { portrait_tags_default as default };
@@ -6,9 +6,9 @@ var project_default = defineCommand({
6
6
  description: "查询 / 切换激活项目"
7
7
  },
8
8
  subCommands: {
9
- list: () => import("./list-DPyzRkq4.mjs").then((m) => m.default),
10
- use: () => import("./use-DwoZynR9.mjs").then((m) => m.default),
11
- current: () => import("./current-CaUOiS5G.mjs").then((m) => m.default)
9
+ list: () => import("./list-Ca5uJXDH.mjs").then((m) => m.default),
10
+ use: () => import("./use-rAR4OVC7.mjs").then((m) => m.default),
11
+ current: () => import("./current-ABh6R3vp.mjs").then((m) => m.default)
12
12
  }
13
13
  });
14
14
  //#endregion
@@ -3,7 +3,7 @@ import { t as xbApiFetch } from "./api-client-D3sCv6L3.mjs";
3
3
  import { n as requireActiveProject } from "./project-store-CudTRvbA.mjs";
4
4
  import { t as tenantProjectHeaders } from "./headers-Dy5gROBB.mjs";
5
5
  import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
6
- import { r as toLocalDateTime, t as csvToArray } from "./util-pyTg7qwY.mjs";
6
+ import { r as toLocalDateTime, t as csvToArray } from "./util-BuoFIeLS.mjs";
7
7
  import { defineCommand } from "citty";
8
8
  //#region src/commands/quantum.ts
9
9
  /**
@@ -96,7 +96,7 @@ var quantum_default = defineCommand({
96
96
  },
97
97
  "intent-dimension": {
98
98
  type: "string",
99
- description: "review|ai(intent)"
99
+ description: "intent 数据口径:review=复核后数据(默认,日常汇报用)|ai=AI 智能评级;用户明确说「AI 评级」才传 ai"
100
100
  },
101
101
  "risk-dimension": {
102
102
  type: "string",
@@ -0,0 +1,18 @@
1
+ import { defineCommand } from "citty";
2
+ //#region src/commands/date/range/index.ts
3
+ var range_default = defineCommand({
4
+ meta: {
5
+ name: "range",
6
+ description: "算出业务查询用的 from/to(含时分秒);不查数据,只生成时间参数给 quantum / list"
7
+ },
8
+ subCommands: {
9
+ today: () => import("./today-BhQnSMJH.mjs").then((m) => m.default),
10
+ yesterday: () => import("./yesterday-CHAh1DlJ.mjs").then((m) => m.default),
11
+ "this-week": () => import("./this-week-2GoqEaXU.mjs").then((m) => m.default),
12
+ "this-month": () => import("./this-month-BRdfmc1s.mjs").then((m) => m.default),
13
+ "last-7-days": () => import("./last-7-days-VKMMIzDz.mjs").then((m) => m.default),
14
+ "today-so-far": () => import("./today-so-far-D2g98rKv.mjs").then((m) => m.default)
15
+ }
16
+ });
17
+ //#endregion
18
+ export { range_default as default };
@@ -5,7 +5,7 @@ var resistance_default = defineCommand({
5
5
  name: "resistance",
6
6
  description: "客户抗性点标签分页查询"
7
7
  },
8
- subCommands: { list: () => import("./list-DciEIXpx.mjs").then((m) => m.default) }
8
+ subCommands: { list: () => import("./list-CiNgcIXS.mjs").then((m) => m.default) }
9
9
  });
10
10
  //#endregion
11
11
  export { resistance_default as default };
@@ -3,7 +3,7 @@ import { t as xbApiFetch } from "./api-client-D3sCv6L3.mjs";
3
3
  import { n as requireActiveProject } from "./project-store-CudTRvbA.mjs";
4
4
  import { t as tenantProjectHeaders } from "./headers-Dy5gROBB.mjs";
5
5
  import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
6
- import { t as csvToArray } from "./util-pyTg7qwY.mjs";
6
+ import { t as csvToArray } from "./util-BuoFIeLS.mjs";
7
7
  import { defineCommand } from "citty";
8
8
  //#region src/commands/kb/search.ts
9
9
  /**
@@ -0,0 +1,11 @@
1
+ import { s as getRange, t as defineDateCommand } from "./shared-CYALikq5.mjs";
2
+ //#region src/commands/date/range/shared.ts
3
+ function defineRangePresetCommand(preset, description) {
4
+ return defineDateCommand({
5
+ name: preset,
6
+ description,
7
+ run: ({ args }) => getRange(preset, args.timezone)
8
+ });
9
+ }
10
+ //#endregion
11
+ export { defineRangePresetCommand as t };
@@ -0,0 +1,92 @@
1
+ import { o as resolveConfig } from "./device-flow-j10PFOQL.mjs";
2
+ import { t as xbApiFetch } from "./api-client-D3sCv6L3.mjs";
3
+ import { n as requireActiveProject } from "./project-store-CudTRvbA.mjs";
4
+ import { t as tenantProjectHeaders } from "./headers-Dy5gROBB.mjs";
5
+ import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
6
+ import { r as toLocalDateTime, t as csvToArray } from "./util-BuoFIeLS.mjs";
7
+ import { defineCommand } from "citty";
8
+ //#region src/commands/beautx/shared.ts
9
+ /**
10
+ * Shared args/body builder for `xiaobao-cli beautx *` — the four beautx (医美)
11
+ * queries share one request shape (visitIds/wangIds/beautxCustomerIds/时间窗/分页).
12
+ */
13
+ function defineBeautxCommand(def) {
14
+ return defineCommand({
15
+ meta: {
16
+ name: def.name,
17
+ description: def.description
18
+ },
19
+ args: {
20
+ "visit-ids": {
21
+ type: "string",
22
+ description: "CSV: 来访 ID 过滤"
23
+ },
24
+ "customer-ids": {
25
+ type: "string",
26
+ description: "CSV: 客户 wang_id 过滤"
27
+ },
28
+ "beautx-customer-ids": {
29
+ type: "string",
30
+ description: "CSV: 医美业务客户 ID 过滤"
31
+ },
32
+ ...def.supportsLatestOnly ? { "latest-only": {
33
+ type: "boolean",
34
+ description: "每客户只取最新一条"
35
+ } } : {},
36
+ ...def.supportsDimension ? { dimension: {
37
+ type: "string",
38
+ description: "画像标签维度名过滤"
39
+ } } : {},
40
+ from: {
41
+ type: "string",
42
+ description: "开始时间(含)"
43
+ },
44
+ to: {
45
+ type: "string",
46
+ description: "结束时间(不含)"
47
+ },
48
+ page: {
49
+ type: "string",
50
+ default: "1"
51
+ },
52
+ size: {
53
+ type: "string",
54
+ default: "10"
55
+ },
56
+ "api-base": { type: "string" },
57
+ "auth-base": { type: "string" },
58
+ format: {
59
+ type: "string",
60
+ default: "toon"
61
+ }
62
+ },
63
+ async run({ args }) {
64
+ try {
65
+ const config = resolveConfig({
66
+ apiBase: args["api-base"],
67
+ authBase: args["auth-base"]
68
+ });
69
+ const active = await requireActiveProject();
70
+ writeResult(await xbApiFetch(config, "POST", def.path, {
71
+ headers: tenantProjectHeaders(active),
72
+ body: {
73
+ visitIds: csvToArray(args["visit-ids"]),
74
+ customerIds: csvToArray(args["customer-ids"]),
75
+ beautxCustomerIds: csvToArray(args["beautx-customer-ids"])?.map(Number),
76
+ latestOnly: def.supportsLatestOnly ? args["latest-only"] : void 0,
77
+ dimensionName: def.supportsDimension ? args.dimension : void 0,
78
+ fromDate: toLocalDateTime(args.from),
79
+ toDate: toLocalDateTime(args.to),
80
+ page: Number(args.page),
81
+ size: Number(args.size)
82
+ }
83
+ }), args.format);
84
+ } catch (err) {
85
+ writeError(err, args.format);
86
+ process.exit(1);
87
+ }
88
+ }
89
+ });
90
+ }
91
+ //#endregion
92
+ export { defineBeautxCommand as t };
@@ -0,0 +1,277 @@
1
+ import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
2
+ import { defineCommand } from "citty";
3
+ //#region src/core/date-util.ts
4
+ /**
5
+ * Local date/time helpers for `xiaobao-cli date *` (no network).
6
+ *
7
+ * Default timezone: Asia/Shanghai (or TZ env). Weekday numbering: 1=Monday … 7=Sunday.
8
+ */
9
+ const DEFAULT_TIMEZONE = "Asia/Shanghai";
10
+ const DATE_RE = /^(\d{4})-(\d{2})-(\d{2})$/;
11
+ const WEEKDAY_SHORT_TO_NUM = {
12
+ Mon: 1,
13
+ Tue: 2,
14
+ Wed: 3,
15
+ Thu: 4,
16
+ Fri: 5,
17
+ Sat: 6,
18
+ Sun: 7
19
+ };
20
+ var DateInputError = class extends Error {
21
+ code = "INVALID_DATE";
22
+ hint = "日期须为 YYYY-MM-DD;days 须为非负整数";
23
+ constructor(message) {
24
+ super(message);
25
+ this.name = "DateInputError";
26
+ }
27
+ };
28
+ function resolveTimezone(input) {
29
+ const tz = (input ?? process.env.TZ ?? "Asia/Shanghai").trim();
30
+ if (!tz) return DEFAULT_TIMEZONE;
31
+ try {
32
+ Intl.DateTimeFormat(void 0, { timeZone: tz });
33
+ return tz;
34
+ } catch {
35
+ throw new DateInputError(`无效时区: ${tz}`);
36
+ }
37
+ }
38
+ function parseYmd(date) {
39
+ const m = DATE_RE.exec(date.trim());
40
+ if (!m) throw new DateInputError(`无效日期: ${date}`);
41
+ const year = Number(m[1]);
42
+ const month = Number(m[2]);
43
+ const day = Number(m[3]);
44
+ const probe = new Date(Date.UTC(year, month - 1, day));
45
+ if (probe.getUTCFullYear() !== year || probe.getUTCMonth() + 1 !== month || probe.getUTCDate() !== day) throw new DateInputError(`无效日期: ${date}`);
46
+ return {
47
+ year,
48
+ month,
49
+ day
50
+ };
51
+ }
52
+ function pad2(n) {
53
+ return String(n).padStart(2, "0");
54
+ }
55
+ function formatYmd(ymd) {
56
+ return `${ymd.year}-${pad2(ymd.month)}-${pad2(ymd.day)}`;
57
+ }
58
+ function formatDateTime(parts) {
59
+ return `${formatYmd(parts)} ${pad2(parts.hour)}:${pad2(parts.minute)}:${pad2(parts.second)}`;
60
+ }
61
+ function getZonedParts(instant, timeZone) {
62
+ const parts = new Intl.DateTimeFormat("en-US", {
63
+ timeZone,
64
+ year: "numeric",
65
+ month: "2-digit",
66
+ day: "2-digit",
67
+ hour: "2-digit",
68
+ minute: "2-digit",
69
+ second: "2-digit",
70
+ weekday: "short",
71
+ hour12: false,
72
+ hourCycle: "h23"
73
+ }).formatToParts(instant);
74
+ const pick = (type) => parts.find((p) => p.type === type)?.value ?? "";
75
+ const hourRaw = Number(pick("hour"));
76
+ const hour = hourRaw === 24 ? 0 : hourRaw;
77
+ return {
78
+ year: Number(pick("year")),
79
+ month: Number(pick("month")),
80
+ day: Number(pick("day")),
81
+ hour,
82
+ minute: Number(pick("minute")),
83
+ second: Number(pick("second")),
84
+ weekdayShort: pick("weekday")
85
+ };
86
+ }
87
+ function weekdayNumFromShort(short) {
88
+ const num = WEEKDAY_SHORT_TO_NUM[short];
89
+ if (!num) throw new DateInputError(`无法解析星期: ${short}`);
90
+ return num;
91
+ }
92
+ function weekdayZh(instant, timeZone) {
93
+ return new Intl.DateTimeFormat("zh-CN", {
94
+ timeZone,
95
+ weekday: "long"
96
+ }).format(instant);
97
+ }
98
+ function zonedInstant(ymd, hms, timeZone) {
99
+ const [hh, mm, ss] = hms.split(":").map(Number);
100
+ const utcGuess = Date.UTC(ymd.year, ymd.month - 1, ymd.day, hh, mm, ss);
101
+ const offset = getTimezoneOffsetMs(timeZone, new Date(utcGuess));
102
+ return new Date(utcGuess - offset);
103
+ }
104
+ function getTimezoneOffsetMs(timeZone, date) {
105
+ const parts = getZonedParts(date, timeZone);
106
+ return Date.UTC(parts.year, parts.month - 1, parts.day, parts.hour, parts.minute, parts.second) - date.getTime();
107
+ }
108
+ function addCalendarDays(ymd, offset) {
109
+ const dt = new Date(Date.UTC(ymd.year, ymd.month - 1, ymd.day + offset));
110
+ return {
111
+ year: dt.getUTCFullYear(),
112
+ month: dt.getUTCMonth() + 1,
113
+ day: dt.getUTCDate()
114
+ };
115
+ }
116
+ function buildDateInfo(parts, timeZone, instant) {
117
+ const weekdayNum = weekdayNumFromShort(parts.weekdayShort);
118
+ return {
119
+ date: formatYmd(parts),
120
+ datetime: formatDateTime(parts),
121
+ timezone: timeZone,
122
+ weekday: weekdayZh(instant, timeZone),
123
+ weekdayNum
124
+ };
125
+ }
126
+ function getNow(timeZoneInput) {
127
+ const timeZone = resolveTimezone(timeZoneInput);
128
+ const instant = /* @__PURE__ */ new Date();
129
+ return buildDateInfo(getZonedParts(instant, timeZone), timeZone, instant);
130
+ }
131
+ function getDateInfo(date, timeZoneInput) {
132
+ const timeZone = resolveTimezone(timeZoneInput);
133
+ const instant = zonedInstant(parseYmd(date), "00:00:00", timeZone);
134
+ const parts = getZonedParts(instant, timeZone);
135
+ return {
136
+ date: formatYmd(parts),
137
+ timezone: timeZone,
138
+ weekday: weekdayZh(instant, timeZone),
139
+ weekdayNum: weekdayNumFromShort(parts.weekdayShort)
140
+ };
141
+ }
142
+ function getRelativeDay(offsetDays, timeZoneInput) {
143
+ const timeZone = resolveTimezone(timeZoneInput);
144
+ return getDateInfo(formatYmd(addCalendarDays(getZonedParts(/* @__PURE__ */ new Date(), timeZone), offsetDays)), timeZone);
145
+ }
146
+ function addDays(date, offset, timeZoneInput) {
147
+ const timeZone = resolveTimezone(timeZoneInput);
148
+ return getDateInfo(formatYmd(addCalendarDays(parseYmd(date), offset)), timeZone);
149
+ }
150
+ function dateDiff(startDate, endDate) {
151
+ const start = parseYmd(startDate);
152
+ const end = parseYmd(endDate);
153
+ const startMs = Date.UTC(start.year, start.month - 1, start.day);
154
+ const endMs = Date.UTC(end.year, end.month - 1, end.day);
155
+ return {
156
+ startDate: formatYmd(start),
157
+ endDate: formatYmd(end),
158
+ days: Math.round((endMs - startMs) / 864e5)
159
+ };
160
+ }
161
+ function startOfWeekMonday(ymd, timeZone) {
162
+ return addCalendarDays(ymd, -(weekdayNumFromShort(getZonedParts(zonedInstant(ymd, "12:00:00", timeZone), timeZone).weekdayShort) - 1));
163
+ }
164
+ function startOfMonth(ymd) {
165
+ return {
166
+ year: ymd.year,
167
+ month: ymd.month,
168
+ day: 1
169
+ };
170
+ }
171
+ function nextMonthStart(ymd) {
172
+ if (ymd.month === 12) return {
173
+ year: ymd.year + 1,
174
+ month: 1,
175
+ day: 1
176
+ };
177
+ return {
178
+ year: ymd.year,
179
+ month: ymd.month + 1,
180
+ day: 1
181
+ };
182
+ }
183
+ function getRange(preset, timeZoneInput) {
184
+ const timeZone = resolveTimezone(timeZoneInput);
185
+ const todayParts = getZonedParts(/* @__PURE__ */ new Date(), timeZone);
186
+ const today = formatYmd(todayParts);
187
+ const tomorrow = formatYmd(addCalendarDays(todayParts, 1));
188
+ const yesterday = formatYmd(addCalendarDays(todayParts, -1));
189
+ let from;
190
+ let to;
191
+ switch (preset) {
192
+ case "today":
193
+ from = `${today} 00:00:00`;
194
+ to = `${tomorrow} 00:00:00`;
195
+ break;
196
+ case "yesterday":
197
+ from = `${yesterday} 00:00:00`;
198
+ to = `${today} 00:00:00`;
199
+ break;
200
+ case "today-so-far":
201
+ from = `${today} 00:00:00`;
202
+ to = formatDateTime(todayParts);
203
+ break;
204
+ case "this-week": {
205
+ const monday = formatYmd(startOfWeekMonday(todayParts, timeZone));
206
+ const nextMonday = formatYmd(addCalendarDays(parseYmd(monday), 7));
207
+ from = `${monday} 00:00:00`;
208
+ to = `${nextMonday} 00:00:00`;
209
+ break;
210
+ }
211
+ case "this-month": {
212
+ const monthStart = formatYmd(startOfMonth(todayParts));
213
+ const nextMonth = formatYmd(nextMonthStart(todayParts));
214
+ from = `${monthStart} 00:00:00`;
215
+ to = `${nextMonth} 00:00:00`;
216
+ break;
217
+ }
218
+ case "last-7-days":
219
+ from = `${formatYmd(addCalendarDays(todayParts, -6))} 00:00:00`;
220
+ to = `${tomorrow} 00:00:00`;
221
+ break;
222
+ default: throw new DateInputError(`未知 preset: ${preset}`);
223
+ }
224
+ const anchor = getDateInfo(today, timeZone);
225
+ return {
226
+ range: preset,
227
+ timezone: timeZone,
228
+ from,
229
+ to,
230
+ date: anchor.date,
231
+ weekday: anchor.weekday,
232
+ weekdayNum: anchor.weekdayNum
233
+ };
234
+ }
235
+ //#endregion
236
+ //#region src/commands/date/shared.ts
237
+ /**
238
+ * Shared helpers for `xiaobao-cli date *`.
239
+ */
240
+ const timezoneArg = { timezone: {
241
+ type: "string",
242
+ description: "IANA 时区,默认 Asia/Shanghai(或 TZ 环境变量)"
243
+ } };
244
+ function parsePositiveDays(raw, label = "days") {
245
+ if (raw === void 0 || raw === "") throw new DateInputError(`缺少 ${label}`);
246
+ const days = Number(raw);
247
+ if (!Number.isInteger(days) || days < 0) throw new DateInputError(`${label} 须为非负整数: ${raw}`);
248
+ return days;
249
+ }
250
+ function defineDateCommand(def) {
251
+ return defineCommand({
252
+ meta: {
253
+ name: def.name,
254
+ description: def.description
255
+ },
256
+ args: {
257
+ format: {
258
+ type: "string",
259
+ default: "toon",
260
+ description: "Stdout format: toon (default) / json / table"
261
+ },
262
+ ...timezoneArg,
263
+ ...def.args
264
+ },
265
+ async run({ args }) {
266
+ const format = typeof args.format === "string" ? args.format : void 0;
267
+ try {
268
+ writeResult(def.run({ args }), format);
269
+ } catch (err) {
270
+ writeError(err, format);
271
+ process.exit(1);
272
+ }
273
+ }
274
+ });
275
+ }
276
+ //#endregion
277
+ export { getDateInfo as a, getRelativeDay as c, dateDiff as i, parsePositiveDays as n, getNow as o, addDays as r, getRange as s, defineDateCommand as t };
@@ -0,0 +1,21 @@
1
+ import { n as parsePositiveDays, r as addDays, t as defineDateCommand } from "./shared-CYALikq5.mjs";
2
+ //#region src/commands/date/subtract.ts
3
+ var subtract_default = defineDateCommand({
4
+ name: "subtract",
5
+ description: "日期往前推 N 天",
6
+ args: {
7
+ date: {
8
+ type: "positional",
9
+ required: true,
10
+ description: "基准日期 YYYY-MM-DD"
11
+ },
12
+ days: {
13
+ type: "positional",
14
+ required: true,
15
+ description: "往前推的天数(非负整数)"
16
+ }
17
+ },
18
+ run: ({ args }) => addDays(args.date, -parsePositiveDays(args.days, "days"), args.timezone)
19
+ });
20
+ //#endregion
21
+ export { subtract_default as default };
@@ -3,7 +3,7 @@ import { t as xbApiFetch } from "./api-client-D3sCv6L3.mjs";
3
3
  import { n as requireActiveProject } from "./project-store-CudTRvbA.mjs";
4
4
  import { t as tenantProjectHeaders } from "./headers-Dy5gROBB.mjs";
5
5
  import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
6
- import { r as toLocalDateTime } from "./util-pyTg7qwY.mjs";
6
+ import { r as toLocalDateTime } from "./util-BuoFIeLS.mjs";
7
7
  import { defineCommand } from "citty";
8
8
  //#region src/commands/visit/summary.ts
9
9
  /**
@@ -0,0 +1,65 @@
1
+ import { o as resolveConfig } from "./device-flow-j10PFOQL.mjs";
2
+ import { t as xbApiFetch } from "./api-client-D3sCv6L3.mjs";
3
+ import { n as requireActiveProject } from "./project-store-CudTRvbA.mjs";
4
+ import { t as tenantProjectHeaders } from "./headers-Dy5gROBB.mjs";
5
+ import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
6
+ import { r as toLocalDateTime, t as csvToArray } from "./util-BuoFIeLS.mjs";
7
+ import { defineCommand } from "citty";
8
+ //#region src/commands/follow/summary.ts
9
+ /**
10
+ * `xiaobao-cli follow summary` — 旺跟进汇总(电话/微信指标)。
11
+ *
12
+ * 同 follow list 的筛选条件,返回电话呼入/呼出次数与接通率、通话时长、
13
+ * 微信通话与消息数等指标(不分页)。调 POST /ai-open/follows/summary。
14
+ */
15
+ var summary_default = defineCommand({
16
+ meta: {
17
+ name: "summary",
18
+ description: "旺跟进汇总:电话呼入/呼出/接通率/时长、微信通话与消息数"
19
+ },
20
+ args: {
21
+ "user-ids": {
22
+ type: "string",
23
+ description: "CSV: 跟进人 userId 过滤;不传按当前授权范围"
24
+ },
25
+ "customer-ids": {
26
+ type: "string",
27
+ description: "CSV: 客户 wang_id 过滤"
28
+ },
29
+ from: {
30
+ type: "string",
31
+ description: "开始时间(含)"
32
+ },
33
+ to: {
34
+ type: "string",
35
+ description: "结束时间(不含)"
36
+ },
37
+ "api-base": { type: "string" },
38
+ "auth-base": { type: "string" },
39
+ format: {
40
+ type: "string",
41
+ default: "toon"
42
+ }
43
+ },
44
+ async run({ args }) {
45
+ try {
46
+ writeResult(await xbApiFetch(resolveConfig({
47
+ apiBase: args["api-base"],
48
+ authBase: args["auth-base"]
49
+ }), "POST", "/ai-open/follows/summary", {
50
+ headers: tenantProjectHeaders(await requireActiveProject()),
51
+ body: {
52
+ userIds: csvToArray(args["user-ids"])?.map(Number),
53
+ customerIds: csvToArray(args["customer-ids"])?.map(Number),
54
+ fromDate: toLocalDateTime(args.from),
55
+ toDate: toLocalDateTime(args.to)
56
+ }
57
+ }), args.format);
58
+ } catch (err) {
59
+ writeError(err, args.format);
60
+ process.exit(1);
61
+ }
62
+ }
63
+ });
64
+ //#endregion
65
+ export { summary_default as default };
@@ -0,0 +1,5 @@
1
+ import { t as defineRangePresetCommand } from "./shared-BEkL4JRB.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-BEkL4JRB.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,5 @@
1
+ import { t as defineRangePresetCommand } from "./shared-BEkL4JRB.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,9 @@
1
+ import { c as getRelativeDay, t as defineDateCommand } from "./shared-CYALikq5.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-BEkL4JRB.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,9 @@
1
+ import { c as getRelativeDay, t as defineDateCommand } from "./shared-CYALikq5.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 };
@@ -6,8 +6,8 @@ var visit_default = defineCommand({
6
6
  description: "客户来访分页查询 / 来访接待总结"
7
7
  },
8
8
  subCommands: {
9
- list: () => import("./list-Ca5Fvq_e.mjs").then((m) => m.default),
10
- summary: () => import("./summary-C3poiB2C.mjs").then((m) => m.default)
9
+ list: () => import("./list-DWv6toPT.mjs").then((m) => m.default),
10
+ summary: () => import("./summary-BIx7F4AE.mjs").then((m) => m.default)
11
11
  }
12
12
  });
13
13
  //#endregion
@@ -0,0 +1,9 @@
1
+ import { t as defineBeautxCommand } from "./shared-Bbxvn4ZI.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-CYALikq5.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,5 @@
1
+ import { t as defineRangePresetCommand } from "./shared-BEkL4JRB.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 };