@puyinkai/xiaobao-cli 0.1.0 → 0.1.8
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{api-Ccj5dLMo.mjs → api-CX99_4K7.mjs} +22 -5
- package/dist/{api-client-DwySN6x-.mjs → api-client-zDBFgk0y.mjs} +5 -3
- package/dist/{audio-VmDQMq59.mjs → audio-ShfvRomP.mjs} +2 -2
- package/dist/{auth-ChHvqjCS.mjs → auth-DpK81Vp5.mjs} +3 -3
- package/dist/cli.mjs +15 -11
- package/dist/{consultant-ABFTL_jx.mjs → consultant-CS9B42d3.mjs} +1 -1
- package/dist/current-CfDExInT.mjs +33 -0
- package/dist/{customer-DtSnQqy_.mjs → customer-B1cxRbJ9.mjs} +1 -1
- package/dist/{focus-BDYuP2vZ.mjs → focus-DfNPPhm5.mjs} +1 -1
- package/dist/{format-BZvv8lYc.mjs → format-yjmxrbNm.mjs} +15 -7
- package/dist/{list-Bkyi95YO.mjs → list-CD08BRLk.mjs} +6 -6
- package/dist/{list-CzB9_Jho.mjs → list-CKlx8YuL.mjs} +6 -6
- package/dist/{list-DW6KAAaC.mjs → list-CnlFIFiY.mjs} +6 -6
- package/dist/{list-iwd9cH1I.mjs → list-Cu6WzPpA.mjs} +5 -5
- package/dist/{list-CVKSGNu4.mjs → list-D56gEqiB.mjs} +6 -6
- package/dist/{list--o5Q_PI8.mjs → list-DCcCS6LM.mjs} +6 -6
- package/dist/{list-CGACp0y-.mjs → list-DI1OD95x.mjs} +3 -3
- package/dist/login-CUUcjWPd.mjs +156 -0
- package/dist/{logout-BJm9pjje.mjs → logout-DP7REhCd.mjs} +10 -7
- package/dist/{project-Ba05YzJ5.mjs → project-BuQQewOs.mjs} +3 -2
- package/dist/{project-store-Bz5kf-EI.mjs → project-store-CKVJa54T.mjs} +4 -3
- package/dist/{qa-D-B9FV9W.mjs → qa-CKsKiQIm.mjs} +5 -5
- package/dist/{resistance-Cf7zsdB3.mjs → resistance-DsE-Ha6Y.mjs} +1 -1
- package/dist/{text-BLH4R3xv.mjs → text-C3jhdPoe.mjs} +5 -5
- package/dist/{token-store-CHZ_rJQk.mjs → token-store-CXizLE2_.mjs} +46 -6
- package/dist/{use-DV9Ii3Tn.mjs → use-BZES4FZC.mjs} +2 -2
- package/dist/{visit-Ct3Vea8I.mjs → visit-CX0Mc1n6.mjs} +1 -1
- package/dist/{whoami-DwTHvI4B.mjs → whoami-CZVez-rm.mjs} +2 -2
- package/package.json +2 -2
- package/skills/wangxiaobao-audio-query/SKILL.md +51 -106
- package/skills/wangxiaobao-audio-wiki/SKILL.md +31 -77
- package/skills/wangxiaobao-audio-wiki/references/audio-wiki-schema.md +386 -0
- package/skills/wangxiaobao-audio-wiki/references/llm-wiki-ingest.md +450 -0
- package/skills/wangxiaobao-customer-focus-query/SKILL.md +37 -87
- package/skills/wangxiaobao-customer-query/SKILL.md +41 -90
- package/skills/wangxiaobao-customer-resistance-query/SKILL.md +32 -86
- package/skills/wangxiaobao-quick-qa/SKILL.md +41 -92
- package/skills/wangxiaobao-shared/SKILL.md +194 -0
- package/skills/wangxiaobao-switch-project/SKILL.md +51 -77
- package/skills/wangxiaobao-visit-query/SKILL.md +41 -88
- package/dist/login-BwkrByMm.mjs +0 -91
- package/dist/{device-flow-BgsZipYA.mjs → device-flow-D6JVcEap.mjs} +1 -1
- /package/dist/{headers-D79npewp.mjs → headers-DSnR4sjk.mjs} +0 -0
- /package/dist/{util-DgwkUfV9.mjs → util-CaPQBlNa.mjs} +0 -0
|
@@ -1,6 +1,8 @@
|
|
|
1
|
-
import { a as resolveConfig } from "./device-flow-
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import {
|
|
1
|
+
import { a as resolveConfig } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-zDBFgk0y.mjs";
|
|
3
|
+
import { t as loadActiveProject } from "./project-store-CKVJa54T.mjs";
|
|
4
|
+
import { t as tenantProjectHeaders } from "./headers-DSnR4sjk.mjs";
|
|
5
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
4
6
|
import { defineCommand } from "citty";
|
|
5
7
|
//#region src/commands/api.ts
|
|
6
8
|
/**
|
|
@@ -56,7 +58,12 @@ var api_default = defineCommand({
|
|
|
56
58
|
},
|
|
57
59
|
headers: {
|
|
58
60
|
type: "string",
|
|
59
|
-
description: "自定义 headers,`K1=V1&K2=V2` 或 `K=V,K=V
|
|
61
|
+
description: "自定义 headers,`K1=V1&K2=V2` 或 `K=V,K=V`。与默认注入的 tenant/project headers 合并(同名 key 用户传入优先)"
|
|
62
|
+
},
|
|
63
|
+
"default-headers": {
|
|
64
|
+
type: "boolean",
|
|
65
|
+
default: true,
|
|
66
|
+
description: "默认按当前激活项目自动注入 X-Tenant-Id / X-Project-Id headers(调 /ai-open/* 开箱即用);`--no-default-headers` 关闭注入"
|
|
60
67
|
},
|
|
61
68
|
"api-base": { type: "string" },
|
|
62
69
|
"auth-base": { type: "string" },
|
|
@@ -85,10 +92,20 @@ var api_default = defineCommand({
|
|
|
85
92
|
} catch {
|
|
86
93
|
body = args.body;
|
|
87
94
|
}
|
|
95
|
+
let mergedHeaders;
|
|
96
|
+
const userHeaders = parseKV(args.headers);
|
|
97
|
+
if (args["default-headers"]) {
|
|
98
|
+
const active = await loadActiveProject();
|
|
99
|
+
if (active) mergedHeaders = {
|
|
100
|
+
...tenantProjectHeaders(active),
|
|
101
|
+
...userHeaders ?? {}
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
mergedHeaders = mergedHeaders ?? userHeaders;
|
|
88
105
|
writeResult(await xbApiFetch(config, method, String(args.path), {
|
|
89
106
|
query: parseKV(args.query),
|
|
90
107
|
body,
|
|
91
|
-
headers:
|
|
108
|
+
headers: mergedHeaders
|
|
92
109
|
}), args.format);
|
|
93
110
|
} catch (err) {
|
|
94
111
|
writeError(err, args.format);
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { r as refreshToken } from "./device-flow-
|
|
2
|
-
import { a as
|
|
1
|
+
import { r as refreshToken } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { a as isAccessTokenValid, l as writeToken, s as readToken } from "./token-store-CXizLE2_.mjs";
|
|
3
3
|
//#region src/core/api-client.ts
|
|
4
4
|
/**
|
|
5
5
|
* HTTP client for wangxiaobao open API endpoints.
|
|
@@ -13,8 +13,10 @@ import { a as writeToken, i as readToken, r as isAccessTokenValid } from "./toke
|
|
|
13
13
|
*/
|
|
14
14
|
var NotAuthenticatedError = class extends Error {
|
|
15
15
|
code = "NOT_AUTHENTICATED";
|
|
16
|
+
hint = "运行 `xiaobao-cli auth login` 完成 OAuth device flow 登录。";
|
|
16
17
|
constructor() {
|
|
17
|
-
super("
|
|
18
|
+
super("当前未登录或 token 已过期");
|
|
19
|
+
this.name = "NotAuthenticatedError";
|
|
18
20
|
}
|
|
19
21
|
};
|
|
20
22
|
async function ensureAccessToken(config) {
|
|
@@ -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-DCcCS6LM.mjs").then((m) => m.default),
|
|
10
|
+
text: () => import("./text-C3jhdPoe.mjs").then((m) => m.default)
|
|
11
11
|
}
|
|
12
12
|
});
|
|
13
13
|
//#endregion
|
|
@@ -6,9 +6,9 @@ var auth_default = defineCommand({
|
|
|
6
6
|
description: "OAuth 登录 / 身份查询 / 登出(device flow)"
|
|
7
7
|
},
|
|
8
8
|
subCommands: {
|
|
9
|
-
login: () => import("./login-
|
|
10
|
-
whoami: () => import("./whoami-
|
|
11
|
-
logout: () => import("./logout-
|
|
9
|
+
login: () => import("./login-CUUcjWPd.mjs").then((m) => m.default),
|
|
10
|
+
whoami: () => import("./whoami-CZVez-rm.mjs").then((m) => m.default),
|
|
11
|
+
logout: () => import("./logout-DP7REhCd.mjs").then((m) => m.default)
|
|
12
12
|
}
|
|
13
13
|
});
|
|
14
14
|
//#endregion
|
package/dist/cli.mjs
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
+
import { readFileSync } from "node:fs";
|
|
3
|
+
import { dirname, join } from "node:path";
|
|
4
|
+
import { fileURLToPath } from "node:url";
|
|
2
5
|
import { defineCommand, runMain } from "citty";
|
|
3
6
|
//#region src/cli.ts
|
|
4
7
|
/**
|
|
@@ -7,23 +10,24 @@ import { defineCommand, runMain } from "citty";
|
|
|
7
10
|
* 14 capabilities mapped 1:1 from openclaw-xiaobao plugin tools to CLI
|
|
8
11
|
* subcommands. See README for full command map.
|
|
9
12
|
*/
|
|
13
|
+
const pkgPath = join(dirname(fileURLToPath(import.meta.url)), "..", "package.json");
|
|
10
14
|
runMain(defineCommand({
|
|
11
15
|
meta: {
|
|
12
16
|
name: "xiaobao-cli",
|
|
13
|
-
version: "
|
|
17
|
+
version: JSON.parse(readFileSync(pkgPath, "utf8")).version,
|
|
14
18
|
description: "旺小宝 CLI — host-agnostic 14 tools (openclaw-xiaobao plugin 的 CLI 等价物)"
|
|
15
19
|
},
|
|
16
20
|
subCommands: {
|
|
17
|
-
auth: () => import("./auth-
|
|
18
|
-
project: () => import("./project-
|
|
19
|
-
consultant: () => import("./consultant-
|
|
20
|
-
audio: () => import("./audio-
|
|
21
|
-
customer: () => import("./customer-
|
|
22
|
-
visit: () => import("./visit-
|
|
23
|
-
focus: () => import("./focus-
|
|
24
|
-
resistance: () => import("./resistance-
|
|
25
|
-
qa: () => import("./qa-
|
|
26
|
-
api: () => import("./api-
|
|
21
|
+
auth: () => import("./auth-DpK81Vp5.mjs").then((m) => m.default),
|
|
22
|
+
project: () => import("./project-BuQQewOs.mjs").then((m) => m.default),
|
|
23
|
+
consultant: () => import("./consultant-CS9B42d3.mjs").then((m) => m.default),
|
|
24
|
+
audio: () => import("./audio-ShfvRomP.mjs").then((m) => m.default),
|
|
25
|
+
customer: () => import("./customer-B1cxRbJ9.mjs").then((m) => m.default),
|
|
26
|
+
visit: () => import("./visit-CX0Mc1n6.mjs").then((m) => m.default),
|
|
27
|
+
focus: () => import("./focus-DfNPPhm5.mjs").then((m) => m.default),
|
|
28
|
+
resistance: () => import("./resistance-DsE-Ha6Y.mjs").then((m) => m.default),
|
|
29
|
+
qa: () => import("./qa-CKsKiQIm.mjs").then((m) => m.default),
|
|
30
|
+
api: () => import("./api-CX99_4K7.mjs").then((m) => m.default)
|
|
27
31
|
}
|
|
28
32
|
}));
|
|
29
33
|
//#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-Cu6WzPpA.mjs").then((m) => m.default) }
|
|
9
9
|
});
|
|
10
10
|
//#endregion
|
|
11
11
|
export { consultant_default as default };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { n as requireActiveProject } from "./project-store-CKVJa54T.mjs";
|
|
2
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
3
|
+
import { defineCommand } from "citty";
|
|
4
|
+
//#region src/commands/project/current.ts
|
|
5
|
+
/**
|
|
6
|
+
* `xiaobao-cli project current` — show the currently active project.
|
|
7
|
+
*
|
|
8
|
+
* Reads ~/.xiaobao/active-project.json (or fallback
|
|
9
|
+
* ~/.openclaw/state/wangxiaobao/active-project.json) and prints the
|
|
10
|
+
* tenant/project record. If none is set, errors out with NO_ACTIVE_PROJECT
|
|
11
|
+
* + hint (same error shape as other commands that need an active project,
|
|
12
|
+
* so agents handle it uniformly).
|
|
13
|
+
*/
|
|
14
|
+
var current_default = defineCommand({
|
|
15
|
+
meta: {
|
|
16
|
+
name: "current",
|
|
17
|
+
description: "显示当前激活的租户/项目"
|
|
18
|
+
},
|
|
19
|
+
args: { format: {
|
|
20
|
+
type: "string",
|
|
21
|
+
default: "json"
|
|
22
|
+
} },
|
|
23
|
+
async run({ args }) {
|
|
24
|
+
try {
|
|
25
|
+
writeResult(await requireActiveProject(), args.format);
|
|
26
|
+
} catch (err) {
|
|
27
|
+
writeError(err, args.format);
|
|
28
|
+
process.exit(1);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
//#endregion
|
|
33
|
+
export { current_default as default };
|
|
@@ -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-CnlFIFiY.mjs").then((m) => m.default) }
|
|
9
9
|
});
|
|
10
10
|
//#endregion
|
|
11
11
|
export { customer_default as default };
|
|
@@ -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-D56gEqiB.mjs").then((m) => m.default) }
|
|
9
9
|
});
|
|
10
10
|
//#endregion
|
|
11
11
|
export { focus_default as default };
|
|
@@ -573,13 +573,16 @@ function writeResult(data, format = "json") {
|
|
|
573
573
|
const text = normalize(format) === "toon" ? encode(data) : JSON.stringify(data, null, 2);
|
|
574
574
|
process.stdout.write(text + "\n");
|
|
575
575
|
}
|
|
576
|
-
/** Print an error structurally to stdout (still parseable) and
|
|
576
|
+
/** Print an error structurally to stdout (still parseable) and human hint to stderr. */
|
|
577
577
|
function writeError(error, format = "json") {
|
|
578
578
|
const payload = serializeError(error);
|
|
579
579
|
const text = normalize(format) === "toon" ? encode(payload) : JSON.stringify(payload, null, 2);
|
|
580
580
|
process.stdout.write(text + "\n");
|
|
581
|
-
const
|
|
582
|
-
|
|
581
|
+
const err = payload;
|
|
582
|
+
const errCode = err.error;
|
|
583
|
+
const msg = err.message;
|
|
584
|
+
if (msg) process.stderr.write(`error: ${errCode ? `[${errCode}] ` : ""}${msg}\n`);
|
|
585
|
+
if (err.hint) process.stderr.write(`hint: ${err.hint}\n`);
|
|
583
586
|
}
|
|
584
587
|
function normalize(f) {
|
|
585
588
|
if (f === "toon") return "toon";
|
|
@@ -587,10 +590,15 @@ function normalize(f) {
|
|
|
587
590
|
return "json";
|
|
588
591
|
}
|
|
589
592
|
function serializeError(error) {
|
|
590
|
-
if (error instanceof Error)
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
593
|
+
if (error instanceof Error) {
|
|
594
|
+
const codeAttr = error.code;
|
|
595
|
+
const hint = error.hint;
|
|
596
|
+
return {
|
|
597
|
+
error: codeAttr ?? (error.name !== "Error" ? error.name : "Error"),
|
|
598
|
+
message: error.message,
|
|
599
|
+
...hint ? { hint } : {}
|
|
600
|
+
};
|
|
601
|
+
}
|
|
594
602
|
if (error && typeof error === "object") {
|
|
595
603
|
const obj = error;
|
|
596
604
|
const errorKey = obj.code ?? obj.error ?? "UNKNOWN";
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as resolveConfig } from "./device-flow-
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as
|
|
4
|
-
import { t as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { a as resolveConfig } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-zDBFgk0y.mjs";
|
|
3
|
+
import { n as requireActiveProject } from "./project-store-CKVJa54T.mjs";
|
|
4
|
+
import { t as tenantProjectHeaders } from "./headers-DSnR4sjk.mjs";
|
|
5
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
6
|
+
import { r as toLocalDateTime } from "./util-CaPQBlNa.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/visit/list.ts
|
|
9
9
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as resolveConfig } from "./device-flow-
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as
|
|
4
|
-
import { t as
|
|
5
|
-
import {
|
|
6
|
-
import { t as
|
|
1
|
+
import { a as resolveConfig } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-zDBFgk0y.mjs";
|
|
3
|
+
import { n as requireActiveProject } from "./project-store-CKVJa54T.mjs";
|
|
4
|
+
import { t as tenantProjectHeaders } from "./headers-DSnR4sjk.mjs";
|
|
5
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
6
|
+
import { r as toLocalDateTime, t as csvToArray } from "./util-CaPQBlNa.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/resistance/list.ts
|
|
9
9
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as resolveConfig } from "./device-flow-
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as
|
|
4
|
-
import { t as
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
1
|
+
import { a as resolveConfig } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-zDBFgk0y.mjs";
|
|
3
|
+
import { n as requireActiveProject } from "./project-store-CKVJa54T.mjs";
|
|
4
|
+
import { t as tenantProjectHeaders } from "./headers-DSnR4sjk.mjs";
|
|
5
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
6
|
+
import { r as toLocalDateTime } from "./util-CaPQBlNa.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/customer/list.ts
|
|
9
9
|
/**
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as resolveConfig } from "./device-flow-
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as
|
|
4
|
-
import { t as
|
|
5
|
-
import { t as
|
|
1
|
+
import { a as resolveConfig } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-zDBFgk0y.mjs";
|
|
3
|
+
import { n as requireActiveProject } from "./project-store-CKVJa54T.mjs";
|
|
4
|
+
import { t as tenantProjectHeaders } from "./headers-DSnR4sjk.mjs";
|
|
5
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
6
6
|
import { defineCommand } from "citty";
|
|
7
7
|
//#region src/commands/consultant/list.ts
|
|
8
8
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as resolveConfig } from "./device-flow-
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as
|
|
4
|
-
import { t as
|
|
5
|
-
import {
|
|
6
|
-
import { t as
|
|
1
|
+
import { a as resolveConfig } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-zDBFgk0y.mjs";
|
|
3
|
+
import { n as requireActiveProject } from "./project-store-CKVJa54T.mjs";
|
|
4
|
+
import { t as tenantProjectHeaders } from "./headers-DSnR4sjk.mjs";
|
|
5
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
6
|
+
import { r as toLocalDateTime, t as csvToArray } from "./util-CaPQBlNa.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/focus/list.ts
|
|
9
9
|
/**
|
|
@@ -1,9 +1,9 @@
|
|
|
1
|
-
import { a as resolveConfig } from "./device-flow-
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as
|
|
4
|
-
import { t as
|
|
5
|
-
import { n as
|
|
6
|
-
import { t as
|
|
1
|
+
import { a as resolveConfig } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-zDBFgk0y.mjs";
|
|
3
|
+
import { n as requireActiveProject } from "./project-store-CKVJa54T.mjs";
|
|
4
|
+
import { t as tenantProjectHeaders } from "./headers-DSnR4sjk.mjs";
|
|
5
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
6
|
+
import { n as mergeUserIds, r as toLocalDateTime, t as csvToArray } from "./util-CaPQBlNa.mjs";
|
|
7
7
|
import { defineCommand } from "citty";
|
|
8
8
|
//#region src/commands/audio/list.ts
|
|
9
9
|
/**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { a as resolveConfig } from "./device-flow-
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
1
|
+
import { a as resolveConfig } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-zDBFgk0y.mjs";
|
|
3
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
//#region src/commands/project/list.ts
|
|
6
6
|
/**
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
import { a as resolveConfig, n as pollForToken, r as refreshToken, t as initiateDeviceAuthorization } from "./device-flow-D6JVcEap.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-CXizLE2_.mjs";
|
|
3
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
4
|
+
import { defineCommand } from "citty";
|
|
5
|
+
//#region src/commands/auth/login.ts
|
|
6
|
+
/**
|
|
7
|
+
* `xiaobao-cli auth login` — OAuth 2.0 Device Authorization Grant.
|
|
8
|
+
*
|
|
9
|
+
* Three modes:
|
|
10
|
+
*
|
|
11
|
+
* 1. Default (blocking) — cache hit / refresh / else initiate the device
|
|
12
|
+
* flow and synchronously poll until success/denial/expiry. Best for a
|
|
13
|
+
* human running it directly in a terminal.
|
|
14
|
+
*
|
|
15
|
+
* 2. `--no-wait` (non-blocking, agent-friendly split-flow step 1) — cache
|
|
16
|
+
* hit / refresh as usual; otherwise initiate the device flow, persist
|
|
17
|
+
* the device_code locally (~/.xiaobao/pending-auth.json, mode 0600) and
|
|
18
|
+
* return immediately with the verification URL — WITHOUT polling and
|
|
19
|
+
* WITHOUT exposing the credential-grade device_code on stdout. The agent
|
|
20
|
+
* forwards the URL to the user, ends its turn, then runs step 2.
|
|
21
|
+
*
|
|
22
|
+
* 3. `--resume` (split-flow step 2) — read the locally-saved device_code
|
|
23
|
+
* and exchange it for a token; no argument needed. `--device-code <code>`
|
|
24
|
+
* remains as an explicit escape hatch and takes precedence when given.
|
|
25
|
+
*/
|
|
26
|
+
var login_default = defineCommand({
|
|
27
|
+
meta: {
|
|
28
|
+
name: "login",
|
|
29
|
+
description: "走 OAuth device flow 登录(--no-wait 非阻塞发起 / --resume 完成)"
|
|
30
|
+
},
|
|
31
|
+
args: {
|
|
32
|
+
force: {
|
|
33
|
+
type: "boolean",
|
|
34
|
+
description: "强制清除缓存并重新发起设备授权流程"
|
|
35
|
+
},
|
|
36
|
+
wait: {
|
|
37
|
+
type: "boolean",
|
|
38
|
+
default: true,
|
|
39
|
+
description: "默认阻塞轮询直到授权完成。`--no-wait` 则发起 device flow 后立即返回 verification_uri 不轮询(device_code 安全存本地,不进 stdout);用户授权后 再用 `auth login --resume` 完成换 token。"
|
|
40
|
+
},
|
|
41
|
+
resume: {
|
|
42
|
+
type: "boolean",
|
|
43
|
+
description: "split-flow 第二步:用上次 `--no-wait` 本地保存的 device_code 换 token,用户在浏览器授权后跑,无需手动传 device_code。"
|
|
44
|
+
},
|
|
45
|
+
"device-code": {
|
|
46
|
+
type: "string",
|
|
47
|
+
description: "(高级 escape hatch)显式传入 device_code 换 token;一般用 `--resume` 即可,CLI 会自动读取本地保存的 device_code。"
|
|
48
|
+
},
|
|
49
|
+
"api-base": {
|
|
50
|
+
type: "string",
|
|
51
|
+
description: "覆盖 API base URL"
|
|
52
|
+
},
|
|
53
|
+
"auth-base": {
|
|
54
|
+
type: "string",
|
|
55
|
+
description: "覆盖 auth base URL"
|
|
56
|
+
},
|
|
57
|
+
format: {
|
|
58
|
+
type: "string",
|
|
59
|
+
default: "json"
|
|
60
|
+
}
|
|
61
|
+
},
|
|
62
|
+
async run({ args }) {
|
|
63
|
+
const config = resolveConfig({
|
|
64
|
+
apiBase: args["api-base"],
|
|
65
|
+
authBase: args["auth-base"]
|
|
66
|
+
});
|
|
67
|
+
const fmt = args.format;
|
|
68
|
+
try {
|
|
69
|
+
if (args.resume || args["device-code"]) {
|
|
70
|
+
let deviceCode;
|
|
71
|
+
let remainingSeconds = 300;
|
|
72
|
+
if (args["device-code"]) deviceCode = String(args["device-code"]);
|
|
73
|
+
else {
|
|
74
|
+
const pending = await readPendingAuth();
|
|
75
|
+
if (!pending) throw new NoPendingAuthError();
|
|
76
|
+
if (pending.expires_at <= Date.now()) {
|
|
77
|
+
await clearPendingAuth();
|
|
78
|
+
throw new NoPendingAuthError("设备授权已过期,device_code 失效");
|
|
79
|
+
}
|
|
80
|
+
deviceCode = pending.device_code;
|
|
81
|
+
remainingSeconds = Math.max(1, Math.ceil((pending.expires_at - Date.now()) / 1e3));
|
|
82
|
+
}
|
|
83
|
+
const saved = await writeToken(await pollForToken(config, deviceCode, 2, remainingSeconds));
|
|
84
|
+
await clearPendingAuth();
|
|
85
|
+
writeResult({
|
|
86
|
+
source: "device-flow",
|
|
87
|
+
expires_at: saved.expires_at,
|
|
88
|
+
scope: saved.scope,
|
|
89
|
+
message: "登录成功,可以正常使用别的命令了"
|
|
90
|
+
}, fmt);
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
if (!args.force) {
|
|
94
|
+
const cached = await readToken();
|
|
95
|
+
if (isAccessTokenValid(cached)) {
|
|
96
|
+
writeResult({
|
|
97
|
+
source: "cache",
|
|
98
|
+
expires_at: cached.expires_at,
|
|
99
|
+
scope: cached.scope
|
|
100
|
+
}, fmt);
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (cached?.refresh_token) try {
|
|
104
|
+
const saved = await writeToken(await refreshToken(config, cached.refresh_token));
|
|
105
|
+
writeResult({
|
|
106
|
+
source: "refresh",
|
|
107
|
+
expires_at: saved.expires_at,
|
|
108
|
+
scope: saved.scope
|
|
109
|
+
}, fmt);
|
|
110
|
+
return;
|
|
111
|
+
} catch {
|
|
112
|
+
await clearToken();
|
|
113
|
+
}
|
|
114
|
+
} else await clearToken();
|
|
115
|
+
const init = await initiateDeviceAuthorization(config);
|
|
116
|
+
const verificationUri = init.verification_uri_complete || init.verification_uri;
|
|
117
|
+
const expiresMinutes = Math.max(1, Math.round(init.expires_in / 60));
|
|
118
|
+
const interval = init.interval ?? 5;
|
|
119
|
+
if (!args.wait) {
|
|
120
|
+
await writePendingAuth({
|
|
121
|
+
device_code: init.device_code,
|
|
122
|
+
user_code: init.user_code,
|
|
123
|
+
verification_uri: verificationUri,
|
|
124
|
+
interval,
|
|
125
|
+
expires_at: Date.now() + init.expires_in * 1e3
|
|
126
|
+
});
|
|
127
|
+
writeResult({
|
|
128
|
+
awaiting_authorization: true,
|
|
129
|
+
verification_uri: verificationUri,
|
|
130
|
+
user_code: init.user_code,
|
|
131
|
+
expires_in: init.expires_in,
|
|
132
|
+
interval,
|
|
133
|
+
message: "请在浏览器打开 verification_uri 完成授权,然后跑 `xiaobao-cli auth login --resume` 完成登录。device_code 已安全保存在本地,无需手动传。"
|
|
134
|
+
}, fmt);
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
process.stderr.write(`
|
|
138
|
+
请在浏览器中打开以下链接完成登录并授权访问你的旺小宝账号:
|
|
139
|
+
\n 🔗 ${verificationUri}\n\n 设备验证码: ${init.user_code}\n 有效期约 ${expiresMinutes} 分钟\n\n等待你在浏览器中确认 ...
|
|
140
|
+
`);
|
|
141
|
+
const saved = await writeToken(await pollForToken(config, init.device_code, interval, init.expires_in));
|
|
142
|
+
await clearPendingAuth();
|
|
143
|
+
writeResult({
|
|
144
|
+
source: "device-flow",
|
|
145
|
+
expires_at: saved.expires_at,
|
|
146
|
+
scope: saved.scope,
|
|
147
|
+
message: "登录成功,token 已缓存到 ~/.xiaobao/token.json"
|
|
148
|
+
}, fmt);
|
|
149
|
+
} catch (err) {
|
|
150
|
+
writeError(err, fmt);
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
//#endregion
|
|
156
|
+
export { login_default as default };
|
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import { a as resolveConfig, i as revokeRefreshToken } from "./device-flow-
|
|
2
|
-
import {
|
|
3
|
-
import { n as writeResult, t as writeError } from "./format-
|
|
1
|
+
import { a as resolveConfig, i as revokeRefreshToken } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { n as clearPendingAuth, r as clearToken, s as readToken } from "./token-store-CXizLE2_.mjs";
|
|
3
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
4
4
|
import { defineCommand } from "citty";
|
|
5
5
|
//#region src/commands/auth/logout.ts
|
|
6
6
|
/**
|
|
7
7
|
* `xiaobao-cli auth logout` — clear local token + best-effort revoke remote
|
|
8
|
-
* refresh_token.
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* refresh_token. Clears BOTH ~/.xiaobao/token.json and the legacy fallback
|
|
9
|
+
* ~/.openclaw/state/wangxiaobao/token.json — otherwise `auth whoami` would
|
|
10
|
+
* read the legacy file via fallback and report logged_in true even after
|
|
11
|
+
* logout. The refresh_token is revoked server-side first so the legacy file
|
|
12
|
+
* is already a dead token by the time it's unlinked.
|
|
11
13
|
*/
|
|
12
14
|
var logout_default = defineCommand({
|
|
13
15
|
meta: {
|
|
@@ -31,10 +33,11 @@ var logout_default = defineCommand({
|
|
|
31
33
|
let revoked = false;
|
|
32
34
|
if (cached?.refresh_token) revoked = await revokeRefreshToken(config, cached.refresh_token);
|
|
33
35
|
await clearToken();
|
|
36
|
+
await clearPendingAuth();
|
|
34
37
|
writeResult({
|
|
35
38
|
message: "Logged out",
|
|
36
39
|
remote_revoked: revoked,
|
|
37
|
-
note: "
|
|
40
|
+
note: "Cleared ~/.xiaobao/token.json and legacy ~/.openclaw/state/wangxiaobao/token.json (if existed)."
|
|
38
41
|
}, args.format);
|
|
39
42
|
} catch (err) {
|
|
40
43
|
try {
|
|
@@ -6,8 +6,9 @@ var project_default = defineCommand({
|
|
|
6
6
|
description: "查询 / 切换激活项目"
|
|
7
7
|
},
|
|
8
8
|
subCommands: {
|
|
9
|
-
list: () => import("./list-
|
|
10
|
-
use: () => import("./use-
|
|
9
|
+
list: () => import("./list-DI1OD95x.mjs").then((m) => m.default),
|
|
10
|
+
use: () => import("./use-BZES4FZC.mjs").then((m) => m.default),
|
|
11
|
+
current: () => import("./current-CfDExInT.mjs").then((m) => m.default)
|
|
11
12
|
}
|
|
12
13
|
});
|
|
13
14
|
//#endregion
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { existsSync } from "node:fs";
|
|
2
|
-
import { homedir } from "node:os";
|
|
3
2
|
import { join } from "node:path";
|
|
3
|
+
import { homedir } from "node:os";
|
|
4
4
|
import { chmod, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
5
5
|
//#region src/core/project-store.ts
|
|
6
6
|
/**
|
|
@@ -48,8 +48,9 @@ async function saveActiveProject(p) {
|
|
|
48
48
|
}
|
|
49
49
|
var NoActiveProjectError = class extends Error {
|
|
50
50
|
code = "NO_ACTIVE_PROJECT";
|
|
51
|
+
hint = "先用 `xiaobao-cli project list [--keyword <kw>]` 查看可选项目,再用 `xiaobao-cli project use --tenant-id ... --tenant-name ... --project-id ... --project-name ...` 激活。";
|
|
51
52
|
constructor() {
|
|
52
|
-
super("
|
|
53
|
+
super("当前未设置激活项目");
|
|
53
54
|
this.name = "NoActiveProjectError";
|
|
54
55
|
}
|
|
55
56
|
};
|
|
@@ -59,4 +60,4 @@ async function requireActiveProject() {
|
|
|
59
60
|
return p;
|
|
60
61
|
}
|
|
61
62
|
//#endregion
|
|
62
|
-
export {
|
|
63
|
+
export { requireActiveProject as n, saveActiveProject as r, loadActiveProject as t };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as resolveConfig } from "./device-flow-
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as
|
|
4
|
-
import { t as
|
|
5
|
-
import { t as
|
|
1
|
+
import { a as resolveConfig } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-zDBFgk0y.mjs";
|
|
3
|
+
import { n as requireActiveProject } from "./project-store-CKVJa54T.mjs";
|
|
4
|
+
import { t as tenantProjectHeaders } from "./headers-DSnR4sjk.mjs";
|
|
5
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
6
6
|
import { defineCommand } from "citty";
|
|
7
7
|
//#region src/commands/qa.ts
|
|
8
8
|
/**
|
|
@@ -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-CKlx8YuL.mjs").then((m) => m.default) }
|
|
9
9
|
});
|
|
10
10
|
//#endregion
|
|
11
11
|
export { resistance_default as default };
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import { a as resolveConfig } from "./device-flow-
|
|
2
|
-
import { t as xbApiFetch } from "./api-client-
|
|
3
|
-
import { n as
|
|
4
|
-
import { t as
|
|
5
|
-
import { t as
|
|
1
|
+
import { a as resolveConfig } from "./device-flow-D6JVcEap.mjs";
|
|
2
|
+
import { t as xbApiFetch } from "./api-client-zDBFgk0y.mjs";
|
|
3
|
+
import { n as requireActiveProject } from "./project-store-CKVJa54T.mjs";
|
|
4
|
+
import { t as tenantProjectHeaders } from "./headers-DSnR4sjk.mjs";
|
|
5
|
+
import { n as writeResult, t as writeError } from "./format-yjmxrbNm.mjs";
|
|
6
6
|
import { defineCommand } from "citty";
|
|
7
7
|
//#region src/commands/audio/text.ts
|
|
8
8
|
/**
|