siluzan-tso-cli 1.1.18-beta.1 → 1.1.18-beta.2
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 +1 -1
- package/dist/index.js +72 -44
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/references/setup.md +28 -18
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -51,7 +51,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
|
|
|
51
51
|
siluzan-tso init --force # 强制覆盖已存在文件
|
|
52
52
|
```
|
|
53
53
|
|
|
54
|
-
> **注意**:当前为测试版(1.1.18-beta.
|
|
54
|
+
> **注意**:当前为测试版(1.1.18-beta.2),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
55
55
|
|
|
56
56
|
| 助手 | 建议 `--ai` |
|
|
57
57
|
| ----------------------- | ------------------------------------ |
|
package/dist/index.js
CHANGED
|
@@ -2913,23 +2913,15 @@ async function createApiKeyByBearer(opts) {
|
|
|
2913
2913
|
}
|
|
2914
2914
|
return data;
|
|
2915
2915
|
}
|
|
2916
|
-
async function
|
|
2917
|
-
const
|
|
2918
|
-
ssoBaseUrl: opts.ssoBaseUrl,
|
|
2919
|
-
phone: opts.phone,
|
|
2920
|
-
verbose: opts.verbose
|
|
2921
|
-
});
|
|
2922
|
-
if (!sendResult.ok) {
|
|
2923
|
-
throw new Error(`\u77ED\u4FE1\u9A8C\u8BC1\u7801\u53D1\u9001\u5931\u8D25\uFF1A${sendResult.message || "(\u540E\u7AEF\u672A\u8FD4\u56DE\u539F\u56E0)"}`);
|
|
2924
|
-
}
|
|
2925
|
-
const code = await opts.getCode();
|
|
2916
|
+
async function issueApiKeyWithPhoneCode(opts) {
|
|
2917
|
+
const code = opts.code?.trim() ?? "";
|
|
2926
2918
|
if (!code) {
|
|
2927
|
-
throw new Error("\
|
|
2919
|
+
throw new Error("\u9A8C\u8BC1\u7801\u4E0D\u80FD\u4E3A\u7A7A");
|
|
2928
2920
|
}
|
|
2929
2921
|
const tokenInfo = await loginByPhoneCode({
|
|
2930
2922
|
ssoBaseUrl: opts.ssoBaseUrl,
|
|
2931
2923
|
phone: opts.phone,
|
|
2932
|
-
code
|
|
2924
|
+
code,
|
|
2933
2925
|
verbose: opts.verbose
|
|
2934
2926
|
});
|
|
2935
2927
|
const apiKey = await createApiKeyByBearer({
|
|
@@ -16447,15 +16439,53 @@ function defaultApiKeyName() {
|
|
|
16447
16439
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
16448
16440
|
return `CLI - ${host} - ${today}`;
|
|
16449
16441
|
}
|
|
16450
|
-
|
|
16451
|
-
const rawPhone =
|
|
16442
|
+
function validateAndNormalizePhone(rawInput) {
|
|
16443
|
+
const rawPhone = rawInput?.trim() ?? "";
|
|
16452
16444
|
if (!isValidChinaPhone(rawPhone)) {
|
|
16453
16445
|
console.error(
|
|
16454
16446
|
"\n\u274C \u624B\u673A\u53F7\u683C\u5F0F\u9519\u8BEF\uFF1A\u4EC5\u652F\u6301\u4E2D\u56FD\u5927\u9646\u624B\u673A\u53F7\uFF0C\u53EF\u5E26\u6216\u4E0D\u5E26 +86\uFF08\u5982 13800138000 / +8613800138000\uFF09\u3002\n"
|
|
16455
16447
|
);
|
|
16456
16448
|
process.exit(1);
|
|
16457
16449
|
}
|
|
16458
|
-
|
|
16450
|
+
return normalizeChinaPhone(rawPhone);
|
|
16451
|
+
}
|
|
16452
|
+
async function runSendLoginCode(opts) {
|
|
16453
|
+
const phone = validateAndNormalizePhone(opts.phone);
|
|
16454
|
+
const tsoApiBase = process.env.SILUZAN_TSO_API_BASE ?? DEFAULT_API_BASE;
|
|
16455
|
+
const ssoBaseUrl = deriveSsoBaseUrl(tsoApiBase);
|
|
16456
|
+
console.log("\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
16457
|
+
console.log(" Siluzan \u53D1\u9001\u767B\u5F55\u77ED\u4FE1\u9A8C\u8BC1\u7801");
|
|
16458
|
+
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
|
|
16459
|
+
console.log(` \u624B\u673A\u53F7 : ${phone}`);
|
|
16460
|
+
console.log(` SSO : ${ssoBaseUrl}
|
|
16461
|
+
`);
|
|
16462
|
+
console.log("\u2192 \u6B63\u5728\u5411\u624B\u673A\u53D1\u9001\u9A8C\u8BC1\u7801...");
|
|
16463
|
+
const r = await sendPhoneLoginCode({ ssoBaseUrl, phone, verbose: opts.verbose });
|
|
16464
|
+
if (!r.ok) {
|
|
16465
|
+
console.error(`
|
|
16466
|
+
\u274C \u77ED\u4FE1\u9A8C\u8BC1\u7801\u53D1\u9001\u5931\u8D25\uFF1A${r.message || "(\u540E\u7AEF\u672A\u8FD4\u56DE\u539F\u56E0)"}
|
|
16467
|
+
`);
|
|
16468
|
+
process.exit(1);
|
|
16469
|
+
}
|
|
16470
|
+
console.log(`\u2713 \u9A8C\u8BC1\u7801\u5DF2\u53D1\u9001\uFF0810 \u5206\u949F\u5185\u6709\u6548\uFF09\u3002
|
|
16471
|
+
`);
|
|
16472
|
+
console.log("\u4E0B\u4E00\u6B65\uFF1A\u62FF\u5230 6 \u4F4D\u9A8C\u8BC1\u7801\u540E\uFF0C\u8FD0\u884C\u4E0B\u9762\u7684\u547D\u4EE4\u5B8C\u6210\u767B\u5F55\uFF1A\n");
|
|
16473
|
+
console.log(` siluzan-tso login --phone ${phone} --code <6\u4F4D\u9A8C\u8BC1\u7801>
|
|
16474
|
+
`);
|
|
16475
|
+
console.log("\u53EF\u9009\u53C2\u6570\uFF1A--name / --valid-days / --expires-at / --services");
|
|
16476
|
+
console.log("\uFF08\u9ED8\u8BA4\u521B\u5EFA 90 \u5929\u6709\u6548\u3001\u52FE\u9009 TSO + CUT \u670D\u52A1\u7684 API Key\uFF09\n");
|
|
16477
|
+
}
|
|
16478
|
+
async function runPhoneLogin(opts) {
|
|
16479
|
+
const phone = validateAndNormalizePhone(opts.phone);
|
|
16480
|
+
const code = opts.code?.trim() ?? "";
|
|
16481
|
+
if (!code) {
|
|
16482
|
+
console.error("\n\u274C \u7F3A\u5C11 --code \u53C2\u6570\u3002\u624B\u673A\u53F7\u767B\u5F55\u662F\u4E24\u6BB5\u5F0F\u8C03\u7528\uFF0C\u8BF7\u6309\u987A\u5E8F\u6267\u884C\uFF1A\n");
|
|
16483
|
+
console.error(` 1) siluzan-tso send-login-code --phone ${phone}`);
|
|
16484
|
+
console.error(` 2) siluzan-tso login --phone ${phone} --code <\u6536\u5230\u76846\u4F4D\u9A8C\u8BC1\u7801>
|
|
16485
|
+
`);
|
|
16486
|
+
console.error("\uFF08\u62C6\u6210\u4E24\u6B65\u662F\u4E3A\u4E86\u907F\u514D AI Agent \u5361\u5728\u4EA4\u4E92\u8F93\u5165\u65F6\u53CD\u590D\u91CD\u8BD5\u5BFC\u81F4\u77ED\u4FE1\u8F70\u70B8\uFF09\n");
|
|
16487
|
+
process.exit(1);
|
|
16488
|
+
}
|
|
16459
16489
|
let allowedServices;
|
|
16460
16490
|
try {
|
|
16461
16491
|
allowedServices = parseAllowedServices(opts.services);
|
|
@@ -16472,10 +16502,12 @@ async function runPhoneLogin(opts) {
|
|
|
16472
16502
|
const tsoApiBase = process.env.SILUZAN_TSO_API_BASE ?? DEFAULT_API_BASE;
|
|
16473
16503
|
const ssoBaseUrl = deriveSsoBaseUrl(tsoApiBase);
|
|
16474
16504
|
const csoBaseUrl = deriveCsoApiBaseUrl(tsoApiBase);
|
|
16505
|
+
const apiKeyName = opts.name ?? defaultApiKeyName();
|
|
16475
16506
|
console.log("\n\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550");
|
|
16476
16507
|
console.log(" Siluzan \u767B\u5F55\uFF08\u624B\u673A\u53F7 + \u77ED\u4FE1\u9A8C\u8BC1\u7801\uFF09");
|
|
16477
16508
|
console.log("\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\u2550\n");
|
|
16478
16509
|
console.log(` \u624B\u673A\u53F7 : ${phone}`);
|
|
16510
|
+
console.log(` \u9A8C\u8BC1\u7801 : ${code}`);
|
|
16479
16511
|
console.log(` SSO : ${ssoBaseUrl}`);
|
|
16480
16512
|
console.log(` CSO API : ${csoBaseUrl}`);
|
|
16481
16513
|
console.log(` \u670D\u52A1\u8303\u56F4 : ${allowedServices.join(", ")}`);
|
|
@@ -16484,40 +16516,20 @@ async function runPhoneLogin(opts) {
|
|
|
16484
16516
|
} else {
|
|
16485
16517
|
console.log(` \u6709\u6548\u671F : ${opts.validDays ?? 90} \u5929`);
|
|
16486
16518
|
}
|
|
16487
|
-
const apiKeyName = opts.name ?? defaultApiKeyName();
|
|
16488
16519
|
console.log(` API Key \u540D\u79F0 : ${apiKeyName}
|
|
16489
16520
|
`);
|
|
16490
|
-
console.log("\u2192 \u6B63\u5728\
|
|
16521
|
+
console.log("\u2192 \u6B63\u5728\u6821\u9A8C\u9A8C\u8BC1\u7801\u5E76\u521B\u5EFA API Key...");
|
|
16491
16522
|
try {
|
|
16492
|
-
const created = await
|
|
16523
|
+
const created = await issueApiKeyWithPhoneCode({
|
|
16493
16524
|
ssoBaseUrl,
|
|
16494
16525
|
csoBaseUrl,
|
|
16495
16526
|
phone,
|
|
16527
|
+
code,
|
|
16496
16528
|
apiKeyName,
|
|
16497
16529
|
validDays: opts.expiresAt ? void 0 : opts.validDays ?? 90,
|
|
16498
16530
|
expiresAt: opts.expiresAt,
|
|
16499
16531
|
allowedServices,
|
|
16500
|
-
verbose: opts.verbose
|
|
16501
|
-
getCode: async () => {
|
|
16502
|
-
if (opts.code !== void 0) {
|
|
16503
|
-
const trimmed = opts.code.trim();
|
|
16504
|
-
if (!trimmed) {
|
|
16505
|
-
console.error("\u274C --code \u4E0D\u80FD\u4E3A\u7A7A\u3002");
|
|
16506
|
-
return null;
|
|
16507
|
-
}
|
|
16508
|
-
console.log(`\u2713 \u9A8C\u8BC1\u7801\u5DF2\u53D1\u9001\uFF0C\u4F7F\u7528\u547D\u4EE4\u884C\u4F20\u5165\u7684 code\uFF08${trimmed}\uFF09\u3002`);
|
|
16509
|
-
return trimmed;
|
|
16510
|
-
}
|
|
16511
|
-
console.log("\u2713 \u9A8C\u8BC1\u7801\u5DF2\u53D1\u9001\uFF0810 \u5206\u949F\u5185\u6709\u6548\uFF09\u3002");
|
|
16512
|
-
const rl = readline2.createInterface({ input: process.stdin, output: process.stdout });
|
|
16513
|
-
const input = await new Promise(
|
|
16514
|
-
(res) => rl.question("\u8BF7\u8F93\u5165\u6536\u5230\u7684 6 \u4F4D\u9A8C\u8BC1\u7801\uFF1A", (a) => {
|
|
16515
|
-
rl.close();
|
|
16516
|
-
res(a.trim());
|
|
16517
|
-
})
|
|
16518
|
-
);
|
|
16519
|
-
return input || null;
|
|
16520
|
-
}
|
|
16532
|
+
verbose: opts.verbose
|
|
16521
16533
|
});
|
|
16522
16534
|
writeSharedConfig({ apiKey: created.rawKey });
|
|
16523
16535
|
console.log("\n\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500");
|
|
@@ -16545,7 +16557,16 @@ async function runPhoneLogin(opts) {
|
|
|
16545
16557
|
`
|
|
16546
16558
|
\u8BE5\u624B\u673A\u53F7\u5C1A\u672A\u6CE8\u518C\u4E1D\u8DEF\u8D5E\u8D26\u53F7\u3002\u8BF7\u5148\u5728\u7F51\u9875\u7AEF\u6CE8\u518C\uFF1A
|
|
16547
16559
|
${WEB_BASE_URL}
|
|
16548
|
-
\u6CE8\u518C\u6210\u529F\u540E\u518D\u56DE\u5230 CLI \u91CD\u8BD5
|
|
16560
|
+
\u6CE8\u518C\u6210\u529F\u540E\u518D\u56DE\u5230 CLI \u91CD\u8BD5\u4E24\u6BB5\u5F0F\u767B\u5F55\uFF1A
|
|
16561
|
+
siluzan-tso send-login-code --phone ${phone}
|
|
16562
|
+
siluzan-tso login --phone ${phone} --code <6\u4F4D\u9A8C\u8BC1\u7801>
|
|
16563
|
+
`
|
|
16564
|
+
);
|
|
16565
|
+
} else if (/验证码错误|验证码/.test(msg)) {
|
|
16566
|
+
console.error(
|
|
16567
|
+
`
|
|
16568
|
+
\u9A8C\u8BC1\u7801\u53EF\u80FD\u5DF2\u8FC7\u671F\u6216\u8F93\u9519\u3002\u8BF7\u91CD\u65B0\u53D1\u7801\u540E\u518D\u8BD5\uFF1A
|
|
16569
|
+
siluzan-tso send-login-code --phone ${phone}
|
|
16549
16570
|
`
|
|
16550
16571
|
);
|
|
16551
16572
|
}
|
|
@@ -16664,15 +16685,22 @@ program.hook("preAction", async () => {
|
|
|
16664
16685
|
setWriteAuditCliCommit(extractCommitFromArgv(process.argv.slice(2)));
|
|
16665
16686
|
setCliInvocationForAudit(process.argv.slice(2));
|
|
16666
16687
|
const activeCmd = process.argv[2];
|
|
16667
|
-
if (activeCmd !== "update" && activeCmd !== "login" && activeCmd !== "audit") {
|
|
16688
|
+
if (activeCmd !== "update" && activeCmd !== "login" && activeCmd !== "send-login-code" && activeCmd !== "audit") {
|
|
16668
16689
|
await notifyIfOutdated().catch(() => {
|
|
16669
16690
|
});
|
|
16670
16691
|
}
|
|
16671
16692
|
});
|
|
16672
|
-
program.command("login").description(
|
|
16693
|
+
program.command("send-login-code").description(
|
|
16694
|
+
"\u5411\u624B\u673A\u53D1\u9001 SSO_LOGIN \u77ED\u4FE1\u9A8C\u8BC1\u7801\uFF08\u624B\u673A\u53F7\u767B\u5F55\u7684\u7B2C\u4E00\u6B65\uFF09\uFF1B\u7ACB\u5373\u8FD4\u56DE\uFF0C\u65E0\u4EFB\u4F55\u4EA4\u4E92\u3002\n \u6536\u5230\u9A8C\u8BC1\u7801\u540E\u7528 `siluzan-tso login --phone xxx --code xxx` \u5B8C\u6210\u767B\u5F55\u3002"
|
|
16695
|
+
).requiredOption(
|
|
16673
16696
|
"--phone <phone>",
|
|
16674
|
-
"
|
|
16675
|
-
).option("--
|
|
16697
|
+
"\u4E2D\u56FD\u5927\u9646\u624B\u673A\u53F7\uFF0C\u53EF\u5E26\u6216\u4E0D\u5E26 +86\uFF08\u5982 13800138000 / +8613800138000\uFF09"
|
|
16698
|
+
).option("--verbose", "\u8F93\u51FA\u6BCF\u6B21 HTTP \u8BF7\u6C42 URL\uFF08\u8C03\u8BD5\u7528\uFF09").action(async (opts) => {
|
|
16699
|
+
await runSendLoginCode({ phone: opts.phone, verbose: opts.verbose });
|
|
16700
|
+
});
|
|
16701
|
+
program.command("login").description(
|
|
16702
|
+
"\u4FDD\u5B58\u8BA4\u8BC1\u51ED\u636E\u5230 ~/.siluzan/config.json\uFF1A\n \xB7 --api-key <key> \u76F4\u63A5\u4FDD\u5B58 API Key\uFF08CI/CD \u63A8\u8350\uFF09\n \xB7 --phone <\u624B\u673A\u53F7> --code <\u9A8C\u8BC1\u7801> \u4E24\u6BB5\u5F0F\u767B\u5F55\u7B2C\u4E8C\u6B65\uFF08\u5148\u8C03 send-login-code\uFF09\n \xB7 \u65E0\u53C2\u6570 \u4EA4\u4E92\u5F0F\u5F15\u5BFC\u7528\u6237\u53BB\u7F51\u9875\u7C98\u8D34 API Key"
|
|
16703
|
+
).option("--api-key <key>", "\u76F4\u63A5\u4FDD\u5B58 API Key\uFF08\u5728\u4E1D\u8DEF\u8D5E\u300C\u8BBE\u7F6E \u2192 API Key \u7BA1\u7406\u300D\u521B\u5EFA\uFF09\uFF0C\u6700\u9AD8\u4F18\u5148\u7EA7").option("--phone <phone>", "\u4E2D\u56FD\u5927\u9646\u624B\u673A\u53F7\uFF0C\u9700\u914D\u5408 --code \u4E00\u8D77\u4F7F\u7528\uFF08\u5FC5\u987B\u5148\u8C03 send-login-code \u53D1\u7801\uFF09").option("--code <code>", "\u77ED\u4FE1\u9A8C\u8BC1\u7801\uFF086 \u4F4D\uFF09\uFF1B\u4E0E --phone \u4E00\u8D77\u5FC5\u586B").option("--name <name>", "\u81EA\u52A8\u521B\u5EFA\u7684 API Key \u540D\u79F0\uFF0C\u9ED8\u8BA4 `CLI - <hostname> - <yyyy-MM-dd>`").option("--valid-days <days>", "API Key \u6709\u6548\u671F\uFF08\u5929\uFF09\uFF0C\u9ED8\u8BA4 90", (v) => parseInt(v, 10)).option("--expires-at <iso8601>", "API Key \u7EDD\u5BF9\u8FC7\u671F\u65F6\u95F4\uFF08ISO 8601\uFF09\uFF0C\u4E0E --valid-days \u4E8C\u9009\u4E00").option(
|
|
16676
16704
|
"--services <list>",
|
|
16677
16705
|
"API Key \u53EF\u8BBF\u95EE\u7684\u670D\u52A1\u5217\u8868\uFF0C\u9017\u53F7\u5206\u9694\uFF1B\u53EF\u9009 CSO/TSO/CUT\uFF0C\u9ED8\u8BA4 `TSO,CUT`"
|
|
16678
16706
|
).option("--manual", "\u4EA4\u4E92\u5F0F\u7C98\u8D34 JWT Token\uFF08\u65E0 API Key \u65F6\u4F7F\u7528\uFF0C\u5DF2\u5E9F\u5F03\uFF09").option("--verbose", "\u8F93\u51FA\u6BCF\u6B21 HTTP \u8BF7\u6C42 URL\uFF08\u8C03\u8BD5\u7528\uFF09").action(
|
package/dist/skill/_meta.json
CHANGED
|
@@ -43,7 +43,8 @@ siluzan-tso init -d /path/to-your/skills # 写入自定义目录
|
|
|
43
43
|
```bash
|
|
44
44
|
siluzan-tso login # 交互式登录,按提示创建 API Key 后粘贴
|
|
45
45
|
siluzan-tso login --api-key <YOUR_API_KEY> # 直接设置 API Key(跳过交互)
|
|
46
|
-
siluzan-tso login --phone 138xxxx
|
|
46
|
+
siluzan-tso send-login-code --phone 138xxxx # 两段式登录第 1 步:发送短信验证码
|
|
47
|
+
siluzan-tso login --phone 138xxxx --code 123456 # 两段式登录第 2 步:用验证码完成登录
|
|
47
48
|
siluzan-tso config set --api-key <Key> # 或通过 config set 直接写入
|
|
48
49
|
siluzan-tso config set --token <Token> # 备用:设置 JWT Token
|
|
49
50
|
```
|
|
@@ -52,34 +53,43 @@ API Key 获取入口:`https://www-ci.siluzan.com/v3/foreign_trade/settings/api
|
|
|
52
53
|
|
|
53
54
|
### 通过手机号 + 验证码登录(对话式 AI 推荐)
|
|
54
55
|
|
|
55
|
-
|
|
56
|
+
**两段式调用**,专为 AI Agent 设计——任何一步都不会进入交互等待,绝不会卡住 stdout。
|
|
57
|
+
拆分后单一职责:第 1 步只发码;第 2 步只用 code 换 API Key。这样 Agent 不会因为"看到 stdout 卡住就重试"而触发短信轰炸。
|
|
58
|
+
|
|
59
|
+
| 步骤 | 命令 | 说明 |
|
|
60
|
+
| ---- | ---- | ---- |
|
|
61
|
+
| 1 | `siluzan-tso send-login-code --phone <手机号>` | 仅向手机发送 6 位验证码,立即返回;**绝不创建 API Key** |
|
|
62
|
+
| 2 | `siluzan-tso login --phone <手机号> --code <验证码>` | 用 code 完成登录并自动签发 API Key 写入 `~/.siluzan/config.json` |
|
|
56
63
|
|
|
57
64
|
```bash
|
|
58
|
-
# 第 1
|
|
59
|
-
siluzan-tso login --phone 13800138000
|
|
65
|
+
# 第 1 步:让用户报出手机号后,立刻发码(命令立即返回,不会等待输入)
|
|
66
|
+
siluzan-tso send-login-code --phone 13800138000
|
|
60
67
|
|
|
61
|
-
# 第 2
|
|
68
|
+
# 第 2 步:让用户读出收到的 6 位验证码,再调登录命令
|
|
62
69
|
siluzan-tso login --phone 13800138000 --code 123456
|
|
63
70
|
|
|
64
|
-
#
|
|
71
|
+
# 自定义 API Key 名称 / 有效期 / 服务范围
|
|
65
72
|
siluzan-tso login --phone 13800138000 --code 123456 \
|
|
66
73
|
--name "Cursor - my-mac - 2026" \
|
|
67
74
|
--valid-days 30 \
|
|
68
75
|
--services TSO,CUT
|
|
69
76
|
```
|
|
70
77
|
|
|
71
|
-
| 参数
|
|
72
|
-
|
|
|
73
|
-
| `--phone`
|
|
74
|
-
| `--code`
|
|
75
|
-
| `--name`
|
|
76
|
-
| `--valid-days`
|
|
77
|
-
| `--expires-at`
|
|
78
|
-
| `--services`
|
|
79
|
-
| `--verbose`
|
|
80
|
-
|
|
81
|
-
>
|
|
82
|
-
>
|
|
78
|
+
| 参数 | 命令 | 说明 | 默认值 |
|
|
79
|
+
| ---- | ---- | ---- | ---- |
|
|
80
|
+
| `--phone` | 两个命令都需要 | 中国大陆手机号,可带或不带 +86(如 `13800138000` / `+8613800138000`);底层会自动补 `+86` 前缀;**手机号必须已在丝路赞网页端注册** | 必填 |
|
|
81
|
+
| `--code` | 仅 `login` | 6 位短信验证码(来自第 1 步发码后的短信);**login 命令必填**,未传会直接报错指引重新走两段式 | 必填(login 命令) |
|
|
82
|
+
| `--name` | 仅 `login` | 自动创建的 API Key 显示名称 | `CLI - <hostname> - <yyyy-MM-dd>` |
|
|
83
|
+
| `--valid-days` | 仅 `login` | API Key 有效期(天),与 `--expires-at` 二选一 | `90` |
|
|
84
|
+
| `--expires-at` | 仅 `login` | API Key 绝对过期时间(ISO 8601) | 不传则用 `--valid-days` |
|
|
85
|
+
| `--services` | 仅 `login` | 可访问的服务列表,逗号分隔;可选 `CSO`/`TSO`/`CUT` | `TSO,CUT`(广告投放 + 素材中心) |
|
|
86
|
+
| `--verbose` | 两个命令都支持 | 输出每次 HTTP 请求的 URL,便于排错 | 关闭 |
|
|
87
|
+
|
|
88
|
+
> **未注册手机号**:`login` 第 2 步会返回 `❌ 登录失败:手机未注册` 并附带网页注册地址,引导用户先去网页注册再回来重试两段式。
|
|
89
|
+
>
|
|
90
|
+
> **验证码错误/过期**:返回明确提示,让用户重新跑 `send-login-code` 拿新验证码。
|
|
91
|
+
>
|
|
92
|
+
> **AI 助手用法**:先调 `send-login-code` 发码、立即返回继续对话;等用户报出收到的验证码后,再调 `login --phone xxx --code xxx` 完成登录。**永远不要在没拿到 `--code` 的情况下调用 `login --phone xxx`,那会直接报错。**
|
|
83
93
|
|
|
84
94
|
### 通过环境变量传入凭据(CI/CD 推荐)
|
|
85
95
|
|