siluzan-tso-cli 1.1.18-beta.5 → 1.1.18-beta.6

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 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.5),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
54
+ > **注意**:当前为测试版(1.1.18-beta.6),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
55
55
 
56
56
  | 助手 | 建议 `--ai` |
57
57
  | ----------------------- | ------------------------------------ |
@@ -69,7 +69,18 @@ siluzan-tso init --force # 强制覆盖已存在文件
69
69
 
70
70
  **若用户已安装 `siluzan-cso` 并完成登录,无需重复操作,直接跳到第 4 步。**
71
71
 
72
- ### 方式 A:交互式登录(推荐)
72
+ **推荐顺序**:① **手机号 + 验证码**(首选)完整参数与排错见 `references/setup.md`(随 Skill 安装到本地)。
73
+
74
+ ### 方式 A:手机号 + 验证码(**推荐**)
75
+
76
+ ```bash
77
+ siluzan-tso send-login-code --phone <手机号>
78
+ siluzan-tso login --phone <手机号> --code <6位验证码>
79
+ ```
80
+
81
+ 不向终端索要交互输入;Agent 先发码、用户回填验证码后再执行第二步。手机号须已在丝路赞注册。
82
+
83
+ ### 方式 B:交互式登录(需真人 TTY)
73
84
 
74
85
  ```bash
75
86
  siluzan-tso login
@@ -81,13 +92,13 @@ siluzan-tso login
81
92
  siluzan-tso login --api-key <YOUR_API_KEY>
82
93
  ```
83
94
 
84
- ### 方式 B:直接设置(适合自动化场景)
95
+ ### 方式 C:直接设置(适合自动化场景)
85
96
 
86
97
  ```bash
87
98
  siluzan-tso config set --api-key <你的ApiKey>
88
99
  ```
89
100
 
90
- ### 方式 C:Token 登录(已有 siluzan-cso 账号)
101
+ ### 方式 D:Token 登录(已有 siluzan-cso 账号)
91
102
 
92
103
  ```bash
93
104
  npm install -g siluzan-cso-cli
@@ -137,4 +148,4 @@ siluzan-tso init --ai xxx --force
137
148
 
138
149
  ## 6. Token 续期
139
150
 
140
- Token 过期后,重新运行 `siluzan-cso login` `siluzan-tso config set --api-key <新Key>` 即可,`siluzan-tso` 自动读取新凭据,无需额外操作。
151
+ Token 过期后:**优先**再走一遍**方式 A**(手机验证码)签发新 API Key;或 `siluzan-cso login` / `siluzan-tso config set --api-key <新Key>`,`siluzan-tso` 自动读取新凭据。
package/dist/index.js CHANGED
@@ -1974,6 +1974,7 @@ import { performance } from "perf_hooks";
1974
1974
  import * as fs2 from "fs";
1975
1975
  import * as path2 from "path";
1976
1976
  import { fileURLToPath } from "url";
1977
+ import { spawn } from "child_process";
1977
1978
  import Table from "cli-table3";
1978
1979
  import * as path3 from "path";
1979
1980
  import { chmod, mkdir, open, readdir, stat, unlink } from "fs/promises";
@@ -2375,6 +2376,29 @@ async function fetchNpmVersion(pkgName, tag, timeoutMs = 4e3) {
2375
2376
  return null;
2376
2377
  }
2377
2378
  }
2379
+ async function defaultRunMinRequiredGlobalInstall(ctx) {
2380
+ if (process.env.SILUZAN_SKIP_AUTO_GLOBAL_INSTALL === "1") {
2381
+ return { ok: false, stderr: "SILUZAN_SKIP_AUTO_GLOBAL_INSTALL=1" };
2382
+ }
2383
+ const spec = `${ctx.pkgName}@${ctx.tag}`;
2384
+ return await new Promise((resolve32) => {
2385
+ const child = spawn("npm", ["install", "-g", spec, "--no-fund", "--no-audit"], {
2386
+ stdio: "inherit",
2387
+ shell: true
2388
+ });
2389
+ child.on("error", (err) => {
2390
+ resolve32({ ok: false, stderr: err instanceof Error ? err.message : String(err) });
2391
+ });
2392
+ child.on("close", (code, signal) => {
2393
+ if (code === 0) {
2394
+ resolve32({ ok: true });
2395
+ } else {
2396
+ const sig = signal ? ` signal=${signal}` : "";
2397
+ resolve32({ ok: false, stderr: `exit code ${code}${sig}` });
2398
+ }
2399
+ });
2400
+ });
2401
+ }
2378
2402
  function createVersionNotifier(opts) {
2379
2403
  const {
2380
2404
  pkgName,
@@ -2383,6 +2407,7 @@ function createVersionNotifier(opts) {
2383
2407
  resolveTag,
2384
2408
  forceUpdateExtra = "",
2385
2409
  updateAvailableExtra = "",
2410
+ runMinRequiredGlobalInstall = defaultRunMinRequiredGlobalInstall,
2386
2411
  getCurrentVersion: getCurrentVersion22,
2387
2412
  mergeWriteConfig,
2388
2413
  readConfigRaw
@@ -2430,11 +2455,26 @@ function createVersionNotifier(opts) {
2430
2455
  await mergeWriteConfig({ [KEY_LAST_NOTIFIED]: (/* @__PURE__ */ new Date()).toISOString() });
2431
2456
  console.log(
2432
2457
  `
2433
- [SILUZAN_FORCE_UPDATE] \u5F53\u524D\u7248\u672C ${current} \u5DF2\u8FC7\u671F\uFF0C\u6700\u4F4E\u8981\u6C42\u7248\u672C ${minRequired}${tagLabel}
2434
- \u26D4 \u5FC5\u987B\u5148\u5347\u7EA7\u624D\u80FD\u7EE7\u7EED\u4F7F\u7528\uFF0CAgent \u8BF7\u7ACB\u5373\u6267\u884C\uFF1A${binName} update
2435
- \u6216\u624B\u52A8\uFF1Anpm install -g ${pkgName}@${tag}
2458
+ [SILUZAN_FORCE_UPDATE] \u5F53\u524D\u7248\u672C ${current} \u5DF2\u4F4E\u4E8E\u6700\u4F4E\u8981\u6C42 ${minRequired}${tagLabel}
2459
+ \u26D4 \u6B63\u5728\u81EA\u52A8\u6267\u884C\uFF1Anpm install -g ${pkgName}@${tag}
2436
2460
  ` + (forceUpdateExtra ? forceUpdateExtra + "\n" : "")
2437
2461
  );
2462
+ const installResult = await runMinRequiredGlobalInstall({ pkgName, tag });
2463
+ if (installResult.ok) {
2464
+ console.log(
2465
+ `
2466
+ [SILUZAN_AUTO_GLOBAL_INSTALL_OK] \u5168\u5C40\u5B89\u88C5\u5DF2\u5B8C\u6210\uFF0C\u8BF7\u91CD\u65B0\u8FD0\u884C\u672C\u547D\u4EE4\u4EE5\u52A0\u8F7D\u65B0\u7248\u672C ${pkgName}@${tag}\u3002
2467
+ `
2468
+ );
2469
+ } else {
2470
+ console.log(
2471
+ `
2472
+ [SILUZAN_AUTO_GLOBAL_INSTALL_FAILED] \u81EA\u52A8\u5168\u5C40\u5B89\u88C5\u5931\u8D25\uFF1A${installResult.stderr ?? "unknown"}
2473
+ \u8BF7\u624B\u52A8\u6267\u884C\uFF1Anpm install -g ${pkgName}@${tag}
2474
+ \u6216\uFF1A${binName} update
2475
+ ` + (forceUpdateExtra ? forceUpdateExtra + "\n" : "")
2476
+ );
2477
+ }
2438
2478
  return;
2439
2479
  }
2440
2480
  if (latest && isNewer(current, latest)) {
@@ -16403,7 +16443,7 @@ async function runAccountShareDetail(opts) {
16403
16443
 
16404
16444
  // src/commands/account-manage/oauth.ts
16405
16445
  init_auth();
16406
- import { spawn } from "child_process";
16446
+ import { spawn as spawn2 } from "child_process";
16407
16447
  function toApiMediaType(media) {
16408
16448
  return media === "Meta" ? "FacebookAds" : media;
16409
16449
  }
@@ -16414,17 +16454,17 @@ function tryOpenBrowser(url) {
16414
16454
  return false;
16415
16455
  }
16416
16456
  if (process.platform === "win32") {
16417
- const child = spawn("rundll32", ["url.dll,FileProtocolHandler", parsed.toString()], {
16457
+ const child = spawn2("rundll32", ["url.dll,FileProtocolHandler", parsed.toString()], {
16418
16458
  detached: true,
16419
16459
  stdio: "ignore",
16420
16460
  windowsHide: true
16421
16461
  });
16422
16462
  child.unref();
16423
16463
  } else if (process.platform === "darwin") {
16424
- const child = spawn("open", [parsed.toString()], { detached: true, stdio: "ignore" });
16464
+ const child = spawn2("open", [parsed.toString()], { detached: true, stdio: "ignore" });
16425
16465
  child.unref();
16426
16466
  } else {
16427
- const child = spawn("xdg-open", [parsed.toString()], { detached: true, stdio: "ignore" });
16467
+ const child = spawn2("xdg-open", [parsed.toString()], { detached: true, stdio: "ignore" });
16428
16468
  child.unref();
16429
16469
  }
16430
16470
  return true;
@@ -26,7 +26,7 @@ allowed-tools: Bash(siluzan-tso:*) Read Write
26
26
 
27
27
  Windows 注意:部分 Agent 客户端通过 PowerShell / cmd 代执行命令时存在兼容性问题。若上述命令异常失败,请先安装 [Git for Windows](https://git-scm.com/download/win),然后在 Git Bash 中执行 macOS / Linux / WSL 的 Bash 安装命令。
28
28
 
29
- 参照 `references/setup.md` 完成安装与配置。
29
+ 参照 `references/setup.md` 完成安装与配置。**需登录或我方 401 换凭据时,优先引导「手机号 + 验证码」**(`send-login-code` → `login --phone --code`),详见 `references/setup.md` 登录优先级说明。
30
30
 
31
31
  ---
32
32
 
@@ -34,7 +34,7 @@ Windows 注意:部分 Agent 客户端通过 PowerShell / cmd 代执行命令
34
34
 
35
35
  | 文档 | 功能 |
36
36
  |------|------|
37
- | `references/setup.md` | 安装、登录、配置、环境切换、更新 |
37
+ | `references/setup.md` | 安装、**登录(手机验证码优先)**、配置、环境切换、更新 |
38
38
  | `references/workflows.md` | 多步骤业务流程、跨命令串联 |
39
39
  | `references/tips.md` | **Agent 拉数一律 `--json-out`**(目录或 `*.json` 文件)+ 读 `cli-manifest[-<查询id>].json` / 各 `<section>[-<查询id>].json` + **`*.outline.txt`**(TS 式类型,**几百字节,描述完整字段结构**——写聚合脚本前先读它而不是 `Read` 整个 JSON,省 2~3 个数量级 context);stdout 一行摘要含 `manifestFile` / `writtenFiles` / `outlineFile` 等 |
40
40
  | `references/accounts.md` | 账户列表、余额、消耗、开户记录、授权/解绑/分享/MCC/BC/BM/邮箱授权 |
@@ -147,7 +147,7 @@ Windows 注意:部分 Agent 客户端通过 PowerShell / cmd 代执行命令
147
147
  2. 中断后**必须**用 `resume --run-id <id>` 续跑,**禁止**重新 `run`。
148
148
  3. stdout 始终是单行 JSON(`kind=siluzan-tso-batch-summary`);进度读 `progress.json`、轨迹读 `state/tasks.jsonl`。
149
149
  4. 退出码:`0` 全成功 / `2` 部分成功 / `3` 全失败或 Token 失效 / `4` 用法错误。
150
- 5. 401 响应 → 整批终止 + `tokenInvalidated:true`,提示用户重新登录`references/setup.md` 后再 resume
150
+ 5. 401 响应 → 整批终止 + `tokenInvalidated:true`,提示用户按 `references/setup.md` **优先手机验证码**重新登录后再 `resume`。
151
151
 
152
152
  若无批量命令(如 117 个 Bing 账户剩余天数计算):先 `list-accounts --json-out <dir>` 一次性拿全量 → `node -e` 本地计算 → 只对命中账户做后续操作。
153
153
 
@@ -244,7 +244,7 @@ siluzan-tso accounts-digest -m Google -a id1,id2,... --start <S> --end <D> --jso
244
244
  ### 常见 HTTP 状态码
245
245
 
246
246
  - **400**:参数错误,查看对应 reference 或用 `-h` 了解命令用法
247
- - **401**:平台方返回则需用户重新授权;我方返回则让用户执行 `siluzan-tso login`
247
+ - **401**:平台方返回则需用户重新授权;**我方凭据失效**则优先 **`send-login-code` + `login --phone --code`**(或 TTY 下 `siluzan-tso login` / `config set …`),见 `references/setup.md`
248
248
  - **500**:服务可能正在部署/升级,建议提交给 Siluzan 相关人员
249
249
 
250
250
  ### 报告模板外部资源
@@ -1,5 +1,5 @@
1
1
  {
2
2
  "slug": "siluzan-tso",
3
- "version": "1.1.18-beta.5",
4
- "publishedAt": 1778322175468
3
+ "version": "1.1.18-beta.6",
4
+ "publishedAt": 1778324246028
5
5
  }
@@ -1,7 +1,5 @@
1
1
  # 账户管理命令详解
2
2
 
3
- > 所属 skill:`siluzan-tso`。通用选项 `--token <token>` 可覆盖配置文件中的 Token(通常无需传,直接使用 `siluzan-tso login` 保存的配置)。
4
-
5
3
  ---
6
4
 
7
5
  ## list-accounts — 查询广告账户列表
@@ -40,8 +40,11 @@ siluzan-tso init -d /path/to-your/skills # 写入自定义目录
40
40
 
41
41
  `siluzan-tso` 与 `siluzan-cso` **共用同一份凭据**,存储在 `~/.siluzan/config.json`,配置一次两个 CLI 均可使用。
42
42
 
43
+ > **登录方式优先级**
44
+ > 1. **首选**:**手机号 + 短信验证码**两段式(`send-login-code` → `login --phone --code`)——无 TTY 不卡死、不依赖浏览器里复制 API Key,**对话式 AI / OpenClaw / CI 日志旁路**均适用。
43
45
 
44
- ### 通过手机号 + 验证码登录(对话式 AI 推荐)
46
+
47
+ ### 通过手机号 + 验证码登录(**首选**;对话式 AI / 无 TTY 与各 Agent 环境)
45
48
 
46
49
  **两段式调用**,专为 AI Agent 设计——任何一步都不会进入交互等待,绝不会卡住 stdout。
47
50
  拆分后单一职责:第 1 步只发码;第 2 步只用 code 换 API Key。这样 Agent 不会因为"看到 stdout 卡住就重试"而触发短信轰炸。
@@ -51,13 +54,12 @@ siluzan-tso init -d /path/to-your/skills # 写入自定义目录
51
54
  | 1 | `siluzan-tso send-login-code --phone <手机号>` | 仅向手机发送 6 位验证码 |
52
55
  | 2 | `siluzan-tso login --phone <手机号> --code <验证码>` | 用 code 完成登录并自动签发 API Key 写入 `~/.siluzan/config.json` |
53
56
 
54
- ## 其他方式登录
57
+ ## 其它登录方式(TTY 交互 / 已有 API Key / JWT)
58
+
55
59
  ```bash
56
- siluzan-tso login # 交互式登录,按提示创建 API Key 后粘贴
60
+ siluzan-tso login # 交互式登录(需 TTY),按提示创建 API Key 后粘贴
57
61
  siluzan-tso login --api-key <YOUR_API_KEY> # 直接设置 API Key(跳过交互)
58
- siluzan-tso send-login-code --phone 138xxxx # 两段式登录第 1 步:发送短信验证码
59
- siluzan-tso login --phone 138xxxx --code 123456 # 两段式登录第 2 步:用验证码完成登录
60
- siluzan-tso config set --api-key <Key> # 或通过 config set 直接写入
62
+ siluzan-tso config set --api-key <Key> # config 直接写入
61
63
  siluzan-tso config set --token <Token> # 备用:设置 JWT Token
62
64
  ```
63
65
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "siluzan-tso-cli",
3
- "version": "1.1.18-beta.5",
3
+ "version": "1.1.18-beta.6",
4
4
  "description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
5
5
  "keywords": [
6
6
  "ad-account",