@puyinkai/xiaobao-cli 0.3.0 → 0.5.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.
- package/README.md +9 -0
- package/dist/admin-BOL_otwc.mjs +14 -0
- package/dist/{api-DtFEKH3I.mjs → api-BaX_r5S5.mjs} +5 -5
- package/dist/{api-client-CDNjkArS.mjs → api-client-D3sCv6L3.mjs} +2 -2
- package/dist/{audio-DhEiStuy.mjs → audio-DzcmDYVu.mjs} +2 -2
- package/dist/{auth-BYWDBat3.mjs → auth-DvvYyJBK.mjs} +4 -3
- package/dist/cli.mjs +13 -12
- package/dist/{consultant-DvH6ezCT.mjs → consultant-Ccnjnhzz.mjs} +1 -1
- package/dist/{current-gZDEGEmi.mjs → current-CaUOiS5G.mjs} +2 -2
- package/dist/{customer-BtAtJyM8.mjs → customer-D_LctjqX.mjs} +1 -1
- package/dist/{device-flow-D6JVcEap.mjs → device-flow-j10PFOQL.mjs} +42 -31
- package/dist/{doc--iAF-laM.mjs → doc-CC08fj8m.mjs} +5 -5
- package/dist/{doc-content-CqDVEgwX.mjs → doc-content-DktnDECM.mjs} +5 -5
- package/dist/{docs-C_sC8m3F.mjs → docs-DtQy3Zoc.mjs} +5 -5
- package/dist/{focus-BmLvFWII.mjs → focus-BPPyRCBb.mjs} +1 -1
- package/dist/{kb-B9IY8-fu.mjs → kb-DpBUFdFV.mjs} +4 -4
- package/dist/{list-CZVU6EVq.mjs → list-CTSX1XuK.mjs} +6 -6
- package/dist/{list-D2qM7Ghn.mjs → list-Ca5Fvq_e.mjs} +6 -6
- package/dist/{list-DW4Sk-76.mjs → list-DPyzRkq4.mjs} +3 -3
- package/dist/{list-VJImXOzy.mjs → list-D_8QLOZ1.mjs} +6 -6
- package/dist/{list-D94oyNpR.mjs → list-DciEIXpx.mjs} +6 -6
- package/dist/{list-CiBpxZFs.mjs → list-Ikc5mo6a.mjs} +5 -5
- package/dist/{list-DDGGG2p2.mjs → list-xbJZbyGQ.mjs} +6 -6
- package/dist/{login-B5e9tJbS.mjs → login-COK74GKN.mjs} +10 -3
- package/dist/{logout-Dz_FFIRP.mjs → logout-BQnDwD5-.mjs} +3 -3
- package/dist/{project-C2fvEuDl.mjs → project-CYA9qd8k.mjs} +3 -3
- package/dist/{qa-C2TSTS-m.mjs → qa-CDYWW-19.mjs} +5 -5
- package/dist/{quantum-4m2WGRWI.mjs → quantum-Dyhp2Clf.mjs} +6 -6
- package/dist/{resistance-B0gVs7-5.mjs → resistance-BhlYgeUx.mjs} +1 -1
- package/dist/sales-report-BIfyfucO.mjs +70 -0
- package/dist/{search-CBWh8yKE.mjs → search-ChFFOKV4.mjs} +6 -6
- package/dist/status-DR0tFzju.mjs +65 -0
- package/dist/{summary-CcLTV5wr.mjs → summary-C3poiB2C.mjs} +6 -6
- package/dist/{text-bgoI1KC-.mjs → text-K7uP8bat.mjs} +5 -5
- package/dist/token-usage-y46b3_7C.mjs +102 -0
- package/dist/{use-xbTXVwXb.mjs → use-DwoZynR9.mjs} +2 -2
- package/dist/{visit-vRqOvBv5.mjs → visit-qf8Lwf_s.mjs} +2 -2
- package/dist/{whoami-BMAFa4es.mjs → whoami-CtuWBu20.mjs} +2 -2
- package/package.json +3 -2
- package/skills/wangxiaobao-admin-sales-report/SKILL.md +54 -0
- package/skills/wangxiaobao-admin-token-usage/SKILL.md +53 -0
- package/skills/wangxiaobao-shared/SKILL.md +5 -0
- /package/dist/{format-CvKe7-yU.mjs → format-DfVypHID.mjs} +0 -0
- /package/dist/{headers-DSnR4sjk.mjs → headers-Dy5gROBB.mjs} +0 -0
- /package/dist/{project-store-CKVJa54T.mjs → project-store-CudTRvbA.mjs} +0 -0
- /package/dist/{token-store-CXizLE2_.mjs → token-store-BB7n-fwJ.mjs} +0 -0
- /package/dist/{util-CaPQBlNa.mjs → util-pyTg7qwY.mjs} +0 -0
package/README.md
CHANGED
|
@@ -56,8 +56,17 @@ xiaobao-cli audio list --from "2026-05-01 00:00:00" --to "2026-05-02 00:00:00" -
|
|
|
56
56
|
| `kb doc <doc-id>` | 新增 · 知识库文档详情 |
|
|
57
57
|
| `kb doc-content <doc-id> [--offset] [--limit]` | 新增 · 知识库文档正文分页 |
|
|
58
58
|
| `quantum <metric> [--view] [--visit-type] …` | 新增 · 量子看板 / KPI 统计(20 指标) |
|
|
59
|
+
| `admin sales-report --from --to [--by project\|zone]` | 新增 · 公司经营数据 出库/回款(super-admin,独立白名单) |
|
|
60
|
+
| `admin token-usage --from --to [--model] …` | 新增 · LLM token 用量(super-admin,独立白名单) |
|
|
59
61
|
| `api <METHOD> <path>` | `xiaobao_api` |
|
|
60
62
|
|
|
63
|
+
## WorkBuddy Connector
|
|
64
|
+
|
|
65
|
+
`workbuddy/` 是按《WorkBuddy Connector 对接规范》方案二(CLI + Skill)准备的连接器配置
|
|
66
|
+
(`connector-meta.json` / `cli.json` / `icon.svg`);`npm run workbuddy:pack` 会连同 `skills/`
|
|
67
|
+
打成 `dist-workbuddy/wangxiaobao-connector.zip` 供提交审核。认证走 `auth login`(device flow)
|
|
68
|
+
+ `auth status`(exit 0 = 已登录,可完成待授权的 device code 换 token)+ `auth logout`。
|
|
69
|
+
|
|
61
70
|
## 通用 flags
|
|
62
71
|
|
|
63
72
|
- `--format toon|json|table` —— 默认 `toon`(省 token,适合 LLM 上下文);`json` 严格 JSON、agent/人类友好;`table` 暂未实现(回退 JSON)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
import { defineCommand } from "citty";
|
|
2
|
+
//#region src/commands/admin/index.ts
|
|
3
|
+
var admin_default = defineCommand({
|
|
4
|
+
meta: {
|
|
5
|
+
name: "admin",
|
|
6
|
+
description: "super-admin 经营报表:公司经营数据(出库/回款)/ LLM token 用量(独立白名单)"
|
|
7
|
+
},
|
|
8
|
+
subCommands: {
|
|
9
|
+
"sales-report": () => import("./sales-report-BIfyfucO.mjs").then((m) => m.default),
|
|
10
|
+
"token-usage": () => import("./token-usage-y46b3_7C.mjs").then((m) => m.default)
|
|
11
|
+
}
|
|
12
|
+
});
|
|
13
|
+
//#endregion
|
|
14
|
+
export { admin_default as default };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { t as loadActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
1
|
+
import { o as resolveConfig } from "./device-flow-j10PFOQL.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-D3sCv6L3.mjs";
|
|
3
|
+
import { t as loadActiveProject } 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
6
|
import { defineCommand } from "citty";
|
|
7
7
|
//#region src/commands/api.ts
|
|
8
8
|
/**
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as isAccessTokenValid, l as writeToken, s as readToken } from "./token-store-
|
|
1
|
+
import { i as refreshToken } from "./device-flow-j10PFOQL.mjs";
|
|
2
|
+
import { a as isAccessTokenValid, l as writeToken, s as readToken } from "./token-store-BB7n-fwJ.mjs";
|
|
3
3
|
//#region src/core/api-client.ts
|
|
4
4
|
/**
|
|
5
5
|
* HTTP client for wangxiaobao open API endpoints.
|
|
@@ -6,8 +6,8 @@ var audio_default = defineCommand({
|
|
|
6
6
|
description: "录音元数据分页 / 单条文本查询"
|
|
7
7
|
},
|
|
8
8
|
subCommands: {
|
|
9
|
-
list: () => import("./list-
|
|
10
|
-
text: () => import("./text-
|
|
9
|
+
list: () => import("./list-CTSX1XuK.mjs").then((m) => m.default),
|
|
10
|
+
text: () => import("./text-K7uP8bat.mjs").then((m) => m.default)
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
13
|
//#endregion
|
|
@@ -6,9 +6,10 @@ var auth_default = defineCommand({
|
|
|
6
6
|
description: "OAuth 登录 / 身份查询 / 登出(device flow)"
|
|
7
7
|
},
|
|
8
8
|
subCommands: {
|
|
9
|
-
login: () => import("./login-
|
|
10
|
-
whoami: () => import("./whoami-
|
|
11
|
-
|
|
9
|
+
login: () => import("./login-COK74GKN.mjs").then((m) => m.default),
|
|
10
|
+
whoami: () => import("./whoami-CtuWBu20.mjs").then((m) => m.default),
|
|
11
|
+
status: () => import("./status-DR0tFzju.mjs").then((m) => m.default),
|
|
12
|
+
logout: () => import("./logout-BQnDwD5-.mjs").then((m) => m.default)
|
|
12
13
|
}
|
|
13
14
|
});
|
|
14
15
|
//#endregion
|
package/dist/cli.mjs
CHANGED
|
@@ -19,18 +19,19 @@ runMain(defineCommand({
|
|
|
19
19
|
description: "旺小宝 CLI — host-agnostic 业务数据 / 问数 / 来访总结 / 知识库 能力 (openclaw-xiaobao plugin 的 CLI 等价物)"
|
|
20
20
|
},
|
|
21
21
|
subCommands: {
|
|
22
|
-
auth: () => import("./auth-
|
|
23
|
-
project: () => import("./project-
|
|
24
|
-
consultant: () => import("./consultant-
|
|
25
|
-
audio: () => import("./audio-
|
|
26
|
-
customer: () => import("./customer-
|
|
27
|
-
visit: () => import("./visit-
|
|
28
|
-
focus: () => import("./focus-
|
|
29
|
-
resistance: () => import("./resistance-
|
|
30
|
-
qa: () => import("./qa-
|
|
31
|
-
kb: () => import("./kb-
|
|
32
|
-
quantum: () => import("./quantum-
|
|
33
|
-
|
|
22
|
+
auth: () => import("./auth-DvvYyJBK.mjs").then((m) => m.default),
|
|
23
|
+
project: () => import("./project-CYA9qd8k.mjs").then((m) => m.default),
|
|
24
|
+
consultant: () => import("./consultant-Ccnjnhzz.mjs").then((m) => m.default),
|
|
25
|
+
audio: () => import("./audio-DzcmDYVu.mjs").then((m) => m.default),
|
|
26
|
+
customer: () => import("./customer-D_LctjqX.mjs").then((m) => m.default),
|
|
27
|
+
visit: () => import("./visit-qf8Lwf_s.mjs").then((m) => m.default),
|
|
28
|
+
focus: () => import("./focus-BPPyRCBb.mjs").then((m) => m.default),
|
|
29
|
+
resistance: () => import("./resistance-BhlYgeUx.mjs").then((m) => m.default),
|
|
30
|
+
qa: () => import("./qa-CDYWW-19.mjs").then((m) => m.default),
|
|
31
|
+
kb: () => import("./kb-DpBUFdFV.mjs").then((m) => m.default),
|
|
32
|
+
quantum: () => import("./quantum-Dyhp2Clf.mjs").then((m) => m.default),
|
|
33
|
+
admin: () => import("./admin-BOL_otwc.mjs").then((m) => m.default),
|
|
34
|
+
api: () => import("./api-BaX_r5S5.mjs").then((m) => m.default)
|
|
34
35
|
}
|
|
35
36
|
}));
|
|
36
37
|
//#endregion
|
|
@@ -5,7 +5,7 @@ var consultant_default = defineCommand({
|
|
|
5
5
|
name: "consultant",
|
|
6
6
|
description: "查询有权限的置业顾问列表"
|
|
7
7
|
},
|
|
8
|
-
subCommands: { list: () => import("./list-
|
|
8
|
+
subCommands: { list: () => import("./list-Ikc5mo6a.mjs").then((m) => m.default) }
|
|
9
9
|
});
|
|
10
10
|
//#endregion
|
|
11
11
|
export { consultant_default as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { n as requireActiveProject } from "./project-store-
|
|
2
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
1
|
+
import { n as requireActiveProject } from "./project-store-CudTRvbA.mjs";
|
|
2
|
+
import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
//#region src/commands/project/current.ts
|
|
5
5
|
/**
|
|
@@ -5,7 +5,7 @@ var customer_default = defineCommand({
|
|
|
5
5
|
name: "customer",
|
|
6
6
|
description: "客户画像分页查询"
|
|
7
7
|
},
|
|
8
|
-
subCommands: { list: () => import("./list-
|
|
8
|
+
subCommands: { list: () => import("./list-xbJZbyGQ.mjs").then((m) => m.default) }
|
|
9
9
|
});
|
|
10
10
|
//#endregion
|
|
11
11
|
export { customer_default as default };
|
|
@@ -88,6 +88,43 @@ async function initiateDeviceAuthorization(config) {
|
|
|
88
88
|
};
|
|
89
89
|
return data;
|
|
90
90
|
}
|
|
91
|
+
/**
|
|
92
|
+
* RFC 8628 §3.4 — ONE token-endpoint attempt. `'pending'` / `'slow_down'`
|
|
93
|
+
* mean "not yet"; anything else terminal is thrown. Shared by the blocking
|
|
94
|
+
* poll loop and by `auth status` (which must return within seconds).
|
|
95
|
+
*/
|
|
96
|
+
async function exchangeDeviceCode(config, deviceCode) {
|
|
97
|
+
const url = `${config.authBase}/oauth2/token`;
|
|
98
|
+
const body = new URLSearchParams({
|
|
99
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
100
|
+
device_code: deviceCode
|
|
101
|
+
});
|
|
102
|
+
const resp = await fetch(url, {
|
|
103
|
+
method: "POST",
|
|
104
|
+
headers: authHeaders(config),
|
|
105
|
+
body: body.toString()
|
|
106
|
+
});
|
|
107
|
+
const parsed = await resp.json();
|
|
108
|
+
if (resp.ok) return parsed;
|
|
109
|
+
const err = parsed.error;
|
|
110
|
+
if (err === "authorization_pending") return "pending";
|
|
111
|
+
if (err === "slow_down") return "slow_down";
|
|
112
|
+
if (err === "access_denied") throw {
|
|
113
|
+
code: "ACCESS_DENIED",
|
|
114
|
+
message: "User declined authorization",
|
|
115
|
+
body: parsed
|
|
116
|
+
};
|
|
117
|
+
if (err === "expired_token") throw {
|
|
118
|
+
code: "EXPIRED_TOKEN",
|
|
119
|
+
message: "Device code expired before user approved",
|
|
120
|
+
body: parsed
|
|
121
|
+
};
|
|
122
|
+
throw {
|
|
123
|
+
code: "TOKEN_POLL_FAILED",
|
|
124
|
+
status: resp.status,
|
|
125
|
+
body: parsed
|
|
126
|
+
};
|
|
127
|
+
}
|
|
91
128
|
/** RFC 8628 §3.4 — poll the token endpoint until success / denial / expiry. */
|
|
92
129
|
async function pollForToken(config, deviceCode, intervalSeconds, expiresInSeconds) {
|
|
93
130
|
const serverDeadline = Date.now() + expiresInSeconds * 1e3;
|
|
@@ -95,39 +132,13 @@ async function pollForToken(config, deviceCode, intervalSeconds, expiresInSecond
|
|
|
95
132
|
let pollIntervalMs = Math.max(1, intervalSeconds) * 1e3;
|
|
96
133
|
while (Date.now() < Math.min(serverDeadline, hardDeadline)) {
|
|
97
134
|
await sleep(pollIntervalMs);
|
|
98
|
-
const
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
device_code: deviceCode
|
|
102
|
-
});
|
|
103
|
-
const resp = await fetch(url, {
|
|
104
|
-
method: "POST",
|
|
105
|
-
headers: authHeaders(config),
|
|
106
|
-
body: body.toString()
|
|
107
|
-
});
|
|
108
|
-
const parsed = await resp.json();
|
|
109
|
-
if (resp.ok) return parsed;
|
|
110
|
-
const err = parsed.error;
|
|
111
|
-
if (err === "authorization_pending") continue;
|
|
112
|
-
if (err === "slow_down") {
|
|
135
|
+
const result = await exchangeDeviceCode(config, deviceCode);
|
|
136
|
+
if (result === "pending") continue;
|
|
137
|
+
if (result === "slow_down") {
|
|
113
138
|
pollIntervalMs += 5e3;
|
|
114
139
|
continue;
|
|
115
140
|
}
|
|
116
|
-
|
|
117
|
-
code: "ACCESS_DENIED",
|
|
118
|
-
message: "User declined authorization",
|
|
119
|
-
body: parsed
|
|
120
|
-
};
|
|
121
|
-
if (err === "expired_token") throw {
|
|
122
|
-
code: "EXPIRED_TOKEN",
|
|
123
|
-
message: "Device code expired before user approved",
|
|
124
|
-
body: parsed
|
|
125
|
-
};
|
|
126
|
-
throw {
|
|
127
|
-
code: "TOKEN_POLL_FAILED",
|
|
128
|
-
status: resp.status,
|
|
129
|
-
body: parsed
|
|
130
|
-
};
|
|
141
|
+
return result;
|
|
131
142
|
}
|
|
132
143
|
throw {
|
|
133
144
|
code: "TIMEOUT",
|
|
@@ -163,4 +174,4 @@ function sleep(ms) {
|
|
|
163
174
|
return new Promise((r) => setTimeout(r, ms));
|
|
164
175
|
}
|
|
165
176
|
//#endregion
|
|
166
|
-
export {
|
|
177
|
+
export { revokeRefreshToken as a, refreshToken as i, initiateDeviceAuthorization as n, resolveConfig as o, pollForToken as r, exchangeDeviceCode as t };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
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
6
|
import { defineCommand } from "citty";
|
|
7
7
|
//#region src/commands/kb/doc.ts
|
|
8
8
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
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
6
|
import { defineCommand } from "citty";
|
|
7
7
|
//#region src/commands/kb/doc-content.ts
|
|
8
8
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
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
6
|
import { defineCommand } from "citty";
|
|
7
7
|
//#region src/commands/kb/docs.ts
|
|
8
8
|
/**
|
|
@@ -5,7 +5,7 @@ var focus_default = defineCommand({
|
|
|
5
5
|
name: "focus",
|
|
6
6
|
description: "客户关注点标签分页查询"
|
|
7
7
|
},
|
|
8
|
-
subCommands: { list: () => import("./list-
|
|
8
|
+
subCommands: { list: () => import("./list-D_8QLOZ1.mjs").then((m) => m.default) }
|
|
9
9
|
});
|
|
10
10
|
//#endregion
|
|
11
11
|
export { focus_default as default };
|
|
@@ -6,10 +6,10 @@ var kb_default = defineCommand({
|
|
|
6
6
|
description: "项目知识库:语义检索 / 文档列表 / 文档详情 / 文档正文分页"
|
|
7
7
|
},
|
|
8
8
|
subCommands: {
|
|
9
|
-
search: () => import("./search-
|
|
10
|
-
docs: () => import("./docs-
|
|
11
|
-
doc: () => import("./doc
|
|
12
|
-
"doc-content": () => import("./doc-content-
|
|
9
|
+
search: () => import("./search-ChFFOKV4.mjs").then((m) => m.default),
|
|
10
|
+
docs: () => import("./docs-DtQy3Zoc.mjs").then((m) => m.default),
|
|
11
|
+
doc: () => import("./doc-CC08fj8m.mjs").then((m) => m.default),
|
|
12
|
+
"doc-content": () => import("./doc-content-DktnDECM.mjs").then((m) => m.default)
|
|
13
13
|
}
|
|
14
14
|
});
|
|
15
15
|
//#endregion
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
6
|
-
import { n as mergeUserIds, r as toLocalDateTime, t as csvToArray } from "./util-
|
|
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 { n as mergeUserIds, r as toLocalDateTime, t as csvToArray } from "./util-pyTg7qwY.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/audio/list.ts
|
|
9
9
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
6
|
-
import { r as toLocalDateTime } from "./util-
|
|
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 } from "./util-pyTg7qwY.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/visit/list.ts
|
|
9
9
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
1
|
+
import { o as resolveConfig } from "./device-flow-j10PFOQL.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-D3sCv6L3.mjs";
|
|
3
|
+
import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
//#region src/commands/project/list.ts
|
|
6
6
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
6
|
-
import { r as toLocalDateTime, t as csvToArray } from "./util-
|
|
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-pyTg7qwY.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/focus/list.ts
|
|
9
9
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
6
|
-
import { r as toLocalDateTime, t as csvToArray } from "./util-
|
|
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-pyTg7qwY.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/resistance/list.ts
|
|
9
9
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
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
6
|
import { defineCommand } from "citty";
|
|
7
7
|
//#region src/commands/consultant/list.ts
|
|
8
8
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
6
|
-
import { r as toLocalDateTime } from "./util-
|
|
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 } from "./util-pyTg7qwY.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/customer/list.ts
|
|
9
9
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { a as isAccessTokenValid, c as writePendingAuth, l as writeToken, n as clearPendingAuth, o as readPendingAuth, r as clearToken, s as readToken, t as NoPendingAuthError } from "./token-store-
|
|
3
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
1
|
+
import { i as refreshToken, n as initiateDeviceAuthorization, o as resolveConfig, r as pollForToken } from "./device-flow-j10PFOQL.mjs";
|
|
2
|
+
import { a as isAccessTokenValid, c as writePendingAuth, l as writeToken, n as clearPendingAuth, o as readPendingAuth, r as clearToken, s as readToken, t as NoPendingAuthError } from "./token-store-BB7n-fwJ.mjs";
|
|
3
|
+
import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
//#region src/commands/auth/login.ts
|
|
6
6
|
/**
|
|
@@ -135,6 +135,13 @@ var login_default = defineCommand({
|
|
|
135
135
|
}, fmt);
|
|
136
136
|
return;
|
|
137
137
|
}
|
|
138
|
+
await writePendingAuth({
|
|
139
|
+
device_code: init.device_code,
|
|
140
|
+
user_code: init.user_code,
|
|
141
|
+
verification_uri: verificationUri,
|
|
142
|
+
interval,
|
|
143
|
+
expires_at: Date.now() + init.expires_in * 1e3
|
|
144
|
+
});
|
|
138
145
|
process.stderr.write(`
|
|
139
146
|
请在浏览器中打开以下链接完成登录并授权访问你的旺小宝账号:
|
|
140
147
|
\n 🔗 ${verificationUri}\n\n 设备验证码: ${init.user_code}\n 有效期约 ${expiresMinutes} 分钟\n\n等待你在浏览器中确认 ...
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as
|
|
2
|
-
import { n as clearPendingAuth, r as clearToken, s as readToken } from "./token-store-
|
|
3
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
1
|
+
import { a as revokeRefreshToken, o as resolveConfig } from "./device-flow-j10PFOQL.mjs";
|
|
2
|
+
import { n as clearPendingAuth, r as clearToken, s as readToken } from "./token-store-BB7n-fwJ.mjs";
|
|
3
|
+
import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
//#region src/commands/auth/logout.ts
|
|
6
6
|
/**
|
|
@@ -6,9 +6,9 @@ var project_default = defineCommand({
|
|
|
6
6
|
description: "查询 / 切换激活项目"
|
|
7
7
|
},
|
|
8
8
|
subCommands: {
|
|
9
|
-
list: () => import("./list-
|
|
10
|
-
use: () => import("./use-
|
|
11
|
-
current: () => import("./current-
|
|
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)
|
|
12
12
|
}
|
|
13
13
|
});
|
|
14
14
|
//#endregion
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
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
6
|
import { defineCommand } from "citty";
|
|
7
7
|
//#region src/commands/qa.ts
|
|
8
8
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
6
|
-
import { r as toLocalDateTime, t as csvToArray } from "./util-
|
|
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-pyTg7qwY.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/quantum.ts
|
|
9
9
|
/**
|
|
@@ -5,7 +5,7 @@ var resistance_default = defineCommand({
|
|
|
5
5
|
name: "resistance",
|
|
6
6
|
description: "客户抗性点标签分页查询"
|
|
7
7
|
},
|
|
8
|
-
subCommands: { list: () => import("./list-
|
|
8
|
+
subCommands: { list: () => import("./list-DciEIXpx.mjs").then((m) => m.default) }
|
|
9
9
|
});
|
|
10
10
|
//#endregion
|
|
11
11
|
export { resistance_default as default };
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import { o as resolveConfig } from "./device-flow-j10PFOQL.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-D3sCv6L3.mjs";
|
|
3
|
+
import { t as loadActiveProject } 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 { defineCommand } from "citty";
|
|
7
|
+
//#region src/commands/admin/sales-report.ts
|
|
8
|
+
/**
|
|
9
|
+
* `xiaobao-cli admin sales-report` — 旺小宝公司经营数据(出库 / 回款)。
|
|
10
|
+
*
|
|
11
|
+
* super-admin 能力:按项目组(type 1,默认)或战区(type 2)返回指定日期区间的
|
|
12
|
+
* 出库金额(outStockAmount)与回款/入库金额(receiveAmount)。数据来自内网金蝶
|
|
13
|
+
* 报表,经 ai-open `POST /super-admin/sales-report` 代理;访问由独立白名单控制
|
|
14
|
+
* (空名单 = 全拒),不在名单会收到引导文案。
|
|
15
|
+
*
|
|
16
|
+
* 公司级数据:不要求激活项目(有激活项目则顺带传 tenant headers)。
|
|
17
|
+
*/
|
|
18
|
+
var sales_report_default = defineCommand({
|
|
19
|
+
meta: {
|
|
20
|
+
name: "sales-report",
|
|
21
|
+
description: "公司经营数据:出库/回款金额,按 项目组(project) 或 战区(zone) 分组(独立白名单)"
|
|
22
|
+
},
|
|
23
|
+
args: {
|
|
24
|
+
from: {
|
|
25
|
+
type: "string",
|
|
26
|
+
required: true,
|
|
27
|
+
description: "开始日期 yyyy-MM-dd(闭区间)"
|
|
28
|
+
},
|
|
29
|
+
to: {
|
|
30
|
+
type: "string",
|
|
31
|
+
required: true,
|
|
32
|
+
description: "结束日期 yyyy-MM-dd(闭区间)"
|
|
33
|
+
},
|
|
34
|
+
by: {
|
|
35
|
+
type: "string",
|
|
36
|
+
default: "project",
|
|
37
|
+
description: "分组维度:project=项目组(type 1,默认) / zone=战区(type 2)"
|
|
38
|
+
},
|
|
39
|
+
"api-base": { type: "string" },
|
|
40
|
+
"auth-base": { type: "string" },
|
|
41
|
+
format: {
|
|
42
|
+
type: "string",
|
|
43
|
+
default: "toon"
|
|
44
|
+
}
|
|
45
|
+
},
|
|
46
|
+
async run({ args }) {
|
|
47
|
+
try {
|
|
48
|
+
const config = resolveConfig({
|
|
49
|
+
apiBase: args["api-base"],
|
|
50
|
+
authBase: args["auth-base"]
|
|
51
|
+
});
|
|
52
|
+
const by = String(args.by);
|
|
53
|
+
if (by !== "project" && by !== "zone") throw new Error(`--by 仅支持 project 或 zone,收到: ${by}`);
|
|
54
|
+
const active = await loadActiveProject();
|
|
55
|
+
writeResult(await xbApiFetch(config, "POST", "/ai-open/super-admin/sales-report", {
|
|
56
|
+
headers: active ? tenantProjectHeaders(active) : void 0,
|
|
57
|
+
body: {
|
|
58
|
+
startDate: args.from,
|
|
59
|
+
endDate: args.to,
|
|
60
|
+
type: by === "zone" ? 2 : 1
|
|
61
|
+
}
|
|
62
|
+
}), args.format);
|
|
63
|
+
} catch (err) {
|
|
64
|
+
writeError(err, args.format);
|
|
65
|
+
process.exit(1);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
});
|
|
69
|
+
//#endregion
|
|
70
|
+
export { sales_report_default as default };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
6
|
-
import { t as csvToArray } from "./util-
|
|
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 { t as csvToArray } from "./util-pyTg7qwY.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/kb/search.ts
|
|
9
9
|
/**
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { i as refreshToken, o as resolveConfig, t as exchangeDeviceCode } from "./device-flow-j10PFOQL.mjs";
|
|
2
|
+
import { a as isAccessTokenValid, i as decodeJwtPayload, l as writeToken, n as clearPendingAuth, o as readPendingAuth, r as clearToken, s as readToken } from "./token-store-BB7n-fwJ.mjs";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
//#region src/commands/auth/status.ts
|
|
5
|
+
/**
|
|
6
|
+
* `xiaobao-cli auth status` — host-friendly auth check (WorkBuddy cli.json
|
|
7
|
+
* `status` command; also handy for scripts).
|
|
8
|
+
*
|
|
9
|
+
* Contract (WorkBuddy Connector spec §12.4): exit 0 + "Logged in as ..." on
|
|
10
|
+
* stdout when authenticated, non-zero otherwise; must return within seconds
|
|
11
|
+
* and be safe to poll every 3s.
|
|
12
|
+
*
|
|
13
|
+
* If a device authorization is pending (`auth login` was started and the host
|
|
14
|
+
* killed it after reading the URL), one token-endpoint attempt finishes the
|
|
15
|
+
* exchange here — this is what lets WorkBuddy's "kill auth, poll status"
|
|
16
|
+
* flow complete without the auth process staying alive.
|
|
17
|
+
*/
|
|
18
|
+
function loggedIn(token) {
|
|
19
|
+
const c = decodeJwtPayload(token.id_token) ?? {};
|
|
20
|
+
const who = c.name ?? c.preferred_username ?? c.sub ?? "unknown";
|
|
21
|
+
process.stdout.write(`Logged in as ${String(who)}\n`);
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
function notLoggedIn(reason) {
|
|
25
|
+
process.stdout.write(`Not authenticated: ${reason}\n`);
|
|
26
|
+
process.exit(1);
|
|
27
|
+
}
|
|
28
|
+
var status_default = defineCommand({
|
|
29
|
+
meta: {
|
|
30
|
+
name: "status",
|
|
31
|
+
description: "认证状态检测(exit 0 = 已登录;可完成待授权的 device flow)"
|
|
32
|
+
},
|
|
33
|
+
args: { "auth-base": {
|
|
34
|
+
type: "string",
|
|
35
|
+
description: "覆盖 auth base URL"
|
|
36
|
+
} },
|
|
37
|
+
async run({ args }) {
|
|
38
|
+
const config = resolveConfig({ authBase: args["auth-base"] });
|
|
39
|
+
const cached = await readToken();
|
|
40
|
+
if (isAccessTokenValid(cached)) loggedIn(cached);
|
|
41
|
+
if (cached?.refresh_token) try {
|
|
42
|
+
loggedIn(await writeToken(await refreshToken(config, cached.refresh_token)));
|
|
43
|
+
} catch {
|
|
44
|
+
await clearToken();
|
|
45
|
+
}
|
|
46
|
+
const pending = await readPendingAuth();
|
|
47
|
+
if (!pending) notLoggedIn("run `xiaobao-cli auth login`");
|
|
48
|
+
if (pending.expires_at <= Date.now()) {
|
|
49
|
+
await clearPendingAuth();
|
|
50
|
+
notLoggedIn("device authorization expired, run `xiaobao-cli auth login` again");
|
|
51
|
+
}
|
|
52
|
+
try {
|
|
53
|
+
const result = await exchangeDeviceCode(config, pending.device_code);
|
|
54
|
+
if (result === "pending" || result === "slow_down") notLoggedIn("awaiting authorization in browser");
|
|
55
|
+
const saved = await writeToken(result);
|
|
56
|
+
await clearPendingAuth();
|
|
57
|
+
loggedIn(saved);
|
|
58
|
+
} catch (err) {
|
|
59
|
+
await clearPendingAuth();
|
|
60
|
+
notLoggedIn(`device authorization failed (${err?.code ?? "error"}), run \`xiaobao-cli auth login\` again`);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
//#endregion
|
|
65
|
+
export { status_default as default };
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
6
|
-
import { r as toLocalDateTime } from "./util-
|
|
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 } from "./util-pyTg7qwY.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/visit/summary.ts
|
|
9
9
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as requireActiveProject } from "./project-store-
|
|
4
|
-
import { t as tenantProjectHeaders } from "./headers-
|
|
5
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
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
6
|
import { defineCommand } from "citty";
|
|
7
7
|
//#region src/commands/audio/text.ts
|
|
8
8
|
/**
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
import { o as resolveConfig } from "./device-flow-j10PFOQL.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-D3sCv6L3.mjs";
|
|
3
|
+
import { t as loadActiveProject } 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 { defineCommand } from "citty";
|
|
7
|
+
//#region src/commands/admin/token-usage.ts
|
|
8
|
+
/**
|
|
9
|
+
* `xiaobao-cli admin token-usage` — 旺小宝 LLM token 用量汇总。
|
|
10
|
+
*
|
|
11
|
+
* super-admin 能力:返回指定日期区间(闭区间)的输入 / 输出 / 总量 tokens,可按
|
|
12
|
+
* 模型、供应商、API Key、接入点、标签、状态过滤。数据来自内网 AI Portal,经
|
|
13
|
+
* ai-open `POST /super-admin/token-usage` 代理;访问由独立白名单控制(空名单 =
|
|
14
|
+
* 全拒),不在名单会收到引导文案。
|
|
15
|
+
*
|
|
16
|
+
* 公司级数据:不要求激活项目(有激活项目则顺带传 tenant headers)。
|
|
17
|
+
*/
|
|
18
|
+
var token_usage_default = defineCommand({
|
|
19
|
+
meta: {
|
|
20
|
+
name: "token-usage",
|
|
21
|
+
description: "LLM token 用量:输入/输出/总量,可按模型/供应商/Key 过滤(独立白名单)"
|
|
22
|
+
},
|
|
23
|
+
args: {
|
|
24
|
+
from: {
|
|
25
|
+
type: "string",
|
|
26
|
+
required: true,
|
|
27
|
+
description: "开始日期 yyyy-MM-dd(闭区间)"
|
|
28
|
+
},
|
|
29
|
+
to: {
|
|
30
|
+
type: "string",
|
|
31
|
+
required: true,
|
|
32
|
+
description: "结束日期 yyyy-MM-dd(闭区间)"
|
|
33
|
+
},
|
|
34
|
+
model: {
|
|
35
|
+
type: "string",
|
|
36
|
+
description: "模型过滤,如 gpt-4.1-mini"
|
|
37
|
+
},
|
|
38
|
+
provider: {
|
|
39
|
+
type: "string",
|
|
40
|
+
description: "供应商过滤,如 openai"
|
|
41
|
+
},
|
|
42
|
+
upstream: {
|
|
43
|
+
type: "string",
|
|
44
|
+
description: "上游过滤"
|
|
45
|
+
},
|
|
46
|
+
"api-key": {
|
|
47
|
+
type: "string",
|
|
48
|
+
description: "API Key 过滤"
|
|
49
|
+
},
|
|
50
|
+
endpoint: {
|
|
51
|
+
type: "string",
|
|
52
|
+
description: "接入点过滤"
|
|
53
|
+
},
|
|
54
|
+
"tag-key": {
|
|
55
|
+
type: "string",
|
|
56
|
+
description: "标签 key"
|
|
57
|
+
},
|
|
58
|
+
"tag-value": {
|
|
59
|
+
type: "string",
|
|
60
|
+
description: "标签 value"
|
|
61
|
+
},
|
|
62
|
+
status: {
|
|
63
|
+
type: "string",
|
|
64
|
+
description: "状态过滤,如 error(只看失败请求)"
|
|
65
|
+
},
|
|
66
|
+
"api-base": { type: "string" },
|
|
67
|
+
"auth-base": { type: "string" },
|
|
68
|
+
format: {
|
|
69
|
+
type: "string",
|
|
70
|
+
default: "toon"
|
|
71
|
+
}
|
|
72
|
+
},
|
|
73
|
+
async run({ args }) {
|
|
74
|
+
try {
|
|
75
|
+
const config = resolveConfig({
|
|
76
|
+
apiBase: args["api-base"],
|
|
77
|
+
authBase: args["auth-base"]
|
|
78
|
+
});
|
|
79
|
+
const active = await loadActiveProject();
|
|
80
|
+
writeResult(await xbApiFetch(config, "POST", "/ai-open/super-admin/token-usage", {
|
|
81
|
+
headers: active ? tenantProjectHeaders(active) : void 0,
|
|
82
|
+
body: {
|
|
83
|
+
startDate: args.from,
|
|
84
|
+
endDate: args.to,
|
|
85
|
+
model: args.model,
|
|
86
|
+
provider: args.provider,
|
|
87
|
+
upstream: args.upstream,
|
|
88
|
+
apiKey: args["api-key"],
|
|
89
|
+
endpoint: args.endpoint,
|
|
90
|
+
tagKey: args["tag-key"],
|
|
91
|
+
tagValue: args["tag-value"],
|
|
92
|
+
status: args.status
|
|
93
|
+
}
|
|
94
|
+
}), args.format);
|
|
95
|
+
} catch (err) {
|
|
96
|
+
writeError(err, args.format);
|
|
97
|
+
process.exit(1);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
});
|
|
101
|
+
//#endregion
|
|
102
|
+
export { token_usage_default as default };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as saveActiveProject } from "./project-store-
|
|
2
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
1
|
+
import { r as saveActiveProject } from "./project-store-CudTRvbA.mjs";
|
|
2
|
+
import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
//#region src/commands/project/use.ts
|
|
5
5
|
/**
|
|
@@ -6,8 +6,8 @@ var visit_default = defineCommand({
|
|
|
6
6
|
description: "客户来访分页查询 / 来访接待总结"
|
|
7
7
|
},
|
|
8
8
|
subCommands: {
|
|
9
|
-
list: () => import("./list-
|
|
10
|
-
summary: () => import("./summary-
|
|
9
|
+
list: () => import("./list-Ca5Fvq_e.mjs").then((m) => m.default),
|
|
10
|
+
summary: () => import("./summary-C3poiB2C.mjs").then((m) => m.default)
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
13
|
//#endregion
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { i as decodeJwtPayload, s as readToken } from "./token-store-
|
|
2
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
1
|
+
import { i as decodeJwtPayload, s as readToken } from "./token-store-BB7n-fwJ.mjs";
|
|
2
|
+
import { n as writeResult, t as writeError } from "./format-DfVypHID.mjs";
|
|
3
3
|
import { defineCommand } from "citty";
|
|
4
4
|
//#region src/commands/auth/whoami.ts
|
|
5
5
|
/**
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@puyinkai/xiaobao-cli",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"description": "旺小宝 CLI — host-agnostic 业务数据 / 问数 / 来访总结 / 知识库 能力 (openclaw-xiaobao plugin 的 CLI 等价物)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -23,7 +23,8 @@
|
|
|
23
23
|
"scripts": {
|
|
24
24
|
"build": "tsdown",
|
|
25
25
|
"typecheck": "tsc --noEmit",
|
|
26
|
-
"dev": "node --import tsx src/cli.ts"
|
|
26
|
+
"dev": "node --import tsx src/cli.ts",
|
|
27
|
+
"workbuddy:pack": "rm -rf dist-workbuddy && mkdir -p dist-workbuddy/wangxiaobao && cp workbuddy/connector-meta.json workbuddy/cli.json workbuddy/icon.svg dist-workbuddy/wangxiaobao/ && cp -R skills dist-workbuddy/wangxiaobao/skills && cd dist-workbuddy && zip -qr wangxiaobao-connector.zip wangxiaobao && echo dist-workbuddy/wangxiaobao-connector.zip"
|
|
27
28
|
},
|
|
28
29
|
"dependencies": {
|
|
29
30
|
"citty": "^0.1.6"
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wangxiaobao-admin-sales-report
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
description: "旺小宝公司经营数据查询(super-admin,独立白名单):按日期区间返回 出库金额(outStockAmount) 与 回款/入库金额(receiveAmount),按 项目组(--by project,默认) 或 战区(--by zone) 分组。只读。高频命令: xiaobao-cli admin sales-report --from <yyyy-MM-dd> --to <yyyy-MM-dd> [--by project|zone]。何时用:用户问 公司业绩/经营数据/出库/回款/入库金额/各项目组业绩/各战区业绩/业绩排名/某月做了多少。注:独立白名单控制(与其它命令的白名单无关),返回引导文案时原样告知用户并停止;不需要激活项目;两个维度出库合计存在口径差,汇报须注明口径。"
|
|
5
|
+
metadata:
|
|
6
|
+
requires:
|
|
7
|
+
bins: ["xiaobao-cli"]
|
|
8
|
+
cliHelp: "xiaobao-cli admin sales-report --help"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# 旺小宝公司经营数据(出库 / 回款)
|
|
12
|
+
|
|
13
|
+
> **CRITICAL** —— 跑命令前 MUST 先用 Read tool 读取 [`../wangxiaobao-shared/SKILL.md`](../wangxiaobao-shared/SKILL.md)(登录 / 输出协议 / 错误码 等通用约定)。
|
|
14
|
+
|
|
15
|
+
`xiaobao-cli admin sales-report` 查询公司级经营数据(数据源:内网金蝶报表,经 ai-open 代理)。
|
|
16
|
+
|
|
17
|
+
## 执行前必读
|
|
18
|
+
- **super-admin 能力,独立白名单**:与其它命令的白名单**互相独立**,且**名单为空 = 全拒**。若返回 `data: "不在白名单中,若有需求请联系19136123281"`,**原样告知用户并停止,不要重试**。
|
|
19
|
+
- 需要登录(token),**不需要激活项目**。
|
|
20
|
+
- 日期为**闭区间**(`--from 2026-07-01 --to 2026-07-31` 含首尾两天),格式 `yyyy-MM-dd`。
|
|
21
|
+
- 只读,不写文件。
|
|
22
|
+
|
|
23
|
+
## 快速索引
|
|
24
|
+
| 用户意图 | 命令 |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| 某月各项目组业绩 | `admin sales-report --from 2026-07-01 --to 2026-07-31`(默认 --by project) |
|
|
27
|
+
| 某月各战区业绩 | `admin sales-report --from ... --to ... --by zone` |
|
|
28
|
+
| 两个维度都要 | 调两次(--by project + --by zone),并注意口径差(见下) |
|
|
29
|
+
| 时间说法(本月/上月/最近 7 天) | 换算成 from/to 再调 |
|
|
30
|
+
|
|
31
|
+
## 核心约束与坑(来自实测)
|
|
32
|
+
1. **出库 vs 回款口径**:`outStockAmount` = 出库,`receiveAmount` = 回款(入库)。
|
|
33
|
+
2. **两个维度合计对不上是数据源特性不是 bug**:入库合计两维度一致,但**出库合计恒是项目组 > 战区**(每月差 0.4~3.6 万,部分出库单归得到项目组归不到战区)。**汇报公司总业绩必须注明口径**(建议用项目组口径)。
|
|
34
|
+
3. **负数是正常的**:出库可为负(退货/红字冲销),如实呈现,不要过滤。
|
|
35
|
+
4. **返回 0 不等于失败**:未来区间、无业务区间正常返回 0;先确认区间合理再下结论。
|
|
36
|
+
5. **日期写反**:ai-open 已拦截(返回 400 "startDate 不能晚于 endDate"),不会再静默返回全 0。
|
|
37
|
+
|
|
38
|
+
## 响应字段
|
|
39
|
+
```jsonc
|
|
40
|
+
{ "code": "0", "data": {
|
|
41
|
+
"totalReceiveAmount": 7546423.51, // 回款(入库)合计
|
|
42
|
+
"totalOutStockAmount": 7809705.90, // 出库合计
|
|
43
|
+
"data": [ // 按出库金额降序(接口原序)
|
|
44
|
+
{ "name": "人脸识别项目组",
|
|
45
|
+
"values": { "receiveAmount": 4102679.69, "outStockAmount": 4176741.33 } }
|
|
46
|
+
] } }
|
|
47
|
+
```
|
|
48
|
+
CLI 再包一层 → 读 `resp.data.data.*`。展示时给出 名称 / 回款 / 出库 / 出库占比,负数保留。
|
|
49
|
+
|
|
50
|
+
## 常见错误
|
|
51
|
+
- **`data` 是"不在白名单中…"文案** → 原样转告用户,停止(联系 19136123281 开通)。
|
|
52
|
+
- **401** → `auth login --no-wait --force` 重登。
|
|
53
|
+
- **400 日期问题** → 检查 yyyy-MM-dd 格式与 from<=to。
|
|
54
|
+
- **全 0** → 先确认区间是否合理(未来区间/无业务),不要报"接口挂了"。
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: wangxiaobao-admin-token-usage
|
|
3
|
+
version: 0.1.0
|
|
4
|
+
description: "旺小宝 LLM token 用量查询(super-admin,独立白名单):按日期区间返回 输入(promptTokens)/输出(completionTokens)/总量(totalTokens) tokens,可按 模型/供应商/API Key/接入点/标签/状态 过滤。只读。高频命令: xiaobao-cli admin token-usage --from <yyyy-MM-dd> --to <yyyy-MM-dd> [--model <m>] [--provider <p>]。何时用:用户问 token 用量/token 消耗/用了多少 token/AI 用量统计/某模型或某供应商的用量/成本核算输入数据。注:独立白名单控制,返回引导文案时原样告知并停止;不需要激活项目;数据从 2026-04 起;日期闭区间;按月对比=逐月调多次。"
|
|
5
|
+
metadata:
|
|
6
|
+
requires:
|
|
7
|
+
bins: ["xiaobao-cli"]
|
|
8
|
+
cliHelp: "xiaobao-cli admin token-usage --help"
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# 旺小宝 LLM Token 用量
|
|
12
|
+
|
|
13
|
+
> **CRITICAL** —— 跑命令前 MUST 先用 Read tool 读取 [`../wangxiaobao-shared/SKILL.md`](../wangxiaobao-shared/SKILL.md)(登录 / 输出协议 / 错误码 等通用约定)。
|
|
14
|
+
|
|
15
|
+
`xiaobao-cli admin token-usage` 查询公司级 LLM token 用量(数据源:内网 AI Portal,经 ai-open 代理)。
|
|
16
|
+
|
|
17
|
+
## 执行前必读
|
|
18
|
+
- **super-admin 能力,独立白名单**:与其它命令的白名单**互相独立**,且**名单为空 = 全拒**。若返回 `data: "不在白名单中,若有需求请联系19136123281"`,**原样告知用户并停止,不要重试**。
|
|
19
|
+
- 需要登录(token),**不需要激活项目**。
|
|
20
|
+
- 日期为**闭区间**,格式 `yyyy-MM-dd`。
|
|
21
|
+
- 只读,不写文件。
|
|
22
|
+
|
|
23
|
+
## 快速索引
|
|
24
|
+
| 用户意图 | 命令 |
|
|
25
|
+
| --- | --- |
|
|
26
|
+
| 某月总用量 | `admin token-usage --from 2026-07-01 --to 2026-07-31` |
|
|
27
|
+
| 只看某模型 / 供应商 | `--model gpt-4.1-mini` / `--provider openai` |
|
|
28
|
+
| 只看某 Key / 接入点 | `--api-key <KEY>` / `--endpoint <EP>` |
|
|
29
|
+
| 按标签 | `--tag-key team --tag-value ai` |
|
|
30
|
+
| 只看失败请求 | `--status error` |
|
|
31
|
+
| 按月对比 | 逐月调多次(每月一个 from/to),自己汇总 |
|
|
32
|
+
|
|
33
|
+
## 核心约束与坑(来自实测)
|
|
34
|
+
1. **数据从 2026-04 开始**:更早区间一律返回 0——那是没数据,不是查询出错。
|
|
35
|
+
2. **闭区间**:`--from 2026-07-01 --to 2026-07-31` 含首尾两天。
|
|
36
|
+
3. **当天数据仍在增长**:含今天的区间两次调用结果会有差异;做对账用截至昨天的区间。
|
|
37
|
+
4. **接口返回整区间汇总,无分页**:要按月/按天拆分就按段多次调用(按天拆一年 = 300+ 次,不要这么干,按月拆)。
|
|
38
|
+
5. 筛选条件可任意组合。
|
|
39
|
+
|
|
40
|
+
## 响应字段
|
|
41
|
+
```jsonc
|
|
42
|
+
{ "code": "0", "data": {
|
|
43
|
+
"promptTokens": 296215003449, // 输入
|
|
44
|
+
"completionTokens": 34882240321, // 输出
|
|
45
|
+
"totalTokens": 331097243770 } } // 总量
|
|
46
|
+
```
|
|
47
|
+
CLI 再包一层 → 读 `resp.data.data.*`。大数字建议换算(如 331.10 B)展示。
|
|
48
|
+
|
|
49
|
+
## 常见错误
|
|
50
|
+
- **`data` 是"不在白名单中…"文案** → 原样转告用户,停止(联系 19136123281 开通)。
|
|
51
|
+
- **401** → `auth login --no-wait --force` 重登。
|
|
52
|
+
- **查 2026-04 之前区间得 0** → 说明"无数据",不要说成"没用量/接口挂了"。
|
|
53
|
+
- **含今天的区间数字对不上** → 正常,当天数据在涨;对账用截至昨天。
|
|
@@ -169,6 +169,11 @@ openclaw 的副本(保留 plugin session 完整性)。`auth logout` 例外
|
|
|
169
169
|
返回该项目知识,不按顾问授权范围细分;`kb doc` / `kb doc-content` 按 docId 直取。
|
|
170
170
|
知识库面向全项目,不存在"看不到别人名下"的概念。
|
|
171
171
|
|
|
172
|
+
**例外 —— `admin *`(super-admin 经营报表)**:`admin sales-report` / `admin token-usage`
|
|
173
|
+
是**公司级**数据(经营出库/回款、LLM token 用量),**不需要激活项目**,且走**独立白名单**
|
|
174
|
+
(与上面按顾问授权的隔离无关;名单为空 = 全拒)。不在名单会收到
|
|
175
|
+
`data: "不在白名单中,若有需求请联系19136123281"` —— 原样转告用户并停止,不要重试。
|
|
176
|
+
|
|
172
177
|
> 后端链路:上述命令统一经 `ai-open`(公网开放层 / 鉴权)代理到内网业务层
|
|
173
178
|
> `wang-ai-mcp`,对调用方透明,命令用法不变。
|
|
174
179
|
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|