siluzan-tso-cli 1.0.0-beta.20 → 1.0.0-beta.22
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 +279 -161
- package/dist/skill/SKILL.md +23 -0
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/references/setup.md +8 -24
- package/package.json +4 -2
- package/scripts/postinstall.mjs +5 -0
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
|
|
|
20
20
|
siluzan-tso init --force # 强制覆盖已存在文件
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
> **注意**:当前为测试版(1.0.0-beta.
|
|
23
|
+
> **注意**:当前为测试版(1.0.0-beta.22),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
24
24
|
|
|
25
25
|
| 助手 | 建议 `--ai` |
|
|
26
26
|
|------|-------------|
|
package/dist/index.js
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
3
|
// src/index.ts
|
|
4
|
-
import * as
|
|
5
|
-
import * as
|
|
4
|
+
import * as fs9 from "fs";
|
|
5
|
+
import * as path10 from "path";
|
|
6
6
|
import { fileURLToPath as fileURLToPath3 } from "url";
|
|
7
7
|
import { Command } from "commander";
|
|
8
8
|
|
|
@@ -183,6 +183,10 @@ function getCurrentVersion(importMetaUrl) {
|
|
|
183
183
|
return "0.0.0";
|
|
184
184
|
}
|
|
185
185
|
}
|
|
186
|
+
function npmDistTagForCurrentVersion(version) {
|
|
187
|
+
const v = version.trim().replace(/^v/i, "");
|
|
188
|
+
return /^\d+\.\d+\.\d+$/.test(v) ? "latest" : "beta";
|
|
189
|
+
}
|
|
186
190
|
function isNewer(a, b) {
|
|
187
191
|
const parse = (v) => {
|
|
188
192
|
const [base, pre] = v.replace(/^v/, "").split("-beta.");
|
|
@@ -485,12 +489,12 @@ async function writeSkillFilesToDir(destDir, skillFiles, force) {
|
|
|
485
489
|
return anyWritten;
|
|
486
490
|
}
|
|
487
491
|
function saveInstalledTargets(entries) {
|
|
488
|
-
const
|
|
492
|
+
const CONFIG_FILE4 = path4.join(os2.homedir(), ".siluzan", "config.json");
|
|
489
493
|
try {
|
|
490
|
-
fsSync.mkdirSync(path4.dirname(
|
|
494
|
+
fsSync.mkdirSync(path4.dirname(CONFIG_FILE4), { recursive: true });
|
|
491
495
|
let existing = {};
|
|
492
|
-
if (fsSync.existsSync(
|
|
493
|
-
existing = JSON.parse(fsSync.readFileSync(
|
|
496
|
+
if (fsSync.existsSync(CONFIG_FILE4)) {
|
|
497
|
+
existing = JSON.parse(fsSync.readFileSync(CONFIG_FILE4, "utf8"));
|
|
494
498
|
}
|
|
495
499
|
const prev = Array.isArray(existing.tsoInstalledTargets) ? existing.tsoInstalledTargets : [];
|
|
496
500
|
const merged = /* @__PURE__ */ new Map();
|
|
@@ -498,12 +502,12 @@ function saveInstalledTargets(entries) {
|
|
|
498
502
|
merged.set(`${e.target}::${e.cwd}`, e);
|
|
499
503
|
}
|
|
500
504
|
fsSync.writeFileSync(
|
|
501
|
-
|
|
505
|
+
CONFIG_FILE4,
|
|
502
506
|
JSON.stringify({ ...existing, tsoInstalledTargets: [...merged.values()] }, null, 2),
|
|
503
507
|
"utf8"
|
|
504
508
|
);
|
|
505
509
|
if (process.platform !== "win32") {
|
|
506
|
-
fsSync.chmodSync(
|
|
510
|
+
fsSync.chmodSync(CONFIG_FILE4, 384);
|
|
507
511
|
}
|
|
508
512
|
} catch {
|
|
509
513
|
}
|
|
@@ -534,9 +538,214 @@ async function runInit(options) {
|
|
|
534
538
|
saveInstalledTargets(installedEntries);
|
|
535
539
|
}
|
|
536
540
|
console.log("\n\u4E0B\u4E00\u6B65\uFF1A");
|
|
537
|
-
console.log("1. \u82E5\u8FD8\u672A\u767B\u5F55\uFF0C\u8BF7\u5148\u8FD0\u884C\uFF1Asiluzan-
|
|
538
|
-
console.log("2.
|
|
539
|
-
console.log("3.
|
|
541
|
+
console.log("1. \u82E5\u8FD8\u672A\u767B\u5F55\uFF0C\u8BF7\u5148\u8FD0\u884C\uFF1Asiluzan-tso login \uFF08siluzan-tso \u4E0E siluzan-cso \u5171\u7528\u540C\u4E00 Token\uFF09");
|
|
542
|
+
console.log("2. CLI \u5347\u7EA7\u540E\u5237\u65B0 Skill\uFF1Asiluzan-tso update\uFF08\u6216 siluzan-tso init --ai \u2026 --force\uFF09");
|
|
543
|
+
console.log("3. OpenClaw \u5168\u5C40\u6280\u80FD\u82E5\u672A\u751F\u6548\uFF0C\u8BF7\u5728 ~/.openclaw/openclaw.json \u7684 skills.load.extraDirs \u4E2D\u52A0\u5165\u6280\u80FD\u7236\u76EE\u5F55\u3002");
|
|
544
|
+
console.log("4. \u6216\u8005\u624B\u52A8\u5728siluzan-tso\u7684\u5B89\u88C5\u76EE\u5F55\u4E0B\u6267\u884C\uFF1Anpm install -g siluzan-tso-cli");
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
// src/commands/update.ts
|
|
548
|
+
import * as fs6 from "fs";
|
|
549
|
+
import * as path6 from "path";
|
|
550
|
+
import * as os4 from "os";
|
|
551
|
+
import { spawnSync } from "child_process";
|
|
552
|
+
|
|
553
|
+
// src/utils/version.ts
|
|
554
|
+
import * as fs5 from "fs";
|
|
555
|
+
import * as path5 from "path";
|
|
556
|
+
import * as os3 from "os";
|
|
557
|
+
var PKG_NAME = "siluzan-tso-cli";
|
|
558
|
+
var CONFIG_FILE2 = path5.join(os3.homedir(), ".siluzan", "config.json");
|
|
559
|
+
function getCurrentVersion2() {
|
|
560
|
+
return getCurrentVersion(import.meta.url);
|
|
561
|
+
}
|
|
562
|
+
function readConfigRaw() {
|
|
563
|
+
try {
|
|
564
|
+
return JSON.parse(fs5.readFileSync(CONFIG_FILE2, "utf8"));
|
|
565
|
+
} catch {
|
|
566
|
+
return {};
|
|
567
|
+
}
|
|
568
|
+
}
|
|
569
|
+
function writeConfigRaw(data) {
|
|
570
|
+
try {
|
|
571
|
+
fs5.mkdirSync(path5.dirname(CONFIG_FILE2), { recursive: true });
|
|
572
|
+
fs5.writeFileSync(CONFIG_FILE2, JSON.stringify(data, null, 2), "utf8");
|
|
573
|
+
if (process.platform !== "win32") {
|
|
574
|
+
fs5.chmodSync(CONFIG_FILE2, 384);
|
|
575
|
+
}
|
|
576
|
+
} catch {
|
|
577
|
+
}
|
|
578
|
+
}
|
|
579
|
+
async function fetchVersionByTag(tag, cacheKey, cfg) {
|
|
580
|
+
const hours24 = 24 * 60 * 60 * 1e3;
|
|
581
|
+
if (cfg._tsoLastVersionCheck && cfg[cacheKey]) {
|
|
582
|
+
const lastCheck = new Date(cfg._tsoLastVersionCheck).getTime();
|
|
583
|
+
if (Date.now() - lastCheck < hours24) {
|
|
584
|
+
return cfg[cacheKey];
|
|
585
|
+
}
|
|
586
|
+
}
|
|
587
|
+
return fetchNpmVersion(PKG_NAME, tag);
|
|
588
|
+
}
|
|
589
|
+
async function notifyIfOutdated() {
|
|
590
|
+
try {
|
|
591
|
+
const current = getCurrentVersion2();
|
|
592
|
+
const tag = npmDistTagForCurrentVersion(current);
|
|
593
|
+
const isBeta = tag === "beta";
|
|
594
|
+
const latestCacheKey = isBeta ? "_tsoLatestBeta" : "_tsoLatestStable";
|
|
595
|
+
const minCacheKey = isBeta ? "_tsoMinRequiredBeta" : "_tsoMinRequiredStable";
|
|
596
|
+
const minTag = isBeta ? "min-required-beta" : "min-required";
|
|
597
|
+
const cfg = readConfigRaw();
|
|
598
|
+
const [latest, minRequired] = await Promise.all([
|
|
599
|
+
fetchVersionByTag(tag, latestCacheKey, cfg),
|
|
600
|
+
fetchVersionByTag(minTag, minCacheKey, cfg)
|
|
601
|
+
]);
|
|
602
|
+
writeConfigRaw({
|
|
603
|
+
...cfg,
|
|
604
|
+
_tsoLastVersionCheck: (/* @__PURE__ */ new Date()).toISOString(),
|
|
605
|
+
...latest ? { [latestCacheKey]: latest } : {},
|
|
606
|
+
...minRequired ? { [minCacheKey]: minRequired } : {}
|
|
607
|
+
});
|
|
608
|
+
const lastNotified = cfg._tsoLastNotified ? new Date(cfg._tsoLastNotified).getTime() : 0;
|
|
609
|
+
if (Date.now() - lastNotified < 24 * 60 * 60 * 1e3) return;
|
|
610
|
+
const tagLabel = isBeta ? "\uFF08\u6D4B\u8BD5\u7248\uFF09" : "\uFF08\u6B63\u5F0F\u7248\uFF09";
|
|
611
|
+
if (minRequired && isNewer(current, minRequired)) {
|
|
612
|
+
writeConfigRaw({ ...cfg, _tsoLastNotified: (/* @__PURE__ */ new Date()).toISOString() });
|
|
613
|
+
console.log(
|
|
614
|
+
`
|
|
615
|
+
[SILUZAN_FORCE_UPDATE] \u5F53\u524D\u7248\u672C ${current} \u5DF2\u8FC7\u671F\uFF0C\u6700\u4F4E\u8981\u6C42\u7248\u672C ${minRequired}${tagLabel}
|
|
616
|
+
\u26D4 \u5FC5\u987B\u5148\u5347\u7EA7\u624D\u80FD\u7EE7\u7EED\u4F7F\u7528\uFF0CAgent \u8BF7\u7ACB\u5373\u6267\u884C\uFF1Asiluzan-tso update
|
|
617
|
+
\u6216\u624B\u52A8\uFF1Anpm install -g ${PKG_NAME}@${tag}
|
|
618
|
+
`
|
|
619
|
+
);
|
|
620
|
+
return;
|
|
621
|
+
}
|
|
622
|
+
if (latest && isNewer(current, latest)) {
|
|
623
|
+
writeConfigRaw({ ...cfg, _tsoLastNotified: (/* @__PURE__ */ new Date()).toISOString() });
|
|
624
|
+
console.log(
|
|
625
|
+
`
|
|
626
|
+
[SILUZAN_UPDATE_AVAILABLE] \u53D1\u73B0\u65B0\u7248\u672C ${latest}${tagLabel}\uFF08\u5F53\u524D ${current}\uFF09
|
|
627
|
+
\u{1F4A1} Agent \u8BF7\u7ACB\u5373\u6267\u884C\uFF1Asiluzan-tso update
|
|
628
|
+
\u6216\u624B\u52A8\uFF1Anpm install -g ${PKG_NAME}@${tag}
|
|
629
|
+
`
|
|
630
|
+
);
|
|
631
|
+
}
|
|
632
|
+
} catch {
|
|
633
|
+
}
|
|
634
|
+
}
|
|
635
|
+
async function fetchLatestVersion() {
|
|
636
|
+
const tag = npmDistTagForCurrentVersion(getCurrentVersion2());
|
|
637
|
+
return fetchNpmVersion(PKG_NAME, tag);
|
|
638
|
+
}
|
|
639
|
+
|
|
640
|
+
// src/commands/update.ts
|
|
641
|
+
var CONFIG_FILE3 = path6.join(os4.homedir(), ".siluzan", "config.json");
|
|
642
|
+
var PKG_NAME2 = "siluzan-tso-cli";
|
|
643
|
+
function readInstalledTargets() {
|
|
644
|
+
try {
|
|
645
|
+
const cfg = JSON.parse(fs6.readFileSync(CONFIG_FILE3, "utf8"));
|
|
646
|
+
return Array.isArray(cfg.tsoInstalledTargets) ? cfg.tsoInstalledTargets : [];
|
|
647
|
+
} catch {
|
|
648
|
+
return [];
|
|
649
|
+
}
|
|
650
|
+
}
|
|
651
|
+
function isNpmGlobalInstall() {
|
|
652
|
+
try {
|
|
653
|
+
const result = spawnSync("npm", ["list", "-g", "--depth=0", PKG_NAME2], {
|
|
654
|
+
encoding: "utf8",
|
|
655
|
+
stdio: "pipe"
|
|
656
|
+
});
|
|
657
|
+
return Boolean(result.stdout?.includes(PKG_NAME2));
|
|
658
|
+
} catch {
|
|
659
|
+
return false;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
async function runUpdate(options) {
|
|
663
|
+
const current = getCurrentVersion2();
|
|
664
|
+
console.log(`
|
|
665
|
+
\u5F53\u524D\u7248\u672C\uFF1A${current}`);
|
|
666
|
+
console.log("\u6B63\u5728\u67E5\u8BE2 npm registry \u2026");
|
|
667
|
+
const latest = await fetchLatestVersion();
|
|
668
|
+
if (!latest) {
|
|
669
|
+
console.warn("\u26A0\uFE0F \u65E0\u6CD5\u8BBF\u95EE npm registry\uFF0C\u8BF7\u68C0\u67E5\u7F51\u7EDC\u540E\u91CD\u8BD5\u3002");
|
|
670
|
+
console.warn(" \u82E5\u9700\u5F3A\u5236\u91CD\u65B0\u5B89\u88C5\u5F53\u524D\u7248\u672C\uFF0C\u52A0 --force \u53C2\u6570\u3002");
|
|
671
|
+
if (!options.force) {
|
|
672
|
+
process.exit(1);
|
|
673
|
+
}
|
|
674
|
+
} else {
|
|
675
|
+
console.log(`\u6700\u65B0\u7248\u672C\uFF1A${latest}`);
|
|
676
|
+
}
|
|
677
|
+
const shouldUpdate = options.force || (latest ? isNewer(current, latest) : false);
|
|
678
|
+
if (!shouldUpdate && latest) {
|
|
679
|
+
console.log("\n\u2705 \u5DF2\u662F\u6700\u65B0\u7248\u672C\uFF0C\u65E0\u9700\u66F4\u65B0\u3002");
|
|
680
|
+
console.log(" \u5982\u9700\u4EC5\u5237\u65B0 Skill \u6587\u4EF6\uFF0C\u53EF\u52A0 --force \u53C2\u6570\u3002");
|
|
681
|
+
return;
|
|
682
|
+
}
|
|
683
|
+
const targetVersion = latest ?? current;
|
|
684
|
+
if (shouldUpdate && latest) {
|
|
685
|
+
console.log(`
|
|
686
|
+
\u2B06\uFE0F \u6B63\u5728\u66F4\u65B0 CLI \u81F3 ${targetVersion} \u2026`);
|
|
687
|
+
} else if (options.force) {
|
|
688
|
+
console.log(`
|
|
689
|
+
\u{1F504} \u5F3A\u5236\u91CD\u65B0\u5B89\u88C5\u5F53\u524D\u7248\u672C ${current} \u2026`);
|
|
690
|
+
}
|
|
691
|
+
if (isNpmGlobalInstall()) {
|
|
692
|
+
try {
|
|
693
|
+
const result = spawnSync(
|
|
694
|
+
"npm",
|
|
695
|
+
["install", "-g", `${PKG_NAME2}@${targetVersion}`],
|
|
696
|
+
{ stdio: "inherit", shell: false }
|
|
697
|
+
);
|
|
698
|
+
if (result.status !== 0) {
|
|
699
|
+
throw new Error(`npm install \u9000\u51FA\u7801\uFF1A${result.status ?? "unknown"}`);
|
|
700
|
+
}
|
|
701
|
+
console.log("\n\u2705 CLI \u66F4\u65B0\u6210\u529F\uFF01");
|
|
702
|
+
} catch (e) {
|
|
703
|
+
console.error(`
|
|
704
|
+
\u274C npm \u5B89\u88C5\u5931\u8D25\uFF1A${e.message}`);
|
|
705
|
+
console.error(" \u5982\u679C\u662F\u6743\u9650\u95EE\u9898\uFF0C\u5C1D\u8BD5\u52A0 sudo\uFF08Unix\uFF09\u6216\u4EE5\u7BA1\u7406\u5458\u8EAB\u4EFD\u8FD0\u884C\u3002");
|
|
706
|
+
process.exit(1);
|
|
707
|
+
}
|
|
708
|
+
} else {
|
|
709
|
+
console.log(
|
|
710
|
+
"\n\u26A0\uFE0F \u68C0\u6D4B\u5230 CLI \u5E76\u975E\u901A\u8FC7 npm \u5168\u5C40\u5B89\u88C5\uFF08\u53EF\u80FD\u662F\u672C\u5730\u5F00\u53D1\u6A21\u5F0F\uFF09\u3002\n \u8DF3\u8FC7 npm \u66F4\u65B0\uFF0C\u4EC5\u91CD\u65B0\u521D\u59CB\u5316 Skill \u6587\u4EF6\u3002\n \u82E5\u9700\u6B63\u5F0F\u5B89\u88C5\uFF0C\u8BF7\u8FD0\u884C\uFF1Anpm install -g siluzan-tso-cli"
|
|
711
|
+
);
|
|
712
|
+
}
|
|
713
|
+
if (options.skipInit) return;
|
|
714
|
+
const targets = readInstalledTargets();
|
|
715
|
+
if (targets.length === 0) {
|
|
716
|
+
console.log(
|
|
717
|
+
"\n\u26A0\uFE0F \u672A\u627E\u5230\u4E0A\u6B21\u5B89\u88C5\u8BB0\u5F55\uFF08tsoInstalledTargets\uFF09\u3002\n \u8BF7\u624B\u52A8\u8FD0\u884C\uFF1Asiluzan-tso init --ai <\u5E73\u53F0> --force\n \u4EE5\u5237\u65B0 Skill \u6587\u4EF6\u3002"
|
|
718
|
+
);
|
|
719
|
+
return;
|
|
720
|
+
}
|
|
721
|
+
console.log(`
|
|
722
|
+
\u{1F504} \u6B63\u5728\u66F4\u65B0 ${targets.length} \u5904 Skill \u5B89\u88C5\u4F4D\u7F6E \u2026`);
|
|
723
|
+
for (const entry of targets) {
|
|
724
|
+
const label = entry.target === "custom" ? entry.dir ?? "unknown" : entry.target;
|
|
725
|
+
const cwd = entry.cwd || os4.homedir();
|
|
726
|
+
console.log(`
|
|
727
|
+
[${label}]`);
|
|
728
|
+
try {
|
|
729
|
+
if (entry.target === "custom" && entry.dir) {
|
|
730
|
+
await runInit({
|
|
731
|
+
cwd: os4.homedir(),
|
|
732
|
+
aiTargets: "",
|
|
733
|
+
dir: entry.dir,
|
|
734
|
+
force: true
|
|
735
|
+
});
|
|
736
|
+
} else {
|
|
737
|
+
await runInit({
|
|
738
|
+
cwd,
|
|
739
|
+
aiTargets: entry.target,
|
|
740
|
+
force: true
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
} catch (e) {
|
|
744
|
+
console.error(` \u274C \u66F4\u65B0\u5931\u8D25\uFF1A${e.message}`);
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
console.log("\n\u2705 \u5168\u90E8 Skill \u6587\u4EF6\u5DF2\u5237\u65B0\u3002");
|
|
748
|
+
console.log(" \u5982\u679C AI \u52A9\u624B\u6B63\u5728\u8FD0\u884C\uFF0C\u5EFA\u8BAE\u91CD\u542F\u4EE5\u4F7F\u65B0 Skill \u6587\u4EF6\u751F\u6548\u3002\n");
|
|
540
749
|
}
|
|
541
750
|
|
|
542
751
|
// src/commands/list-accounts.ts
|
|
@@ -1446,19 +1655,19 @@ async function runTransferList(opts) {
|
|
|
1446
1655
|
}
|
|
1447
1656
|
|
|
1448
1657
|
// src/commands/invoice.ts
|
|
1449
|
-
import * as
|
|
1450
|
-
import * as
|
|
1451
|
-
import * as
|
|
1658
|
+
import * as fs7 from "fs";
|
|
1659
|
+
import * as path7 from "path";
|
|
1660
|
+
import * as os5 from "os";
|
|
1452
1661
|
async function ensureDataPermission(config) {
|
|
1453
1662
|
if (config.dataPermission) return config;
|
|
1454
1663
|
if (!config.mainApiUrl) return config;
|
|
1455
1664
|
const dp = await fetchDataPermission(config.mainApiUrl, config.authToken);
|
|
1456
1665
|
if (!dp) return config;
|
|
1457
|
-
const configPath =
|
|
1666
|
+
const configPath = path7.join(os5.homedir(), ".siluzan", "config.json");
|
|
1458
1667
|
try {
|
|
1459
|
-
const raw =
|
|
1668
|
+
const raw = fs7.existsSync(configPath) ? JSON.parse(fs7.readFileSync(configPath, "utf8")) : {};
|
|
1460
1669
|
raw.dataPermission = dp;
|
|
1461
|
-
|
|
1670
|
+
fs7.writeFileSync(configPath, JSON.stringify(raw, null, 2), "utf8");
|
|
1462
1671
|
} catch {
|
|
1463
1672
|
}
|
|
1464
1673
|
return { ...config, dataPermission: dp };
|
|
@@ -3165,8 +3374,8 @@ async function runOptimizeChildren(opts) {
|
|
|
3165
3374
|
}
|
|
3166
3375
|
|
|
3167
3376
|
// src/commands/forewarning.ts
|
|
3168
|
-
import
|
|
3169
|
-
import
|
|
3377
|
+
import os6 from "os";
|
|
3378
|
+
import path8 from "path";
|
|
3170
3379
|
import QRCode from "qrcode";
|
|
3171
3380
|
import open from "open";
|
|
3172
3381
|
var VALID_MEDIA_TYPES7 = ["Google", "TikTok"];
|
|
@@ -3373,7 +3582,7 @@ async function runForewarningNotifyAccounts(opts) {
|
|
|
3373
3582
|
console.log(" \u901A\u77E5\u6E20\u9053\uFF1A\u4E1D\u8DEF\u8D5E\u5E73\u53F0\u5FAE\u4FE1\u670D\u52A1\u53F7\uFF08\u9700\u626B\u7801\u5173\u6CE8\u540E\u624D\u80FD\u6536\u5230\u9884\u8B66\u901A\u77E5\uFF09\n");
|
|
3374
3583
|
if (qrLink) {
|
|
3375
3584
|
try {
|
|
3376
|
-
const imgPath =
|
|
3585
|
+
const imgPath = path8.join(os6.tmpdir(), "siluzan-wechat-qr.png");
|
|
3377
3586
|
await QRCode.toFile(imgPath, qrLink, { width: 300 });
|
|
3378
3587
|
await open(imgPath);
|
|
3379
3588
|
console.log(` \u{1F4F7} \u4E8C\u7EF4\u7801\u5DF2\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\uFF0C\u8BF7\u7528\u624B\u673A\u5FAE\u4FE1\u626B\u7801\u5173\u6CE8"\u4E1D\u8DEF\u8D5E\u5E73\u53F0"\u670D\u52A1\u53F7
|
|
@@ -5972,8 +6181,8 @@ async function runAccountBmBind(opts) {
|
|
|
5972
6181
|
}
|
|
5973
6182
|
|
|
5974
6183
|
// src/commands/open-account.ts
|
|
5975
|
-
import * as
|
|
5976
|
-
import * as
|
|
6184
|
+
import * as fs8 from "fs";
|
|
6185
|
+
import * as path9 from "path";
|
|
5977
6186
|
import * as readline from "readline/promises";
|
|
5978
6187
|
import { stdin as stdinStream, stdout as stdoutStream } from "process";
|
|
5979
6188
|
async function runListAdvertiserGroups(opts) {
|
|
@@ -6101,8 +6310,6 @@ async function resolveGoogleMediaAccountGroupId(config, opts) {
|
|
|
6101
6310
|
}
|
|
6102
6311
|
const company = opts.company.trim();
|
|
6103
6312
|
const promotionLink = normalizePromotionLinkForGoogle(opts.promotionLink);
|
|
6104
|
-
const level1 = (opts.industryLevel1 ?? "").trim();
|
|
6105
|
-
const level2 = (opts.industryLevel2 ?? "").trim();
|
|
6106
6313
|
let profile;
|
|
6107
6314
|
try {
|
|
6108
6315
|
profile = await apiFetch2(
|
|
@@ -6125,7 +6332,6 @@ async function resolveGoogleMediaAccountGroupId(config, opts) {
|
|
|
6125
6332
|
const mediaAccountGroupPayload = {
|
|
6126
6333
|
advertiserName: company,
|
|
6127
6334
|
StorageProvider: storageFromGroup ?? "StorageAccount",
|
|
6128
|
-
industry: { level1, level2 },
|
|
6129
6335
|
promotionLink,
|
|
6130
6336
|
promotionType: opts.promotionType
|
|
6131
6337
|
};
|
|
@@ -6222,8 +6428,8 @@ async function runOpenAccountYandex(opts) {
|
|
|
6222
6428
|
}
|
|
6223
6429
|
}
|
|
6224
6430
|
async function uploadAttachment(filePath, apiBaseUrl, config, verbose) {
|
|
6225
|
-
const fileName =
|
|
6226
|
-
const fileBuffer =
|
|
6431
|
+
const fileName = path9.basename(filePath);
|
|
6432
|
+
const fileBuffer = fs8.readFileSync(filePath);
|
|
6227
6433
|
const mimeType = guessContentType(fileName);
|
|
6228
6434
|
const form = new FormData();
|
|
6229
6435
|
form.append("file", new Blob([fileBuffer], { type: mimeType }), fileName);
|
|
@@ -6249,7 +6455,7 @@ async function uploadAttachment(filePath, apiBaseUrl, config, verbose) {
|
|
|
6249
6455
|
return { id: data.id, fileName };
|
|
6250
6456
|
}
|
|
6251
6457
|
function guessContentType(fileName) {
|
|
6252
|
-
const ext =
|
|
6458
|
+
const ext = path9.extname(fileName).toLowerCase();
|
|
6253
6459
|
const map = {
|
|
6254
6460
|
".jpg": "image/jpeg",
|
|
6255
6461
|
".jpeg": "image/jpeg",
|
|
@@ -6262,7 +6468,7 @@ function guessContentType(fileName) {
|
|
|
6262
6468
|
}
|
|
6263
6469
|
async function runOpenAccountBing(opts) {
|
|
6264
6470
|
const config = loadConfig(opts.token);
|
|
6265
|
-
if (!
|
|
6471
|
+
if (!fs8.existsSync(opts.licenseFile)) {
|
|
6266
6472
|
console.error(`
|
|
6267
6473
|
\u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
|
|
6268
6474
|
`);
|
|
@@ -6289,9 +6495,10 @@ async function runOpenAccountBing(opts) {
|
|
|
6289
6495
|
opts.verbose,
|
|
6290
6496
|
opts.advertiserId
|
|
6291
6497
|
);
|
|
6498
|
+
const accountCount = Math.min(Math.max(opts.accountCount ?? 1, 1), 6);
|
|
6292
6499
|
const body = {
|
|
6293
6500
|
MediaAccountGroupId: magKey,
|
|
6294
|
-
AccountCount:
|
|
6501
|
+
AccountCount: accountCount,
|
|
6295
6502
|
BingCustomerInfo: {
|
|
6296
6503
|
name: opts.advertiserName,
|
|
6297
6504
|
province: opts.province,
|
|
@@ -6337,9 +6544,9 @@ async function runOpenAccountBing(opts) {
|
|
|
6337
6544
|
}
|
|
6338
6545
|
}
|
|
6339
6546
|
async function uploadToKwai(filePath, apiBaseUrl, config, verbose) {
|
|
6340
|
-
const ext =
|
|
6547
|
+
const ext = path9.extname(filePath).toLowerCase().replace(".", "").replace("jpg", "jpeg");
|
|
6341
6548
|
const imageType = ext || "jpeg";
|
|
6342
|
-
const fileBuffer =
|
|
6549
|
+
const fileBuffer = fs8.readFileSync(filePath);
|
|
6343
6550
|
const base64Image = fileBuffer.toString("base64");
|
|
6344
6551
|
const res = await apiFetch2(
|
|
6345
6552
|
`${apiBaseUrl}/KwaiAccount/Management/Upload`,
|
|
@@ -6358,7 +6565,7 @@ async function uploadToKwai(filePath, apiBaseUrl, config, verbose) {
|
|
|
6358
6565
|
}
|
|
6359
6566
|
async function runOpenAccountKwai(opts) {
|
|
6360
6567
|
const config = loadConfig(opts.token);
|
|
6361
|
-
if (!
|
|
6568
|
+
if (!fs8.existsSync(opts.licenseFile)) {
|
|
6362
6569
|
console.error(`
|
|
6363
6570
|
\u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
|
|
6364
6571
|
`);
|
|
@@ -6618,18 +6825,14 @@ async function runOpenAccountGoogle(opts) {
|
|
|
6618
6825
|
company: opts.company,
|
|
6619
6826
|
promotionLink: opts.promotionLink,
|
|
6620
6827
|
promotionType: opts.promotionType,
|
|
6621
|
-
industryLevel1: opts.industryLevel1,
|
|
6622
|
-
industryLevel2: opts.industryLevel2,
|
|
6623
6828
|
verbose: opts.verbose
|
|
6624
6829
|
});
|
|
6625
|
-
const level1 = (opts.industryLevel1 ?? "").trim();
|
|
6626
|
-
const level2 = (opts.industryLevel2 ?? "").trim();
|
|
6627
|
-
const industryStr = level1 || level2 ? `${level1}-${level2}` : "";
|
|
6628
6830
|
const promotionLinkNorm = normalizePromotionLinkForGoogle(opts.promotionLink);
|
|
6629
6831
|
const body = {
|
|
6630
|
-
accountInfo: Array.from({ length: counts }, () => ({
|
|
6832
|
+
accountInfo: Array.from({ length: counts }, (_, i) => ({
|
|
6631
6833
|
advertiser_info: {
|
|
6632
|
-
|
|
6834
|
+
// 多账户时在名称末尾追加 -1, -2 … 以便区分
|
|
6835
|
+
name: counts > 1 ? `${opts.accountName}-${i + 1}` : opts.accountName,
|
|
6633
6836
|
currency: opts.currency,
|
|
6634
6837
|
timezone: opts.timezone,
|
|
6635
6838
|
accounttype: "Adwords",
|
|
@@ -6637,8 +6840,7 @@ async function runOpenAccountGoogle(opts) {
|
|
|
6637
6840
|
inviteduserrole: opts.inviteRole ?? "Standard"
|
|
6638
6841
|
},
|
|
6639
6842
|
customer_info: {
|
|
6640
|
-
company: opts.company.trim()
|
|
6641
|
-
industry: industryStr
|
|
6843
|
+
company: opts.company.trim()
|
|
6642
6844
|
},
|
|
6643
6845
|
qualification_info: {
|
|
6644
6846
|
promotion_link: promotionLinkNorm,
|
|
@@ -6674,8 +6876,8 @@ async function runOpenAccountGoogle(opts) {
|
|
|
6674
6876
|
}
|
|
6675
6877
|
}
|
|
6676
6878
|
async function uploadLicenseToTikTok(filePath, businessCentreType, config, verbose) {
|
|
6677
|
-
const fileName =
|
|
6678
|
-
const fileBuffer =
|
|
6879
|
+
const fileName = path9.basename(filePath);
|
|
6880
|
+
const fileBuffer = fs8.readFileSync(filePath);
|
|
6679
6881
|
const base64Image = fileBuffer.toString("base64");
|
|
6680
6882
|
const res = await apiFetch2(
|
|
6681
6883
|
`${config.apiBaseUrl}/command/media-account/tiktok/Upload`,
|
|
@@ -6697,34 +6899,16 @@ async function uploadLicenseToTikTok(filePath, businessCentreType, config, verbo
|
|
|
6697
6899
|
}
|
|
6698
6900
|
return imageId;
|
|
6699
6901
|
}
|
|
6700
|
-
async function checkUnionpayRequired(licenseNo, company, businessCentreType, config, verbose) {
|
|
6701
|
-
try {
|
|
6702
|
-
const params = new URLSearchParams({
|
|
6703
|
-
license_no: licenseNo,
|
|
6704
|
-
company_name: company,
|
|
6705
|
-
businessCentreType
|
|
6706
|
-
});
|
|
6707
|
-
const res = await apiFetch2(
|
|
6708
|
-
`${config.apiBaseUrl}/query/media-account/tiktok/TikTokAdvQuery/CheckUnionpayInfo?${params}`,
|
|
6709
|
-
config,
|
|
6710
|
-
{},
|
|
6711
|
-
verbose
|
|
6712
|
-
);
|
|
6713
|
-
return res?.data?.unionpay_verification_required === true;
|
|
6714
|
-
} catch {
|
|
6715
|
-
return false;
|
|
6716
|
-
}
|
|
6717
|
-
}
|
|
6718
6902
|
async function runOpenAccountTikTok(opts) {
|
|
6719
6903
|
const config = loadConfig(opts.token);
|
|
6720
6904
|
const bcType = opts.businessCentreType ?? "Shop";
|
|
6721
|
-
if (!
|
|
6905
|
+
if (!fs8.existsSync(opts.licenseFile)) {
|
|
6722
6906
|
console.error(`
|
|
6723
6907
|
\u274C \u8425\u4E1A\u6267\u7167\u6587\u4EF6\u4E0D\u5B58\u5728\uFF1A${opts.licenseFile}
|
|
6724
6908
|
`);
|
|
6725
6909
|
process.exit(1);
|
|
6726
6910
|
}
|
|
6727
|
-
console.log(" [1/
|
|
6911
|
+
console.log(" [1/3] \u6B63\u5728\u4E0A\u4F20\u8425\u4E1A\u6267\u7167\u5230 TikTok...");
|
|
6728
6912
|
let licenseImageId;
|
|
6729
6913
|
try {
|
|
6730
6914
|
licenseImageId = await uploadLicenseToTikTok(opts.licenseFile, bcType, config, opts.verbose);
|
|
@@ -6735,7 +6919,7 @@ async function runOpenAccountTikTok(opts) {
|
|
|
6735
6919
|
process.exit(1);
|
|
6736
6920
|
}
|
|
6737
6921
|
console.log(` TikTok license_image_id: ${licenseImageId}`);
|
|
6738
|
-
console.log(" [2/
|
|
6922
|
+
console.log(" [2/3] \u6B63\u5728\u4E0A\u4F20\u8425\u4E1A\u6267\u7167\u5230 Siluzan \u5B58\u6863...");
|
|
6739
6923
|
let siluzanImageId = "";
|
|
6740
6924
|
try {
|
|
6741
6925
|
const uploaded = await uploadAttachment(opts.licenseFile, config.apiBaseUrl, config, opts.verbose);
|
|
@@ -6744,7 +6928,7 @@ async function runOpenAccountTikTok(opts) {
|
|
|
6744
6928
|
} catch (err) {
|
|
6745
6929
|
console.warn(` \u26A0\uFE0F Siluzan \u5B58\u6863\u4E0A\u4F20\u5931\u8D25\uFF08\u4E0D\u5F71\u54CD\u5F00\u6237\uFF09\uFF1A${err instanceof Error ? err.message : String(err)}`);
|
|
6746
6930
|
}
|
|
6747
|
-
console.log(" [3/
|
|
6931
|
+
console.log(" [3/3] \u6B63\u5728\u5173\u8054\u5E7F\u544A\u4E3B\u7EC4...");
|
|
6748
6932
|
const magKey = await resolveGenericMagKey(
|
|
6749
6933
|
config,
|
|
6750
6934
|
opts.company,
|
|
@@ -6760,19 +6944,11 @@ async function runOpenAccountTikTok(opts) {
|
|
|
6760
6944
|
opts.verbose,
|
|
6761
6945
|
opts.advertiserId
|
|
6762
6946
|
);
|
|
6763
|
-
console.log(" [4/4] \u6B63\u5728\u68C0\u67E5\u6CD5\u4EBA\u9A8C\u8BC1\u8981\u6C42...");
|
|
6764
|
-
const needUnionpay = await checkUnionpayRequired(opts.licenseNo, opts.company, bcType, config, opts.verbose);
|
|
6765
|
-
if (needUnionpay && (!opts.representativeName || !opts.representativeId)) {
|
|
6766
|
-
console.error(
|
|
6767
|
-
"\n\u274C \u8BE5\u8425\u4E1A\u6267\u7167\u9700\u8981\u586B\u5199\u6CD5\u4EBA\u94F6\u8054\u9A8C\u8BC1\u4FE1\u606F\uFF0C\u8BF7\u8FFD\u52A0\u4EE5\u4E0B\u53C2\u6570\u518D\u91CD\u8BD5\uFF1A\n --representative-name <\u6CD5\u4EBA\u59D3\u540D>\n --representative-id <\u8EAB\u4EFD\u8BC1\u53F7>\n --unionpay-account <\u94F6\u8054\u8D26\u53F7>\n --representative-phone <\u624B\u673A\u53F7>\n"
|
|
6768
|
-
);
|
|
6769
|
-
process.exit(1);
|
|
6770
|
-
}
|
|
6771
6947
|
const counts = Math.min(Math.max(opts.counts ?? 1, 1), 10);
|
|
6772
6948
|
const singleAccountInfo = {
|
|
6773
6949
|
advertiser_info: {
|
|
6774
6950
|
name: opts.accountName,
|
|
6775
|
-
currency:
|
|
6951
|
+
currency: "USD",
|
|
6776
6952
|
timezone: opts.timezone
|
|
6777
6953
|
},
|
|
6778
6954
|
customer_info: {
|
|
@@ -6784,18 +6960,23 @@ async function runOpenAccountTikTok(opts) {
|
|
|
6784
6960
|
promotion_link: opts.promotionLink,
|
|
6785
6961
|
license_no: opts.licenseNo,
|
|
6786
6962
|
license_image_id: licenseImageId
|
|
6963
|
+
},
|
|
6964
|
+
representative_info: {
|
|
6965
|
+
representative_name: opts.representativeName,
|
|
6966
|
+
representative_id: opts.representativeId,
|
|
6967
|
+
unionpay_account: opts.unionpayAccount,
|
|
6968
|
+
representative_phone_number: opts.representativePhone
|
|
6787
6969
|
}
|
|
6788
6970
|
};
|
|
6789
|
-
if (needUnionpay && opts.representativeName) {
|
|
6790
|
-
singleAccountInfo.representative_info = {
|
|
6791
|
-
representative_name: opts.representativeName,
|
|
6792
|
-
representative_id: opts.representativeId ?? "",
|
|
6793
|
-
unionpay_account: opts.unionpayAccount ?? "",
|
|
6794
|
-
representative_phone_number: opts.representativePhone ?? ""
|
|
6795
|
-
};
|
|
6796
|
-
}
|
|
6797
6971
|
const body = {
|
|
6798
|
-
accountInfo: Array.from({ length: counts }, () => ({
|
|
6972
|
+
accountInfo: Array.from({ length: counts }, (_, i) => ({
|
|
6973
|
+
...singleAccountInfo,
|
|
6974
|
+
advertiser_info: {
|
|
6975
|
+
...singleAccountInfo.advertiser_info,
|
|
6976
|
+
// 多账户时在名称末尾追加 -1, -2 … 以便区分
|
|
6977
|
+
name: counts > 1 ? `${opts.accountName}-${i + 1}` : opts.accountName
|
|
6978
|
+
}
|
|
6979
|
+
})),
|
|
6799
6980
|
MediaAccountGroupId: magKey,
|
|
6800
6981
|
IsSaltAdd: false,
|
|
6801
6982
|
ManagerCustomerId: "",
|
|
@@ -7080,79 +7261,12 @@ async function runLogin(opts = {}) {
|
|
|
7080
7261
|
console.log(" siluzan-tso balance -m Google \u67E5\u770B\u8D26\u6237\u4F59\u989D\n");
|
|
7081
7262
|
}
|
|
7082
7263
|
|
|
7083
|
-
// src/utils/version.ts
|
|
7084
|
-
import * as fs7 from "fs";
|
|
7085
|
-
import * as path8 from "path";
|
|
7086
|
-
import * as os5 from "os";
|
|
7087
|
-
var PKG_NAME = "siluzan-tso-cli";
|
|
7088
|
-
var CONFIG_FILE2 = path8.join(os5.homedir(), ".siluzan", "config.json");
|
|
7089
|
-
function getCurrentVersion2() {
|
|
7090
|
-
return getCurrentVersion(import.meta.url);
|
|
7091
|
-
}
|
|
7092
|
-
function isBetaVersion(version) {
|
|
7093
|
-
return version.includes("-beta");
|
|
7094
|
-
}
|
|
7095
|
-
function readConfigRaw() {
|
|
7096
|
-
try {
|
|
7097
|
-
return JSON.parse(fs7.readFileSync(CONFIG_FILE2, "utf8"));
|
|
7098
|
-
} catch {
|
|
7099
|
-
return {};
|
|
7100
|
-
}
|
|
7101
|
-
}
|
|
7102
|
-
function writeConfigRaw(data) {
|
|
7103
|
-
try {
|
|
7104
|
-
fs7.mkdirSync(path8.dirname(CONFIG_FILE2), { recursive: true });
|
|
7105
|
-
fs7.writeFileSync(CONFIG_FILE2, JSON.stringify(data, null, 2), "utf8");
|
|
7106
|
-
if (process.platform !== "win32") {
|
|
7107
|
-
fs7.chmodSync(CONFIG_FILE2, 384);
|
|
7108
|
-
}
|
|
7109
|
-
} catch {
|
|
7110
|
-
}
|
|
7111
|
-
}
|
|
7112
|
-
async function fetchVersionByTag(tag, cfg) {
|
|
7113
|
-
const cacheKey = tag === "beta" ? "_tsoLatestBeta" : "_tsoLatestStable";
|
|
7114
|
-
const hours24 = 24 * 60 * 60 * 1e3;
|
|
7115
|
-
if (cfg._tsoLastVersionCheck && cfg[cacheKey]) {
|
|
7116
|
-
const lastCheck = new Date(cfg._tsoLastVersionCheck).getTime();
|
|
7117
|
-
if (Date.now() - lastCheck < hours24) {
|
|
7118
|
-
return cfg[cacheKey];
|
|
7119
|
-
}
|
|
7120
|
-
}
|
|
7121
|
-
return fetchNpmVersion(PKG_NAME, tag);
|
|
7122
|
-
}
|
|
7123
|
-
async function notifyIfOutdated() {
|
|
7124
|
-
try {
|
|
7125
|
-
const current = getCurrentVersion2();
|
|
7126
|
-
const isBeta = isBetaVersion(current);
|
|
7127
|
-
const tag = isBeta ? "beta" : "latest";
|
|
7128
|
-
const cfg = readConfigRaw();
|
|
7129
|
-
const latest = await fetchVersionByTag(tag, cfg);
|
|
7130
|
-
if (!latest) return;
|
|
7131
|
-
const cacheKey = isBeta ? "_tsoLatestBeta" : "_tsoLatestStable";
|
|
7132
|
-
writeConfigRaw({
|
|
7133
|
-
...cfg,
|
|
7134
|
-
_tsoLastVersionCheck: (/* @__PURE__ */ new Date()).toISOString(),
|
|
7135
|
-
[cacheKey]: latest
|
|
7136
|
-
});
|
|
7137
|
-
if (isNewer(current, latest)) {
|
|
7138
|
-
const tagLabel = isBeta ? "\uFF08\u6D4B\u8BD5\u7248\uFF09" : "\uFF08\u6B63\u5F0F\u7248\uFF09";
|
|
7139
|
-
console.error(
|
|
7140
|
-
`
|
|
7141
|
-
\u{1F4A1} \u53D1\u73B0\u65B0\u7248\u672C ${latest}${tagLabel}\uFF08\u5F53\u524D ${current}\uFF09\uFF0C\u8FD0\u884C\u4EE5\u4E0B\u547D\u4EE4\u5347\u7EA7\uFF1A
|
|
7142
|
-
npm install -g ${PKG_NAME}@${tag}
|
|
7143
|
-
`
|
|
7144
|
-
);
|
|
7145
|
-
}
|
|
7146
|
-
} catch {
|
|
7147
|
-
}
|
|
7148
|
-
}
|
|
7149
|
-
|
|
7150
7264
|
// src/index.ts
|
|
7151
7265
|
function getVersion() {
|
|
7152
7266
|
try {
|
|
7153
|
-
const __dirname2 =
|
|
7154
|
-
const pkgPath =
|
|
7155
|
-
const pkg = JSON.parse(
|
|
7267
|
+
const __dirname2 = path10.dirname(fileURLToPath3(import.meta.url));
|
|
7268
|
+
const pkgPath = path10.join(__dirname2, "..", "package.json");
|
|
7269
|
+
const pkg = JSON.parse(fs9.readFileSync(pkgPath, "utf8"));
|
|
7156
7270
|
return pkg.version ?? "0.0.0";
|
|
7157
7271
|
} catch {
|
|
7158
7272
|
return "0.0.0";
|
|
@@ -7177,6 +7291,9 @@ configCmd.command("set").description("\u4FDD\u5B58\u914D\u7F6E\u5230 ~/.siluzan/
|
|
|
7177
7291
|
cmdConfigSet({ apiKey: opts.apiKey, token: opts.token, apiBase: opts.apiBase, googleApi: opts.googleApi });
|
|
7178
7292
|
});
|
|
7179
7293
|
configCmd.command("clear").description("\u6E05\u7A7A\u5DF2\u4FDD\u5B58\u7684 Token").action(() => cmdConfigClear());
|
|
7294
|
+
program.command("update").description("\u68C0\u67E5\u5E76\u66F4\u65B0 siluzan-tso-cli \u81F3\u6700\u65B0\u7248\u672C\uFF0C\u540C\u6B65\u5237\u65B0\u6240\u6709\u5DF2\u5B89\u88C5\u7684 Skill \u6587\u4EF6").option("--force", "\u8DF3\u8FC7\u7248\u672C\u6BD4\u8F83\uFF0C\u5F3A\u5236\u91CD\u65B0\u5B89\u88C5\u5E76\u5237\u65B0 Skill \u6587\u4EF6", false).option("--skip-init", "\u4EC5\u66F4\u65B0 CLI\uFF0C\u4E0D\u91CD\u65B0\u521D\u59CB\u5316 Skill \u6587\u4EF6", false).action(async (opts) => {
|
|
7295
|
+
await runUpdate({ force: opts.force, skipInit: opts.skipInit });
|
|
7296
|
+
});
|
|
7180
7297
|
program.command("init").description("\u5C06 siluzan-tso Skill \u6587\u4EF6\u5199\u5165\u6307\u5B9A AI \u52A9\u624B\u76EE\u5F55").option(
|
|
7181
7298
|
"-a, --ai <targets>",
|
|
7182
7299
|
"\u76EE\u6807\u5E73\u53F0\uFF0C\u9017\u53F7\u5206\u9694\uFF1Acursor,claude,openclaw-workspace,openclaw-global,workbuddy-workspace,workbuddy-global,all",
|
|
@@ -8369,7 +8486,7 @@ openAccountCmd.command("yandex").description("\u63D0\u4EA4 Yandex \u5F00\u6237\u
|
|
|
8369
8486
|
verbose: opts.verbose
|
|
8370
8487
|
});
|
|
8371
8488
|
});
|
|
8372
|
-
openAccountCmd.command("bing").description("\u63D0\u4EA4 Bing/BingV2 \u5F00\u6237\u7533\u8BF7\uFF08\u9700\u4E0A\u4F20\u8425\u4E1A\u6267\u7167\u56FE\u7247\uFF0C\u6309\u516C\u53F8\u540D\u81EA\u52A8\u521B\u5EFA/\u5173\u8054\u5E7F\u544A\u4E3B\u7EC4\uFF09").requiredOption("--advertiser-name <name>", "\u5E7F\u544A\u4E3B\u540D\u79F0\uFF08\u516C\u53F8\u5168\u79F0\uFF0C\u7528\u4E8E\u5339\u914D\u6216\u521B\u5EFA\u5E7F\u544A\u4E3B\u7EC4\uFF09").requiredOption("--name-short <short>", "\u5E7F\u544A\u4E3B\u7B80\u79F0").requiredOption("--province <province>", "\u7701/\u5DDE").requiredOption("--city <city>", "\u57CE\u5E02").requiredOption("--address <address>", "\u8BE6\u7EC6\u5730\u5740").requiredOption("--promotion-link <url>", "\u63A8\u5E7F\u94FE\u63A5").requiredOption("--trade-id <name>", "\u884C\u4E1A\u540D\u79F0\uFF08\u6765\u81EA open-account bing-industries \u7684 name \u5B57\u6BB5\uFF09").requiredOption("--license-file <path>", "\u8425\u4E1A\u6267\u7167\u56FE\u7247\u672C\u5730\u8DEF\u5F84\uFF08JPG/PNG/PDF\uFF09").option("--postcode <code>", "\u90AE\u653F\u7F16\u7801").option("--advertiser-cid <cid>", "\u7ECF\u7406\u8D26\u6237 CID").option("--advertiser-name2 <name>", "\u7ECF\u7406\u8D26\u6237\u540D\u79F0").option("--account-count <n>", "\u5F00\u6237\u6570\u91CF\
|
|
8489
|
+
openAccountCmd.command("bing").description("\u63D0\u4EA4 Bing/BingV2 \u5F00\u6237\u7533\u8BF7\uFF08\u9700\u4E0A\u4F20\u8425\u4E1A\u6267\u7167\u56FE\u7247\uFF0C\u6309\u516C\u53F8\u540D\u81EA\u52A8\u521B\u5EFA/\u5173\u8054\u5E7F\u544A\u4E3B\u7EC4\uFF09").requiredOption("--advertiser-name <name>", "\u5E7F\u544A\u4E3B\u540D\u79F0\uFF08\u516C\u53F8\u5168\u79F0\uFF0C\u7528\u4E8E\u5339\u914D\u6216\u521B\u5EFA\u5E7F\u544A\u4E3B\u7EC4\uFF09").requiredOption("--name-short <short>", "\u5E7F\u544A\u4E3B\u7B80\u79F0").requiredOption("--province <province>", "\u7701/\u5DDE").requiredOption("--city <city>", "\u57CE\u5E02").requiredOption("--address <address>", "\u8BE6\u7EC6\u5730\u5740").requiredOption("--promotion-link <url>", "\u63A8\u5E7F\u94FE\u63A5").requiredOption("--trade-id <name>", "\u884C\u4E1A\u540D\u79F0\uFF08\u6765\u81EA open-account bing-industries \u7684 name \u5B57\u6BB5\uFF09").requiredOption("--license-file <path>", "\u8425\u4E1A\u6267\u7167\u56FE\u7247\u672C\u5730\u8DEF\u5F84\uFF08JPG/PNG/PDF\uFF09").option("--postcode <code>", "\u90AE\u653F\u7F16\u7801").option("--advertiser-cid <cid>", "\u7ECF\u7406\u8D26\u6237 CID").option("--advertiser-name2 <name>", "\u7ECF\u7406\u8D26\u6237\u540D\u79F0").option("--account-count <n>", "\u5F00\u6237\u6570\u91CF\uFF081~6\uFF0C\u9ED8\u8BA4 1\uFF09", parseInt).option("--advertiser-id <magKey>", "\u53EF\u9009\uFF1A\u624B\u52A8\u6307\u5B9A\u5E7F\u544A\u4E3B\u7EC4 magKey\uFF08\u4E00\u822C\u65E0\u9700\u586B\u5199\uFF09").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(async (opts) => {
|
|
8373
8490
|
await runOpenAccountBing({
|
|
8374
8491
|
token: opts.token,
|
|
8375
8492
|
advertiserId: opts.advertiserId,
|
|
@@ -8411,7 +8528,7 @@ openAccountCmd.command("google-timezones").description("\u5217\u51FA Google \u5F
|
|
|
8411
8528
|
openAccountCmd.command("google-wizard").description("\u4EA4\u4E92\u5F0F Google \u5F00\u6237\uFF08\u5BF9\u9F50\u7F51\u9875\u4E94\u6B65\u8BF4\u660E + \u4E24\u6B65\u8868\u5355\uFF1B\u9700\u7EC8\u7AEF TTY\uFF09").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(async (opts) => {
|
|
8412
8529
|
await runOpenAccountGoogleWizard({ token: opts.token, verbose: opts.verbose });
|
|
8413
8530
|
});
|
|
8414
|
-
openAccountCmd.command("google").description("\u63D0\u4EA4 Google \u5F00\u6237\u7533\u8BF7\uFF08\u4E0E\u7F51\u9875\u8868\u5355\u4E00\u81F4\uFF1A\u6309\u516C\u53F8\u540D\u79F0\u81EA\u52A8\u521B\u5EFA/\u5173\u8054\u5E7F\u544A\u4E3B\u7EC4\uFF0C\u65E0\u9700 magKey\uFF09").option("--advertiser-id <magKey>", "\u53EF\u9009\uFF1A\u624B\u52A8\u6307\u5B9A\u5E7F\u544A\u4E3B\u7EC4 ID\uFF08\u4E00\u822C\u4E0D\u7528\uFF1B\u8C03\u8BD5\u7528\u6216\u7279\u6B8A\u573A\u666F\uFF09").requiredOption("--account-name <name>", "\u5E7F\u544A\u8D26\u6237\u540D\u79F0\uFF08\u5EFA\u8BAE 22 \u4E2A\u5B57\u7B26\u4EE5\u5185\uFF09").requiredOption("--currency <code>", "\u8D27\u5E01\uFF1AUSD | CNY").requiredOption("--timezone <tz>", "\u65F6\u533A\uFF0C\u5982 Asia/Hong_Kong\uFF08\u53EF\u5148\u67E5 open-account google-timezones\uFF09").requiredOption("--invite-email <email>", "\u53D7\u9080\u7528\u6237\u90AE\u7BB1\uFF08\u8D26\u6237\u9080\u8BF7\u5C06\u53D1\u5230\u6B64\u90AE\u7BB1\uFF09").requiredOption("--company <name>", "\u516C\u53F8\u540D\u79F0\uFF08\u7528\u4E8E\u5339\u914D\u6216\u521B\u5EFA\u5E7F\u544A\u4E3B\u7EC4\uFF0C\u4E0E\u7F51\u9875\u7B2C\u4E00\u6B65\u4E00\u81F4\uFF09").
|
|
8531
|
+
openAccountCmd.command("google").description("\u63D0\u4EA4 Google \u5F00\u6237\u7533\u8BF7\uFF08\u4E0E\u7F51\u9875\u8868\u5355\u4E00\u81F4\uFF1A\u6309\u516C\u53F8\u540D\u79F0\u81EA\u52A8\u521B\u5EFA/\u5173\u8054\u5E7F\u544A\u4E3B\u7EC4\uFF0C\u65E0\u9700 magKey\uFF09").option("--advertiser-id <magKey>", "\u53EF\u9009\uFF1A\u624B\u52A8\u6307\u5B9A\u5E7F\u544A\u4E3B\u7EC4 ID\uFF08\u4E00\u822C\u4E0D\u7528\uFF1B\u8C03\u8BD5\u7528\u6216\u7279\u6B8A\u573A\u666F\uFF09").requiredOption("--account-name <name>", "\u5E7F\u544A\u8D26\u6237\u540D\u79F0\uFF08\u5EFA\u8BAE 22 \u4E2A\u5B57\u7B26\u4EE5\u5185\uFF09").requiredOption("--currency <code>", "\u8D27\u5E01\uFF1AUSD | CNY").requiredOption("--timezone <tz>", "\u65F6\u533A\uFF0C\u5982 Asia/Hong_Kong\uFF08\u53EF\u5148\u67E5 open-account google-timezones\uFF09").requiredOption("--invite-email <email>", "\u53D7\u9080\u7528\u6237\u90AE\u7BB1\uFF08\u8D26\u6237\u9080\u8BF7\u5C06\u53D1\u5230\u6B64\u90AE\u7BB1\uFF09").requiredOption("--company <name>", "\u516C\u53F8\u540D\u79F0\uFF08\u7528\u4E8E\u5339\u914D\u6216\u521B\u5EFA\u5E7F\u544A\u4E3B\u7EC4\uFF0C\u4E0E\u7F51\u9875\u7B2C\u4E00\u6B65\u4E00\u81F4\uFF09").requiredOption("--promotion-link <url>", "\u63A8\u5E7F\u94FE\u63A5\uFF08\u516C\u53F8\u5B98\u7F51\u6216\u4EA7\u54C1\u9875\uFF1B\u53EF\u5199\u57DF\u540D\uFF0C\u4F1A\u81EA\u52A8\u8865 https://\uFF09").requiredOption("--promotion-type <type>", "\u63A8\u5E7F\u7C7B\u578B\uFF1Ab2b | b2c | app").option("--invite-role <role>", "\u53D7\u9080\u7528\u6237\u89D2\u8272\uFF1AStandard | Admin\uFF08\u9ED8\u8BA4 Standard\uFF09", "Standard").option("--auto-mailbox", "\u81EA\u52A8\u5206\u914D\u90AE\u7BB1", false).option("--counts <n>", "\u672C\u6B21\u5F00\u6237\u6570\u91CF\uFF081-3\uFF0C\u9ED8\u8BA4 1\uFF09", parseInt).option("--manager-customer-id <id>", "MCC \u7ECF\u7406\u8D26\u6237 ID\uFF08\u53EF\u9009\uFF09").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(async (opts) => {
|
|
8415
8532
|
await runOpenAccountGoogle({
|
|
8416
8533
|
token: opts.token,
|
|
8417
8534
|
advertiserId: opts.advertiserId,
|
|
@@ -8420,8 +8537,6 @@ openAccountCmd.command("google").description("\u63D0\u4EA4 Google \u5F00\u6237\u
|
|
|
8420
8537
|
timezone: opts.timezone,
|
|
8421
8538
|
inviteEmail: opts.inviteEmail,
|
|
8422
8539
|
company: opts.company,
|
|
8423
|
-
industryLevel1: opts.industry1,
|
|
8424
|
-
industryLevel2: opts.industry2,
|
|
8425
8540
|
promotionLink: opts.promotionLink,
|
|
8426
8541
|
promotionType: opts.promotionType,
|
|
8427
8542
|
inviteRole: opts.inviteRole,
|
|
@@ -8431,12 +8546,11 @@ openAccountCmd.command("google").description("\u63D0\u4EA4 Google \u5F00\u6237\u
|
|
|
8431
8546
|
verbose: opts.verbose
|
|
8432
8547
|
});
|
|
8433
8548
|
});
|
|
8434
|
-
openAccountCmd.command("tiktok").description("\u63D0\u4EA4 TikTok \u5F00\u6237\u7533\u8BF7\uFF08\u9700\u4E0A\u4F20\u8425\u4E1A\u6267\u7167\u56FE\u7247\uFF0C\u6309\u516C\u53F8\u540D\u81EA\u52A8\u521B\u5EFA/\u5173\u8054\u5E7F\u544A\u4E3B\u7EC4\uFF09").requiredOption("--account-name <name>", "\u5E7F\u544A\u8D26\u6237\u540D\u79F0").requiredOption("--
|
|
8549
|
+
openAccountCmd.command("tiktok").description("\u63D0\u4EA4 TikTok \u5F00\u6237\u7533\u8BF7\uFF08\u9700\u4E0A\u4F20\u8425\u4E1A\u6267\u7167\u56FE\u7247\uFF0C\u6309\u516C\u53F8\u540D\u81EA\u52A8\u521B\u5EFA/\u5173\u8054\u5E7F\u544A\u4E3B\u7EC4\uFF09").requiredOption("--account-name <name>", "\u5E7F\u544A\u8D26\u6237\u540D\u79F0").requiredOption("--timezone <tz>", "\u65F6\u533A\uFF0C\u5982 UTC+8\uFF08\u53EF\u5148\u67E5 open-account tiktok-timezones\uFF09").requiredOption("--company <name>", "\u516C\u53F8\u540D\u79F0").requiredOption("--industry-id <id>", "\u884C\u4E1A ID\uFF08\u6570\u5B57\uFF0CTikTok \u884C\u4E1A\u53F6\u5B50\u8282\u70B9 ID\uFF09", parseInt).requiredOption("--registered-area <code>", "\u6CE8\u518C\u5730\u56FD\u5BB6\u4EE3\u7801\uFF0C\u5982 CN").requiredOption("--promotion-link <url>", "\u63A8\u5E7F\u94FE\u63A5").requiredOption("--license-no <no>", "\u8425\u4E1A\u6267\u7167\u7F16\u7801\uFF08\u793E\u4F1A\u7EDF\u4E00\u4FE1\u7528\u4EE3\u7801\uFF09").requiredOption("--license-file <path>", "\u8425\u4E1A\u6267\u7167\u56FE\u7247\u672C\u5730\u8DEF\u5F84\uFF08JPG/PNG\uFF09").option("--bc-type <type>", "\u4E1A\u52A1\u4E2D\u5FC3\u7C7B\u578B\uFF1AShop | Store | App | B2B | Other\uFF08\u9ED8\u8BA4 Shop\uFF09", "Shop").option("--partner-id <id>", "BC \u5408\u4F5C\u4F19\u4F34 ID\uFF08bc_id\uFF0C\u53EF\u9009\uFF09").option("--counts <n>", "\u672C\u6B21\u5F00\u6237\u6570\u91CF\uFF081-10\uFF0C\u9ED8\u8BA4 1\uFF09", parseInt).requiredOption("--representative-name <name>", "\u6CD5\u4EBA\u59D3\u540D\uFF08\u94F6\u8054\u9A8C\u8BC1\u5FC5\u586B\uFF09").requiredOption("--representative-id <id>", "\u6CD5\u4EBA\u8EAB\u4EFD\u8BC1\u53F7\uFF08\u94F6\u8054\u9A8C\u8BC1\u5FC5\u586B\uFF09").requiredOption("--unionpay-account <no>", "\u6CD5\u4EBA\u94F6\u8054\u8D26\u53F7\uFF08\u94F6\u8054\u9A8C\u8BC1\u5FC5\u586B\uFF09").requiredOption("--representative-phone <phone>", "\u6CD5\u4EBA\u624B\u673A\u53F7\uFF08\u94F6\u8054\u9A8C\u8BC1\u5FC5\u586B\uFF09").option("--advertiser-id <magKey>", "\u53EF\u9009\uFF1A\u624B\u52A8\u6307\u5B9A\u5E7F\u544A\u4E3B\u7EC4 magKey\uFF08\u4E00\u822C\u65E0\u9700\u586B\u5199\uFF09").option("-t, --token <token>", "Auth Token").option("--verbose", "\u8BE6\u7EC6\u9519\u8BEF\u4FE1\u606F", false).action(async (opts) => {
|
|
8435
8550
|
await runOpenAccountTikTok({
|
|
8436
8551
|
token: opts.token,
|
|
8437
8552
|
advertiserId: opts.advertiserId,
|
|
8438
8553
|
accountName: opts.accountName,
|
|
8439
|
-
currency: opts.currency,
|
|
8440
8554
|
timezone: opts.timezone,
|
|
8441
8555
|
company: opts.company,
|
|
8442
8556
|
industryId: opts.industryId,
|
|
@@ -8484,6 +8598,10 @@ program.command("diagnostic").description("Google \u5E7F\u544A\u8BCA\u65AD\uFF1A
|
|
|
8484
8598
|
console.log(" \u8BCA\u65AD\u5165\u53E3\uFF08\u6D4B\u8BD5\uFF09\uFF1Ahttps://www-ci.siluzan.com/diagnostics/\n");
|
|
8485
8599
|
console.log(" \u8BF7\u5728\u6D4F\u89C8\u5668\u4E2D\u6253\u5F00\u4E0A\u8FF0\u5730\u5740\u5B8C\u6210\u8BCA\u65AD\u64CD\u4F5C\u3002\n");
|
|
8486
8600
|
});
|
|
8601
|
+
var activeCmd = process.argv[2];
|
|
8487
8602
|
program.parseAsync().then(() => {
|
|
8488
|
-
|
|
8603
|
+
if (activeCmd !== "update" && activeCmd !== "login") {
|
|
8604
|
+
notifyIfOutdated().catch(() => {
|
|
8605
|
+
});
|
|
8606
|
+
}
|
|
8489
8607
|
});
|
package/dist/skill/SKILL.md
CHANGED
|
@@ -115,6 +115,29 @@ description: >-
|
|
|
115
115
|
|
|
116
116
|
---
|
|
117
117
|
|
|
118
|
+
## 自动更新规则(必须遵守)
|
|
119
|
+
|
|
120
|
+
CLI 命令执行后可能在输出末尾出现以下两种标记,Agent 必须按对应规则处理:
|
|
121
|
+
|
|
122
|
+
### `[SILUZAN_FORCE_UPDATE]` — 强制更新(必须,不可跳过)
|
|
123
|
+
|
|
124
|
+
当前版本已低于最低要求版本,**必须先升级再继续**:
|
|
125
|
+
|
|
126
|
+
1. 立即执行 `siluzan-tso update`
|
|
127
|
+
2. 告知用户:当前版本过旧,已自动升级,请重新执行刚才的操作
|
|
128
|
+
3. 不得在升级前继续执行任何业务命令
|
|
129
|
+
|
|
130
|
+
### `[SILUZAN_UPDATE_AVAILABLE]` — 可选更新
|
|
131
|
+
|
|
132
|
+
有新版本可用,但当前版本仍可正常使用:
|
|
133
|
+
|
|
134
|
+
1. 执行 `siluzan-tso update`
|
|
135
|
+
2. 更新完成后继续执行原本的用户任务
|
|
136
|
+
|
|
137
|
+
> 两种情况下,`siluzan-tso update` 都会同步刷新 Skill 文件,新版本可能包含参数或流程变更。
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
118
141
|
## AI 行为规范
|
|
119
142
|
|
|
120
143
|
- **先查账户再操作**:对具体账户做操作前,先通过 `list-accounts` 确认 ID。
|
package/dist/skill/_meta.json
CHANGED
|
@@ -73,20 +73,21 @@ siluzan-tso config show
|
|
|
73
73
|
|
|
74
74
|
## 更新 CLI 与 Skill 文件
|
|
75
75
|
|
|
76
|
-
CLI
|
|
76
|
+
CLI 在每次命令执行后会静默检查新版本,有更新时提示;**推荐一键升级并刷新 Skill**:
|
|
77
77
|
|
|
78
|
-
```
|
|
79
|
-
|
|
80
|
-
npm install -g siluzan-tso-cli@beta
|
|
78
|
+
```bash
|
|
79
|
+
siluzan-tso update
|
|
81
80
|
```
|
|
82
81
|
|
|
83
|
-
|
|
82
|
+
等价于:拉取 npm 最新版(全局安装时)+ 按 `tsoInstalledTargets` 强制重写各平台 Skill。也可手动:
|
|
84
83
|
|
|
85
84
|
```bash
|
|
86
|
-
npm install -g siluzan-tso-cli@beta #
|
|
87
|
-
siluzan-tso init --force #
|
|
85
|
+
npm install -g siluzan-tso-cli@beta # 仅升级 CLI
|
|
86
|
+
siluzan-tso init --force # 再按上次记录刷新(--ai 与初始安装时一致)
|
|
88
87
|
```
|
|
89
88
|
|
|
89
|
+
`update` 也支持 `--force`(不比较版本,强制重装并刷新)、`--skip-init`(只跑 npm 不刷新 Skill)。
|
|
90
|
+
|
|
90
91
|
已安装过的目标平台记录在 `~/.siluzan/config.json` 的 `tsoInstalledTargets` 字段,可用于确认需要更新哪些平台。
|
|
91
92
|
|
|
92
93
|
---
|
|
@@ -100,20 +101,3 @@ siluzan-tso config clear # 清空所有凭据
|
|
|
100
101
|
```
|
|
101
102
|
|
|
102
103
|
---
|
|
103
|
-
|
|
104
|
-
## 环境切换
|
|
105
|
-
|
|
106
|
-
| 配置项 | 生产环境(默认) | 测试环境 |
|
|
107
|
-
|--------|----------------|---------|
|
|
108
|
-
| `apiBaseUrl` | `https://tso-api.siluzan.com` | `https://tso-api-ci.siluzan.com` |
|
|
109
|
-
| `googleApiUrl` | `https://googleapi.mysiluzan.com` | `https://googleapi-ci.mysiluzan.com` |
|
|
110
|
-
|
|
111
|
-
```bash
|
|
112
|
-
# 切换到测试环境
|
|
113
|
-
siluzan-tso config set --api-base https://tso-api-ci.siluzan.com
|
|
114
|
-
siluzan-tso config set --google-api https://googleapi-ci.mysiluzan.com
|
|
115
|
-
|
|
116
|
-
# 切回生产环境
|
|
117
|
-
siluzan-tso config set --api-base https://tso-api.siluzan.com
|
|
118
|
-
siluzan-tso config set --google-api https://googleapi.mysiluzan.com
|
|
119
|
-
```
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "siluzan-tso-cli",
|
|
3
|
-
"version": "1.0.0-beta.
|
|
3
|
+
"version": "1.0.0-beta.22",
|
|
4
4
|
"description": "Siluzan 广告账户管理 CLI — 查询账户、余额、消耗数据,管理绑定关系与充值。",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -8,7 +8,8 @@
|
|
|
8
8
|
},
|
|
9
9
|
"files": [
|
|
10
10
|
"dist",
|
|
11
|
-
"README.md"
|
|
11
|
+
"README.md",
|
|
12
|
+
"scripts/postinstall.mjs"
|
|
12
13
|
],
|
|
13
14
|
"keywords": [
|
|
14
15
|
"siluzan",
|
|
@@ -40,6 +41,7 @@
|
|
|
40
41
|
"node": ">=18"
|
|
41
42
|
},
|
|
42
43
|
"scripts": {
|
|
44
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
43
45
|
"build": "node scripts/write-defaults.mjs --env production && tsup && node scripts/copy-skill-assets.mjs --env production",
|
|
44
46
|
"build:prod": "node scripts/write-defaults.mjs --env production && tsup && node scripts/copy-skill-assets.mjs --env production",
|
|
45
47
|
"build:test": "node scripts/write-defaults.mjs --env test && tsup && node scripts/copy-skill-assets.mjs --env test",
|