siluzan-website-cli 1.0.1-beta.4 → 1.0.1-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/dist/index.js CHANGED
@@ -3905,10 +3905,514 @@ async function runSitesList(options) {
3905
3905
  console.log("\n\u540E\u7EED\uFF1Asiluzan-website pages list --site <guid>\n");
3906
3906
  }
3907
3907
  function register5(program2) {
3908
- const sites = program2.command("sites").description("WordPress \u7AD9\u70B9\u67E5\u8BE2");
3908
+ const sites = program2.command("sites").description("WordPress \u7AD9\u70B9\u67E5\u8BE2\u4E0E\u5F00\u901A");
3909
3909
  sites.command("list").description("\u5217\u51FA\u5F53\u524D\u8D26\u53F7\u4E0B\u7684 WordPress \u7AD9\u70B9").option("-q, --query <keyword>", "\u6309\u540D\u79F0\u641C\u7D22").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
3910
3910
  await runSitesList(opts);
3911
3911
  });
3912
+ sites.command("create").description("\u805A\u5408\u521B\u5EFA\u7AD9\u70B9\uFF08website-provision\uFF0C\u5199\u64CD\u4F5C\uFF0CAgent \u987B\u5148\u83B7\u7528\u6237\u786E\u8BA4\uFF09").option("--name <advertiserName>", "\u7AD9\u70B9\u540D\u79F0").option("--region <US|CN>", "\u533A\u57DF", "US").option("--package <packageId>", "\u5957\u9910 ID").option("--template <siteTemplateId>", "\u6A21\u677F ID").option("--site-lang <lang>", "\u524D\u53F0\u8BED\u8A00\uFF0C\u5982 en_US / zh_CN").option("--admin-lang <lang>", "\u540E\u53F0\u8BED\u8A00").option("--bill <packageBillId>", "\u5DF2\u4ED8\u8D26\u5355\u53F7\uFF08\u4ED8\u8D39\u8DEF\u5F84\uFF1B\u8BD5\u7528\u53EF\u4E0D\u4F20\uFF09").option("--wait", "\u521B\u5EFA\u540E\u8F6E\u8BE2\u81F3 Online", false).option("--timeout <seconds>", "wait \u8D85\u65F6\u79D2\u6570", "600").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
3913
+ await runSitesCreate(opts);
3914
+ });
3915
+ sites.command("status").description("\u67E5\u8BE2\u5EFA\u7AD9\u72B6\u6001\uFF08website-provision\uFF09").option("--site <siteGuid>", "\u7AD9\u70B9 guid").option("--region <US|CN>", "\u533A\u57DF", "US").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
3916
+ await runSitesStatus(opts);
3917
+ });
3918
+ sites.command("bind").description("\u8D26\u53F7\u6302\u63A5\u8865\u507F\uFF08SiteMan \u5DF2\u6210\u529F\u4F46 list \u4E0D\u53EF\u89C1\u65F6\uFF09").option("--site <siteGuid>", "\u7AD9\u70B9 guid").option("--region <US|CN>", "\u533A\u57DF", "US").option("--name <advertiserName>", "\u7AD9\u70B9\u540D\u79F0\uFF08\u7528\u4E8E\u67E5\u627E/\u521B\u5EFA Mag\uFF09").option("--mag <magKey>", "\u5DF2\u6709 Mag Key\uFF08\u53EF\u9009\uFF09").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
3919
+ await runSitesBind(opts);
3920
+ });
3921
+ }
3922
+ function asRecordLocal(value) {
3923
+ return value && typeof value === "object" ? value : null;
3924
+ }
3925
+ function readStr2(obj, key) {
3926
+ if (!obj) return "";
3927
+ const v = obj[key];
3928
+ return typeof v === "string" ? v : v == null ? "" : String(v);
3929
+ }
3930
+ async function runSitesCreate(opts) {
3931
+ const name = opts.name?.trim();
3932
+ const packageId = opts.package?.trim();
3933
+ const templateId = opts.template?.trim();
3934
+ const region = (opts.region || "US").trim();
3935
+ const siteLang = opts.siteLang?.trim() || (region.toUpperCase() === "CN" ? "zh_CN" : "en_US");
3936
+ const adminLang = opts.adminLang?.trim() || siteLang;
3937
+ if (!name || !packageId || !templateId) {
3938
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --name --package --template\uFF08\u4EE5\u53CA\u53EF\u9009 --bill / --region / --site-lang / --admin-lang\uFF09\n");
3939
+ process.exit(1);
3940
+ }
3941
+ console.log("\n\u5373\u5C06\u521B\u5EFA WordPress \u7AD9\u70B9\uFF08\u4E3B\u7AD9 website-provision\uFF0C\u4E0D\u53EF\u76F2\u76EE\u91CD\u8BD5\uFF09\uFF1A");
3942
+ console.log(` name : ${name}`);
3943
+ console.log(` region : ${region}`);
3944
+ console.log(` packageId : ${packageId}`);
3945
+ console.log(` templateId : ${templateId}`);
3946
+ console.log(` siteLang : ${siteLang}`);
3947
+ console.log(` adminLang : ${adminLang}`);
3948
+ console.log(` billId : ${opts.bill?.trim() || "(\u8BD5\u7528)"}`);
3949
+ const config = loadConfig();
3950
+ const body = {
3951
+ advertiserName: name,
3952
+ region,
3953
+ packageId,
3954
+ siteTemplateId: templateId,
3955
+ siteLang,
3956
+ adminLang,
3957
+ packageBillId: opts.bill?.trim() || void 0
3958
+ };
3959
+ const url = `${config.apiBaseUrl}/website-provision/sites`;
3960
+ let raw;
3961
+ try {
3962
+ raw = await apiFetch2(
3963
+ url,
3964
+ config,
3965
+ { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) },
3966
+ opts.verbose
3967
+ );
3968
+ } catch (e) {
3969
+ console.error(`
3970
+ \u274C \u521B\u5EFA\u7AD9\u70B9\u5931\u8D25\uFF1A${e.message}`);
3971
+ process.exit(1);
3972
+ return;
3973
+ }
3974
+ const obj = asRecordLocal(raw);
3975
+ const siteGuid = readStr2(obj, "siteGuid") || readStr2(obj, "SiteGuid");
3976
+ const bound = obj?.bound === true || obj?.Bound === true;
3977
+ const code = readStr2(obj, "code") || readStr2(obj, "Code") || "ok";
3978
+ if (opts.json) {
3979
+ console.log(JSON.stringify(raw, null, 2));
3980
+ } else {
3981
+ console.log(code === "site_created_unbound" ? "\n\u26A0\uFE0F \u7AD9\u70B9\u5DF2\u521B\u5EFA\u4F46\u8D26\u53F7\u6302\u63A5\u672A\u5B8C\u6210\n" : "\n\u2705 \u7AD9\u70B9\u521B\u5EFA\u8BF7\u6C42\u5DF2\u53D7\u7406\n");
3982
+ console.log(` siteGuid : ${siteGuid}`);
3983
+ console.log(` region : ${readStr2(obj, "region") || region}`);
3984
+ console.log(` state : ${readStr2(obj, "state") || readStr2(obj, "State") || "-"}`);
3985
+ console.log(` platformUrl : ${readStr2(obj, "platformUrl") || readStr2(obj, "PlatformUrl") || "-"}`);
3986
+ console.log(` bound : ${bound}`);
3987
+ console.log(` magKey : ${readStr2(obj, "magKey") || readStr2(obj, "MagKey") || "-"}`);
3988
+ console.log(` code : ${code}`);
3989
+ if (code === "site_created_unbound") {
3990
+ console.log(`
3991
+ \u8865\u507F\uFF1Asiluzan-website sites bind --site ${siteGuid} --region ${region} --name "${name}"
3992
+ `);
3993
+ }
3994
+ }
3995
+ if (opts.wait && siteGuid) {
3996
+ await pollUntilOnline(config, siteGuid, region, Number(opts.timeout) || 600, opts.verbose);
3997
+ } else if (siteGuid && !opts.json) {
3998
+ console.log(`
3999
+ \u8F6E\u8BE2\u72B6\u6001\uFF1Asiluzan-website sites status --site ${siteGuid} --region ${region}`);
4000
+ console.log(`\u5217\u8868\u6838\u5BF9\uFF1Asiluzan-website sites list -q ${siteGuid}
4001
+ `);
4002
+ }
4003
+ }
4004
+ async function runSitesStatus(opts) {
4005
+ const siteGuid = opts.site?.trim();
4006
+ const region = (opts.region || "US").trim();
4007
+ if (!siteGuid) {
4008
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --site <siteGuid>\n");
4009
+ process.exit(1);
4010
+ }
4011
+ const config = loadConfig();
4012
+ const url = `${config.apiBaseUrl}/website-provision/sites/${encodeURIComponent(region)}/${encodeURIComponent(siteGuid)}/status`;
4013
+ let raw;
4014
+ try {
4015
+ raw = await apiFetch2(url, config, {}, opts.verbose);
4016
+ } catch (e) {
4017
+ console.error(`
4018
+ \u274C \u67E5\u8BE2\u72B6\u6001\u5931\u8D25\uFF1A${e.message}`);
4019
+ process.exit(1);
4020
+ return;
4021
+ }
4022
+ if (opts.json) {
4023
+ console.log(JSON.stringify(raw, null, 2));
4024
+ return;
4025
+ }
4026
+ const obj = asRecordLocal(raw);
4027
+ console.log("\n\u5EFA\u7AD9\u72B6\u6001\n");
4028
+ console.log(` siteGuid : ${readStr2(obj, "siteGuid") || siteGuid}`);
4029
+ console.log(` region : ${readStr2(obj, "region") || region}`);
4030
+ console.log(` statusCode : ${String(obj?.statusCode ?? obj?.StatusCode ?? "-")}`);
4031
+ console.log(` online : ${String(obj?.online ?? obj?.Online ?? "-")}`);
4032
+ console.log(` url : ${readStr2(obj, "url") || readStr2(obj, "Url") || "-"}`);
4033
+ console.log();
4034
+ }
4035
+ async function runSitesBind(opts) {
4036
+ const siteGuid = opts.site?.trim();
4037
+ if (!siteGuid) {
4038
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --site <siteGuid>\n");
4039
+ process.exit(1);
4040
+ }
4041
+ if (!opts.name?.trim() && !opts.mag?.trim()) {
4042
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --name <advertiserName> \u6216 --mag <magKey>\n");
4043
+ process.exit(1);
4044
+ }
4045
+ const config = loadConfig();
4046
+ const body = {
4047
+ region: opts.region || "US",
4048
+ advertiserName: opts.name?.trim(),
4049
+ magKey: opts.mag?.trim()
4050
+ };
4051
+ const url = `${config.apiBaseUrl}/website-provision/sites/${encodeURIComponent(siteGuid)}/bind`;
4052
+ let raw;
4053
+ try {
4054
+ raw = await apiFetch2(
4055
+ url,
4056
+ config,
4057
+ { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) },
4058
+ opts.verbose
4059
+ );
4060
+ } catch (e) {
4061
+ console.error(`
4062
+ \u274C \u6302\u63A5\u5931\u8D25\uFF1A${e.message}`);
4063
+ process.exit(1);
4064
+ return;
4065
+ }
4066
+ if (opts.json) {
4067
+ console.log(JSON.stringify(raw, null, 2));
4068
+ return;
4069
+ }
4070
+ const obj = asRecordLocal(raw);
4071
+ console.log("\n\u2705 \u6302\u63A5\u5B8C\u6210\n");
4072
+ console.log(` siteGuid : ${readStr2(obj, "siteGuid") || siteGuid}`);
4073
+ console.log(` bound : ${String(obj?.bound ?? true)}`);
4074
+ console.log(` magKey : ${readStr2(obj, "magKey") || "-"}`);
4075
+ console.log("\n\u8BF7\u518D\u8DD1 siluzan-website sites list \u6838\u5BF9\u3002\n");
4076
+ }
4077
+ async function pollUntilOnline(config, siteGuid, region, timeoutSec, verbose) {
4078
+ const deadline = Date.now() + timeoutSec * 1e3;
4079
+ console.log(`
4080
+ \u7B49\u5F85\u7AD9\u70B9 Online\uFF08\u6700\u957F ${timeoutSec}s\uFF09\u2026`);
4081
+ while (Date.now() < deadline) {
4082
+ try {
4083
+ const url = `${config.apiBaseUrl}/website-provision/sites/${encodeURIComponent(region)}/${encodeURIComponent(siteGuid)}/status`;
4084
+ const raw = await apiFetch2(url, config, {}, verbose);
4085
+ const obj = asRecordLocal(raw);
4086
+ const online = Boolean(obj?.online ?? obj?.Online);
4087
+ const code = obj?.statusCode ?? obj?.StatusCode;
4088
+ process.stdout.write(` statusCode=${code} online=${online}
4089
+ `);
4090
+ if (online) {
4091
+ console.log("\n\u2705 \u7AD9\u70B9\u5DF2\u53EF\u8BBF\u95EE\uFF08Online\uFF09\n");
4092
+ return;
4093
+ }
4094
+ } catch (e) {
4095
+ process.stdout.write(` \u8F6E\u8BE2\u5F02\u5E38\uFF1A${e.message}
4096
+ `);
4097
+ }
4098
+ await new Promise((r) => setTimeout(r, 1e4));
4099
+ }
4100
+ console.error("\n\u26A0\uFE0F \u7B49\u5F85\u8D85\u65F6\uFF0C\u7AD9\u70B9\u53EF\u80FD\u4ECD\u5728\u521B\u5EFA\u4E2D\u3002\u8BF7\u7A0D\u540E siluzan-website sites status \u518D\u67E5\u3002\n");
4101
+ }
4102
+
4103
+ // src/commands/packages.ts
4104
+ function asRecord2(value) {
4105
+ return value && typeof value === "object" ? value : null;
4106
+ }
4107
+ function readString2(obj, key) {
4108
+ if (!obj) return "";
4109
+ const v = obj[key];
4110
+ return typeof v === "string" ? v : v == null ? "" : String(v);
4111
+ }
4112
+ function unwrapList(raw) {
4113
+ if (Array.isArray(raw)) {
4114
+ return raw.map(asRecord2).filter((x) => Boolean(x));
4115
+ }
4116
+ const obj = asRecord2(raw);
4117
+ if (!obj) return [];
4118
+ if (Array.isArray(obj.data)) {
4119
+ return obj.data.map(asRecord2).filter((x) => Boolean(x));
4120
+ }
4121
+ return [];
4122
+ }
4123
+ async function runPackagesList(opts) {
4124
+ const config = loadConfig();
4125
+ const url = `${config.apiBaseUrl}/website-provision/packages`;
4126
+ let raw;
4127
+ try {
4128
+ raw = await apiFetch2(url, config, {}, opts.verbose);
4129
+ } catch (e) {
4130
+ console.error(`
4131
+ \u274C \u83B7\u53D6\u5957\u9910\u5217\u8868\u5931\u8D25\uFF1A${e.message}`);
4132
+ if (!opts.verbose) console.error(" \u52A0 --verbose \u53EF\u67E5\u770B\u8BE6\u7EC6\u9519\u8BEF");
4133
+ process.exit(1);
4134
+ return;
4135
+ }
4136
+ const list = unwrapList(raw);
4137
+ if (opts.json) {
4138
+ console.log(JSON.stringify({ total: list.length, packages: list }, null, 2));
4139
+ return;
4140
+ }
4141
+ if (list.length === 0) {
4142
+ console.log("\n\u6682\u65E0\u53EF\u7528\u5957\u9910\u3002\n");
4143
+ return;
4144
+ }
4145
+ const columns = [
4146
+ { key: "packageId", header: "packageId" },
4147
+ { key: "packageName", header: "\u540D\u79F0" },
4148
+ { key: "monthUsd", header: "\u6708\u4ED8(USD)" },
4149
+ { key: "yearUsd", header: "\u5E74\u4ED8\u6708\u4EF7(USD)" },
4150
+ { key: "enabled", header: "\u542F\u7528" },
4151
+ { key: "sunset", header: "\u4E0B\u67B6" }
4152
+ ];
4153
+ const rows = list.map((p) => ({
4154
+ packageId: readString2(p, "packageId") || readString2(p, "PackageId"),
4155
+ packageName: readString2(p, "packageName") || readString2(p, "PackageName"),
4156
+ monthUsd: readString2(p, "monthPriceUSD") || readString2(p, "MonthPriceUSD") || "-",
4157
+ yearUsd: readString2(p, "yearlyPriceUSD") || readString2(p, "YearlyPriceUSD") || "-",
4158
+ enabled: String(p.enabled ?? p.Enabled ?? "-"),
4159
+ sunset: String(p.sunset ?? p.Sunset ?? "-")
4160
+ }));
4161
+ console.log(`
4162
+ \u5957\u9910\u5217\u8868\uFF08\u5171 ${list.length} \u4E2A\uFF09
4163
+ `);
4164
+ printCliTable(rows, columns);
4165
+ console.log("\n\u4E0B\u4E00\u6B65\uFF1Asiluzan-website templates list --package <packageId>\n");
4166
+ }
4167
+ function register6(program2) {
4168
+ const packages = program2.command("packages").description("\u5EFA\u7AD9\u5957\u9910\uFF08website-provision\uFF09");
4169
+ packages.command("list").description("\u5217\u51FA\u53EF\u552E\u5957\u9910").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
4170
+ await runPackagesList(opts);
4171
+ });
4172
+ }
4173
+
4174
+ // src/commands/templates.ts
4175
+ function asRecord3(value) {
4176
+ return value && typeof value === "object" ? value : null;
4177
+ }
4178
+ function readString3(obj, key) {
4179
+ if (!obj) return "";
4180
+ const v = obj[key];
4181
+ return typeof v === "string" ? v : v == null ? "" : String(v);
4182
+ }
4183
+ function unwrapList2(raw) {
4184
+ if (Array.isArray(raw)) {
4185
+ return raw.map(asRecord3).filter((x) => Boolean(x));
4186
+ }
4187
+ const obj = asRecord3(raw);
4188
+ if (!obj) return [];
4189
+ if (Array.isArray(obj.data)) {
4190
+ return obj.data.map(asRecord3).filter((x) => Boolean(x));
4191
+ }
4192
+ return [];
4193
+ }
4194
+ async function runTemplatesList(opts) {
4195
+ const config = loadConfig();
4196
+ const params = new URLSearchParams({ pageSize: "100", pageIndex: "1" });
4197
+ if (opts.package) params.set("package", opts.package);
4198
+ if (opts.industry) params.set("industry", opts.industry);
4199
+ if (opts.keyword) params.set("keyword", opts.keyword);
4200
+ const url = `${config.apiBaseUrl}/website-provision/templates?${params.toString()}`;
4201
+ let raw;
4202
+ try {
4203
+ raw = await apiFetch2(url, config, {}, opts.verbose);
4204
+ } catch (e) {
4205
+ console.error(`
4206
+ \u274C \u83B7\u53D6\u6A21\u677F\u5217\u8868\u5931\u8D25\uFF1A${e.message}`);
4207
+ if (!opts.verbose) console.error(" \u52A0 --verbose \u53EF\u67E5\u770B\u8BE6\u7EC6\u9519\u8BEF");
4208
+ process.exit(1);
4209
+ return;
4210
+ }
4211
+ const list = unwrapList2(raw);
4212
+ if (opts.json) {
4213
+ console.log(JSON.stringify({ total: list.length, templates: list }, null, 2));
4214
+ return;
4215
+ }
4216
+ if (list.length === 0) {
4217
+ console.log("\n\u6682\u65E0\u5339\u914D\u6A21\u677F\u3002\u8BF7\u68C0\u67E5 --package \u662F\u5426\u6B63\u786E\u3002\n");
4218
+ return;
4219
+ }
4220
+ const columns = [
4221
+ { key: "id", header: "siteTemplateId" },
4222
+ { key: "name", header: "\u540D\u79F0" },
4223
+ { key: "industry", header: "\u884C\u4E1A" },
4224
+ { key: "version", header: "\u7248\u672C" },
4225
+ { key: "hot", header: "\u70ED\u95E8" },
4226
+ { key: "neu", header: "\u65B0\u54C1" }
4227
+ ];
4228
+ const rows = list.map((t) => ({
4229
+ id: readString3(t, "siteTemplateId") || readString3(t, "SiteTemplateId"),
4230
+ name: readString3(t, "name") || readString3(t, "Name"),
4231
+ industry: readString3(t, "industrys") || readString3(t, "Industrys") || "-",
4232
+ version: readString3(t, "version") || readString3(t, "Version") || "-",
4233
+ hot: String(t.hotTag ?? t.HotTag ?? "-"),
4234
+ neu: String(t.newTag ?? t.NewTag ?? "-")
4235
+ }));
4236
+ console.log(`
4237
+ \u6A21\u677F\u5217\u8868\uFF08\u5171 ${list.length} \u4E2A\uFF09
4238
+ `);
4239
+ printCliTable(rows, columns);
4240
+ console.log("\n\u8BE6\u60C5\uFF1Asiluzan-website templates get --id <siteTemplateId>\n");
4241
+ }
4242
+ async function runTemplatesGet(opts) {
4243
+ const id = opts.id?.trim();
4244
+ if (!id) {
4245
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --id <siteTemplateId>\n");
4246
+ process.exit(1);
4247
+ }
4248
+ const config = loadConfig();
4249
+ const url = `${config.apiBaseUrl}/website-provision/templates/${encodeURIComponent(id)}`;
4250
+ let raw;
4251
+ try {
4252
+ raw = await apiFetch2(url, config, {}, opts.verbose);
4253
+ } catch (e) {
4254
+ console.error(`
4255
+ \u274C \u83B7\u53D6\u6A21\u677F\u8BE6\u60C5\u5931\u8D25\uFF1A${e.message}`);
4256
+ process.exit(1);
4257
+ return;
4258
+ }
4259
+ if (opts.json) {
4260
+ console.log(JSON.stringify(raw, null, 2));
4261
+ return;
4262
+ }
4263
+ const t = asRecord3(raw);
4264
+ console.log("\n\u6A21\u677F\u8BE6\u60C5\n");
4265
+ console.log(` siteTemplateId : ${readString3(t, "siteTemplateId") || readString3(t, "SiteTemplateId") || id}`);
4266
+ console.log(` name : ${readString3(t, "name") || readString3(t, "Name")}`);
4267
+ console.log(` description : ${readString3(t, "description") || readString3(t, "Description") || "-"}`);
4268
+ console.log(` industrys : ${readString3(t, "industrys") || readString3(t, "Industrys") || "-"}`);
4269
+ console.log(` version : ${readString3(t, "version") || readString3(t, "Version") || "-"}`);
4270
+ console.log(` hasTheme : ${String(t?.hasTheme ?? "-")}`);
4271
+ console.log("\n\uFF08\u5B89\u88C5\u5305\u5730\u5740\u5DF2\u8131\u654F\uFF0C\u4E0D\u4F1A\u8F93\u51FA\uFF09\n");
4272
+ }
4273
+ function register7(program2) {
4274
+ const templates = program2.command("templates").description("\u5EFA\u7AD9\u6A21\u677F\uFF08website-provision\uFF09");
4275
+ templates.command("list").description("\u6309\u5957\u9910\u7B49\u6761\u4EF6\u5217\u51FA\u6A21\u677F").option("--package <packageId>", "\u5957\u9910 ID \u8FC7\u6EE4").option("--industry <industry>", "\u884C\u4E1A\u8FC7\u6EE4").option("--keyword <keyword>", "\u5173\u952E\u8BCD").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
4276
+ await runTemplatesList(opts);
4277
+ });
4278
+ templates.command("get").description("\u6A21\u677F\u8BE6\u60C5\uFF08\u4E0D\u542B\u5B89\u88C5\u5305 URI\uFF09").option("--id <siteTemplateId>", "\u6A21\u677F ID").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
4279
+ await runTemplatesGet(opts);
4280
+ });
4281
+ }
4282
+
4283
+ // src/commands/trial.ts
4284
+ function asRecord4(value) {
4285
+ return value && typeof value === "object" ? value : null;
4286
+ }
4287
+ async function runTrialStatus(opts) {
4288
+ const config = loadConfig();
4289
+ const url = `${config.apiBaseUrl}/website-provision/trial-count`;
4290
+ let raw;
4291
+ try {
4292
+ raw = await apiFetch2(url, config, {}, opts.verbose);
4293
+ } catch (e) {
4294
+ console.error(`
4295
+ \u274C \u83B7\u53D6\u8BD5\u7528\u6B21\u6570\u5931\u8D25\uFF1A${e.message}`);
4296
+ process.exit(1);
4297
+ return;
4298
+ }
4299
+ if (opts.json) {
4300
+ console.log(JSON.stringify(raw, null, 2));
4301
+ return;
4302
+ }
4303
+ const obj = asRecord4(raw);
4304
+ const used = Number(obj?.used ?? obj?.Used ?? 0);
4305
+ const limit = Number(obj?.limit ?? obj?.Limit ?? 3);
4306
+ const remaining = Number(obj?.remaining ?? obj?.Remaining ?? Math.max(0, limit - used));
4307
+ console.log("\n\u8BD5\u7528\u5EFA\u7AD9\u989D\u5EA6\n");
4308
+ console.log(` \u5DF2\u7528 : ${used}`);
4309
+ console.log(` \u4E0A\u9650 : ${limit}`);
4310
+ console.log(` \u5269\u4F59 : ${remaining}`);
4311
+ console.log();
4312
+ }
4313
+ function register8(program2) {
4314
+ const trial = program2.command("trial").description("\u8BD5\u7528\u5EFA\u7AD9\u989D\u5EA6\uFF08website-provision\uFF09");
4315
+ trial.command("status").description("\u67E5\u770B\u5F53\u524D\u8D26\u53F7\u8BD5\u7528\u5DF2\u7528\u6B21\u6570\u4E0E\u4E0A\u9650").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
4316
+ await runTrialStatus(opts);
4317
+ });
4318
+ }
4319
+
4320
+ // src/commands/bills.ts
4321
+ function asRecord5(value) {
4322
+ return value && typeof value === "object" ? value : null;
4323
+ }
4324
+ function readString4(obj, key) {
4325
+ if (!obj) return "";
4326
+ const v = obj[key];
4327
+ return typeof v === "string" ? v : v == null ? "" : String(v);
4328
+ }
4329
+ async function runBillsCreate(opts) {
4330
+ const packageId = opts.package?.trim();
4331
+ if (!packageId) {
4332
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --package <packageId>\n");
4333
+ process.exit(1);
4334
+ }
4335
+ const config = loadConfig();
4336
+ const body = {
4337
+ packageId,
4338
+ payChannel: opts.channel || "Monthly",
4339
+ currency: opts.currency || "USD",
4340
+ successUrl: opts.successUrl || "",
4341
+ cancelUrl: opts.cancelUrl || ""
4342
+ };
4343
+ console.log("\n\u5373\u5C06\u521B\u5EFA\u5957\u9910\u8D26\u5355\uFF08\u4E0D\u4F1A\u81EA\u52A8\u6263\u6B3E\uFF0C\u7528\u6237\u9700\u6253\u5F00\u6536\u94F6\u53F0\u5B8C\u6210\u652F\u4ED8\uFF09\uFF1A");
4344
+ console.log(` packageId : ${body.packageId}`);
4345
+ console.log(` payChannel : ${body.payChannel}`);
4346
+ console.log(` currency : ${body.currency}`);
4347
+ const url = `${config.apiBaseUrl}/website-provision/bills`;
4348
+ let raw;
4349
+ try {
4350
+ raw = await apiFetch2(
4351
+ url,
4352
+ config,
4353
+ { method: "POST", headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) },
4354
+ opts.verbose
4355
+ );
4356
+ } catch (e) {
4357
+ console.error(`
4358
+ \u274C \u521B\u5EFA\u8D26\u5355\u5931\u8D25\uFF1A${e.message}`);
4359
+ process.exit(1);
4360
+ return;
4361
+ }
4362
+ if (opts.json) {
4363
+ console.log(JSON.stringify(raw, null, 2));
4364
+ return;
4365
+ }
4366
+ const obj = asRecord5(raw);
4367
+ const billId = readString4(obj, "billId") || readString4(obj, "BillId");
4368
+ const checkoutUrl = readString4(obj, "checkoutUrl") || readString4(obj, "CheckoutUrl");
4369
+ console.log("\n\u2705 \u8D26\u5355\u5DF2\u521B\u5EFA\n");
4370
+ console.log(` billId : ${billId}`);
4371
+ console.log(` state : ${readString4(obj, "state") || readString4(obj, "State") || "-"}`);
4372
+ console.log(` checkoutUrl : ${checkoutUrl || "(\u65E0\uFF0C\u8BF7\u68C0\u67E5 Stripe \u914D\u7F6E)"}`);
4373
+ console.log("\n\u8BF7\u5C06\u6536\u94F6\u53F0\u94FE\u63A5\u53D1\u7ED9\u7528\u6237\u5B8C\u6210\u652F\u4ED8\uFF0C\u7136\u540E\uFF1A");
4374
+ console.log(` siluzan-website bills get --id ${billId}`);
4375
+ console.log(` \u652F\u4ED8\u6210\u529F\u540E\u521B\u5EFA\u7AD9\u70B9\u65F6\u5E26 --bill ${billId}
4376
+ `);
4377
+ }
4378
+ async function runBillsGet(opts) {
4379
+ const id = opts.id?.trim();
4380
+ if (!id) {
4381
+ console.error("\n\u274C \u8BF7\u63D0\u4F9B --id <billId>\n");
4382
+ process.exit(1);
4383
+ }
4384
+ const config = loadConfig();
4385
+ const url = `${config.apiBaseUrl}/website-provision/bills/${encodeURIComponent(id)}`;
4386
+ let raw;
4387
+ try {
4388
+ raw = await apiFetch2(url, config, {}, opts.verbose);
4389
+ } catch (e) {
4390
+ console.error(`
4391
+ \u274C \u67E5\u8BE2\u8D26\u5355\u5931\u8D25\uFF1A${e.message}`);
4392
+ process.exit(1);
4393
+ return;
4394
+ }
4395
+ if (opts.json) {
4396
+ console.log(JSON.stringify(raw, null, 2));
4397
+ return;
4398
+ }
4399
+ const obj = asRecord5(raw);
4400
+ console.log("\n\u8D26\u5355\u72B6\u6001\n");
4401
+ console.log(` billId : ${readString4(obj, "billId") || id}`);
4402
+ console.log(` state : ${readString4(obj, "state") || readString4(obj, "State")}`);
4403
+ console.log(` paid : ${String(obj?.paid ?? obj?.Paid ?? "-")}`);
4404
+ console.log(` packageId : ${readString4(obj, "packageId") || readString4(obj, "PackageId") || "-"}`);
4405
+ console.log(` siteId : ${readString4(obj, "siteId") || readString4(obj, "SiteId") || "(\u672A\u7ED1\u5B9A)"}`);
4406
+ console.log();
4407
+ }
4408
+ function register9(program2) {
4409
+ const bills = program2.command("bills").description("\u5EFA\u7AD9\u5957\u9910\u8D26\u5355 / \u652F\u4ED8\uFF08website-provision\uFF09");
4410
+ bills.command("create").description("\u521B\u5EFA\u5957\u9910\u8D26\u5355\u5E76\u8FD4\u56DE\u6536\u94F6\u53F0 URL\uFF08\u5199\u64CD\u4F5C\uFF0CAgent \u987B\u5148\u83B7\u7528\u6237\u786E\u8BA4\uFF09").option("--package <packageId>", "\u5957\u9910 ID").option("--channel <Monthly|Yearly>", "\u4ED8\u8D39\u5468\u671F", "Monthly").option("--currency <code>", "\u5E01\u79CD", "USD").option("--success-url <url>", "\u652F\u4ED8\u6210\u529F\u56DE\u8DF3 URL").option("--cancel-url <url>", "\u652F\u4ED8\u53D6\u6D88\u56DE\u8DF3 URL").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
4411
+ await runBillsCreate(opts);
4412
+ });
4413
+ bills.command("get").description("\u67E5\u8BE2\u8D26\u5355\u652F\u4ED8\u4E0E\u7ED1\u5B9A\u72B6\u6001").option("--id <billId>", "\u8D26\u5355\u53F7").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
4414
+ await runBillsGet(opts);
4415
+ });
3912
4416
  }
3913
4417
 
3914
4418
  // src/commands/pages.ts
@@ -4202,7 +4706,7 @@ async function runPagesTrash(opts) {
4202
4706
  `
4203
4707
  );
4204
4708
  }
4205
- function register6(program2) {
4709
+ function register10(program2) {
4206
4710
  const pages = program2.command("pages").description("WordPress \u9875\u9762\uFF08zionbuilder visual-edit\uFF09");
4207
4711
  pages.command("list").description("\u5217\u51FA\u7AD9\u70B9\u9875\u9762").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740\uFF08\u8DF3\u8FC7 all-sites\uFF09").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
4208
4712
  await runPagesList(opts);
@@ -4225,7 +4729,7 @@ function register6(program2) {
4225
4729
  }
4226
4730
 
4227
4731
  // src/commands/plugins.ts
4228
- import { readFileSync as readFileSync6, existsSync as existsSync3 } from "fs";
4732
+ import { readFileSync as readFileSync7, existsSync as existsSync3 } from "fs";
4229
4733
  import { basename as basename2, resolve as resolve2 } from "path";
4230
4734
 
4231
4735
  // src/utils/wp-plugin-catalog.ts
@@ -4385,6 +4889,381 @@ function downloadOfficialZip(url) {
4385
4889
  });
4386
4890
  }
4387
4891
 
4892
+ // src/commands/zasp.ts
4893
+ import { readFileSync as readFileSync6 } from "fs";
4894
+ var SECRET_KEY = /api_key|password|token|secret|private_key/i;
4895
+ function zaspUrl(base, path6) {
4896
+ const suffix = path6.startsWith("/") ? path6 : `/${path6}`;
4897
+ return `${base}/wp-json/zasp-b2b/v2${suffix}`;
4898
+ }
4899
+ function explainZaspError(err) {
4900
+ const msg = err instanceof Error ? err.message : String(err);
4901
+ if (/404|rest_no_route|not found/i.test(msg)) {
4902
+ return `${msg}
4903
+ \u7AD9\u70B9\u53EF\u80FD\u6CA1\u88C5 zasp-smart-recommender\uFF0C\u6216\u7248\u672C\u592A\u65E7\u3001\u6CA1\u6709\u7BA1\u7406 REST\u3002
4904
+ \u5148 \`plugins list\`\uFF0C\u518D \`plugins catalog\` / \`install --slug zasp-smart-recommender\`\uFF0C
4905
+ \u6216 \`update --plugin zasp-smart-recommender/zasp-smart-recommender\``;
4906
+ }
4907
+ return msg;
4908
+ }
4909
+ function redactSecrets(value) {
4910
+ if (Array.isArray(value)) return value.map(redactSecrets);
4911
+ if (value && typeof value === "object") {
4912
+ const out = {};
4913
+ for (const [key, nested] of Object.entries(value)) {
4914
+ if (SECRET_KEY.test(key) && typeof nested === "string" && nested) {
4915
+ out[key] = "***";
4916
+ } else {
4917
+ out[key] = redactSecrets(nested);
4918
+ }
4919
+ }
4920
+ return out;
4921
+ }
4922
+ return value;
4923
+ }
4924
+ function printJson(data) {
4925
+ console.log(JSON.stringify(redactSecrets(data), null, 2));
4926
+ }
4927
+ function collectPair(value, acc) {
4928
+ acc.push(value);
4929
+ return acc;
4930
+ }
4931
+ function coerceSetValue(raw) {
4932
+ if (raw === "true") return true;
4933
+ if (raw === "false") return false;
4934
+ if (raw === "null") return null;
4935
+ if (/^-?\d+$/.test(raw)) return Number(raw);
4936
+ if (/^-?\d+\.\d+$/.test(raw)) return Number(raw);
4937
+ return raw;
4938
+ }
4939
+ function parseSetPairs(pairs) {
4940
+ const body = {};
4941
+ for (const raw of pairs ?? []) {
4942
+ const eq = raw.indexOf("=");
4943
+ if (eq <= 0) {
4944
+ throw new Error(`--set \u683C\u5F0F\u5E94\u4E3A key=value\uFF0C\u6536\u5230\uFF1A${raw}`);
4945
+ }
4946
+ const key = raw.slice(0, eq).trim();
4947
+ if (!key) {
4948
+ throw new Error(`--set \u7F3A\u5C11\u5B57\u6BB5\u540D\uFF1A${raw}`);
4949
+ }
4950
+ body[key] = coerceSetValue(raw.slice(eq + 1));
4951
+ }
4952
+ return body;
4953
+ }
4954
+ function parseBodyJson(inline, filePath) {
4955
+ const raw = filePath ? readFileSync6(filePath, "utf8") : inline;
4956
+ if (!raw?.trim()) return {};
4957
+ const parsed = JSON.parse(raw);
4958
+ if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
4959
+ throw new Error("--body / --body-file \u5FC5\u987B\u662F JSON \u5BF9\u8C61");
4960
+ }
4961
+ return parsed;
4962
+ }
4963
+ async function zaspFetch(opts, path6, init = {}) {
4964
+ const target = await resolveTarget(opts);
4965
+ try {
4966
+ const data = await apiFetch2(zaspUrl(target.base, path6), target.config, init, opts.verbose);
4967
+ return { data, siteName: target.site.name, base: target.base };
4968
+ } catch (e) {
4969
+ throw new Error(explainZaspError(e));
4970
+ }
4971
+ }
4972
+ async function runZaspSettings(opts) {
4973
+ let pack;
4974
+ try {
4975
+ pack = await zaspFetch(opts, "/settings");
4976
+ } catch (e) {
4977
+ console.error(`
4978
+ \u274C \u8BFB\u53D6\u914D\u7F6E\u5931\u8D25\uFF1A${e.message}
4979
+ `);
4980
+ process.exit(1);
4981
+ return;
4982
+ }
4983
+ if (opts.json) {
4984
+ printJson({ site: pack.siteName, url: pack.base, ...pack.data });
4985
+ return;
4986
+ }
4987
+ const settings = pack.data.settings ?? {};
4988
+ const runtime = pack.data.runtime ?? {};
4989
+ console.log(`
4990
+ ${pack.siteName} AI \u63A8\u8350\u914D\u7F6E (${pack.base})
4991
+ `);
4992
+ printCliTable(
4993
+ [
4994
+ { k: "ai_provider", v: String(settings.ai_provider ?? "-") },
4995
+ { k: "vector_provider", v: String(settings.vector_provider ?? "-") },
4996
+ { k: "related_enabled", v: String(settings.related_enabled ?? "-") },
4997
+ { k: "related_limit", v: String(settings.related_limit ?? "-") },
4998
+ { k: "auto_sync", v: String(settings.auto_sync ?? "-") },
4999
+ { k: "has_ai_api_key", v: String(settings.has_ai_api_key ?? "-") },
5000
+ { k: "has_vector_api_key", v: String(settings.has_vector_api_key ?? "-") },
5001
+ { k: "has_vector_embed_api_key", v: String(settings.has_vector_embed_api_key ?? "-") },
5002
+ { k: "runtime.ai_configured", v: String(runtime.ai_configured ?? "-") },
5003
+ { k: "runtime.vector_configured", v: String(runtime.vector_configured ?? "-") },
5004
+ { k: "runtime.vector_site_id", v: String(runtime.vector_site_id ?? "-") },
5005
+ { k: "runtime.retrieval_mode", v: String(runtime.retrieval_mode ?? "-") }
5006
+ ],
5007
+ [
5008
+ { key: "k", header: "\u5B57\u6BB5" },
5009
+ { key: "v", header: "\u503C" }
5010
+ ]
5011
+ );
5012
+ const sync = runtime.sync_state;
5013
+ if (sync?.error) {
5014
+ console.log(`
5015
+ \u4E0A\u6B21\u540C\u6B65\u5931\u8D25\uFF1A${String(sync.error)}`);
5016
+ }
5017
+ console.log("\n\u5B8C\u6574\u5B57\u6BB5\u7528 --json\uFF1B\u5B57\u6BB5\u5B57\u5178\u7528 `zasp schema`\u3002\n");
5018
+ }
5019
+ async function runZaspSchema(opts) {
5020
+ let pack;
5021
+ try {
5022
+ pack = await zaspFetch(opts, "/settings/schema");
5023
+ } catch (e) {
5024
+ console.error(`
5025
+ \u274C \u8BFB\u53D6\u5B57\u6BB5\u5B57\u5178\u5931\u8D25\uFF1A${e.message}
5026
+ `);
5027
+ process.exit(1);
5028
+ return;
5029
+ }
5030
+ if (opts.json) {
5031
+ printJson(pack.data);
5032
+ return;
5033
+ }
5034
+ console.log(`
5035
+ ${pack.siteName} \u5B57\u6BB5\u5B57\u5178
5036
+ `);
5037
+ printJson(pack.data);
5038
+ console.log();
5039
+ }
5040
+ async function runZaspSet(opts) {
5041
+ let patch;
5042
+ try {
5043
+ patch = {
5044
+ ...parseBodyJson(opts.body, opts.bodyFile),
5045
+ ...parseSetPairs(opts.set)
5046
+ };
5047
+ } catch (e) {
5048
+ console.error(`
5049
+ \u274C ${e.message}
5050
+ `);
5051
+ process.exit(1);
5052
+ return;
5053
+ }
5054
+ if (opts.clearAiKey) patch.clear_ai_key = true;
5055
+ if (opts.clearVectorKey) patch.clear_vector_key = true;
5056
+ if (opts.clearVectorEmbedKey) patch.clear_vector_embed_key = true;
5057
+ if (Object.keys(patch).length === 0) {
5058
+ console.error(`
5059
+ \u274C \u6CA1\u6709\u8981\u6539\u7684\u5B57\u6BB5\u3002\u7528 --set key=value\uFF0C\u6216 --body '{"related_enabled":1}'
5060
+ `);
5061
+ process.exit(1);
5062
+ }
5063
+ let pack;
5064
+ try {
5065
+ pack = await zaspFetch(opts, "/settings", {
5066
+ method: "PATCH",
5067
+ body: JSON.stringify(patch)
5068
+ });
5069
+ } catch (e) {
5070
+ console.error(`
5071
+ \u274C \u66F4\u65B0\u914D\u7F6E\u5931\u8D25\uFF1A${e.message}
5072
+ `);
5073
+ process.exit(1);
5074
+ return;
5075
+ }
5076
+ const changed = Object.keys(patch).filter((k) => !SECRET_KEY.test(k) && !k.startsWith("clear_"));
5077
+ console.log(`
5078
+ \u2705 \u5DF2\u66F4\u65B0 ${pack.siteName} \u7684 AI \u63A8\u8350\u914D\u7F6E`);
5079
+ if (changed.length) console.log(` \u5B57\u6BB5\uFF1A${changed.join(", ")}`);
5080
+ if (opts.clearAiKey || opts.clearVectorKey || opts.clearVectorEmbedKey) {
5081
+ console.log(" \u5DF2\u6309\u5F00\u5173\u6E05\u7A7A\u5BF9\u5E94\u5BC6\u94A5\uFF08\u660E\u6587\u4E0D\u4F1A\u56DE\u663E\uFF09");
5082
+ }
5083
+ console.log(` \u7AD9\u70B9\uFF1A${pack.base}
5084
+ `);
5085
+ if (opts.json) {
5086
+ printJson(pack.data);
5087
+ return;
5088
+ }
5089
+ const settings = pack.data.settings ?? {};
5090
+ const runtime = pack.data.runtime ?? {};
5091
+ console.log(
5092
+ ` ai_provider=${String(settings.ai_provider ?? "-")} vector_provider=${String(settings.vector_provider ?? "-")} ai_configured=${String(runtime.ai_configured ?? "-")} vector_configured=${String(runtime.vector_configured ?? "-")}`
5093
+ );
5094
+ console.log(" \u6539\u4E86\u5411\u91CF\u540E\u7AEF\u7684\u8BDD\uFF0C\u63A5\u7740\u8DD1 `zasp sync`\uFF1B\u53EA\u6539\u76F8\u5173\u63A8\u8350 / custom AI \u4E00\u822C\u4E0D\u7528\u3002\n");
5095
+ }
5096
+ async function runZaspSync(opts) {
5097
+ let pack;
5098
+ try {
5099
+ pack = await zaspFetch(opts, "/sync", { method: "POST" });
5100
+ } catch (e) {
5101
+ console.error(`
5102
+ \u274C \u540C\u6B65\u5931\u8D25\uFF1A${e.message}
5103
+ `);
5104
+ process.exit(1);
5105
+ return;
5106
+ }
5107
+ if (opts.json) {
5108
+ printJson(pack.data);
5109
+ return;
5110
+ }
5111
+ if (pack.data.ok) {
5112
+ console.log(`
5113
+ \u2705 ${pack.siteName} \u5168\u91CF\u540C\u6B65\u5B8C\u6210\uFF0C\u5199\u5165 ${pack.data.count ?? 0} \u6761
5114
+ `);
5115
+ return;
5116
+ }
5117
+ console.error(`
5118
+ \u274C \u540C\u6B65\u672A\u5B8C\u6210\uFF1A${pack.data.error || "\u672A\u77E5\u9519\u8BEF"}`);
5119
+ console.error(" \u5148\u4FEE Collection / key / \u7EF4\u5EA6\uFF0C\u518D `zasp set`\uFF0C\u518D `zasp sync`\n");
5120
+ process.exit(1);
5121
+ }
5122
+ async function runZaspStatus(opts) {
5123
+ let pack;
5124
+ try {
5125
+ pack = await zaspFetch(opts, "/status");
5126
+ } catch (e) {
5127
+ console.error(`
5128
+ \u274C \u8BFB\u53D6\u72B6\u6001\u5931\u8D25\uFF1A${e.message}
5129
+ `);
5130
+ process.exit(1);
5131
+ return;
5132
+ }
5133
+ if (opts.json) {
5134
+ printJson({ site: pack.siteName, url: pack.base, ...pack.data });
5135
+ return;
5136
+ }
5137
+ const counts = pack.data.source_counts ?? {};
5138
+ console.log(`
5139
+ ${pack.siteName} AI \u63A8\u8350\u72B6\u6001 (${pack.base})
5140
+ `);
5141
+ printCliTable(
5142
+ [
5143
+ { k: "ready", v: String(pack.data.ready ?? pack.data.status ?? "-") },
5144
+ { k: "ai_configured", v: String(pack.data.ai_configured ?? "-") },
5145
+ { k: "vector_configured", v: String(pack.data.vector_configured ?? "-") },
5146
+ { k: "vector_site_id", v: String(pack.data.vector_site_id ?? "-") },
5147
+ { k: "mode", v: String(pack.data.mode ?? "-") },
5148
+ { k: "version", v: String(pack.data.version ?? "-") },
5149
+ { k: "documents", v: String(counts.documents ?? "-") },
5150
+ { k: "products", v: String(counts.products ?? "-") }
5151
+ ],
5152
+ [
5153
+ { key: "k", header: "\u5B57\u6BB5" },
5154
+ { key: "v", header: "\u503C" }
5155
+ ]
5156
+ );
5157
+ console.log();
5158
+ }
5159
+ async function runZaspDiagnostics(opts) {
5160
+ let pack;
5161
+ try {
5162
+ pack = await zaspFetch(opts, "/diagnostics");
5163
+ } catch (e) {
5164
+ console.error(`
5165
+ \u274C \u8BCA\u65AD\u5931\u8D25\uFF1A${e.message}
5166
+ `);
5167
+ process.exit(1);
5168
+ return;
5169
+ }
5170
+ console.log(`
5171
+ ${pack.siteName} \u8BCA\u65AD
5172
+ `);
5173
+ printJson(pack.data);
5174
+ console.log();
5175
+ }
5176
+ async function runZaspRecommend(opts) {
5177
+ const placement = opts.placement?.trim() || "assistant";
5178
+ const limit = Number(opts.limit ?? 5);
5179
+ const pageId = Number(opts.pageId ?? 0);
5180
+ if (!Number.isFinite(limit) || limit < 1) {
5181
+ console.error("\n\u274C --limit \u5FC5\u987B\u662F\u6B63\u6574\u6570\n");
5182
+ process.exit(1);
5183
+ }
5184
+ if (placement === "related_products" && (!Number.isFinite(pageId) || pageId <= 0)) {
5185
+ console.error("\n\u274C \u9875\u9762\u76F8\u5173\u63A8\u8350\u5FC5\u987B\u63D0\u4F9B\u6709\u6548\u5546\u54C1 --page-id\n");
5186
+ process.exit(1);
5187
+ }
5188
+ const body = {
5189
+ query: opts.query?.trim() ?? "",
5190
+ placement,
5191
+ limit,
5192
+ page_id: Number.isFinite(pageId) ? pageId : 0,
5193
+ constraints: {},
5194
+ session: { seen: [], interest: {} }
5195
+ };
5196
+ let pack;
5197
+ try {
5198
+ pack = await zaspFetch(opts, "/recommend", {
5199
+ method: "POST",
5200
+ body: JSON.stringify(body)
5201
+ });
5202
+ } catch (e) {
5203
+ console.error(`
5204
+ \u274C \u8BD5\u63A8\u5931\u8D25\uFF1A${e.message}
5205
+ `);
5206
+ process.exit(1);
5207
+ return;
5208
+ }
5209
+ if (opts.json) {
5210
+ printJson(pack.data);
5211
+ return;
5212
+ }
5213
+ const items = pack.data.items ?? [];
5214
+ console.log(`
5215
+ ${pack.siteName} \u8BD5\u63A8 status=${pack.data.status ?? "-"} mode=${pack.data.mode ?? "-"}`);
5216
+ if (items.length === 0) {
5217
+ console.log("\u6CA1\u6709\u5339\u914D\u7ED3\u679C\u3002\n");
5218
+ return;
5219
+ }
5220
+ printCliTable(
5221
+ items.map((item) => ({
5222
+ id: item.id != null ? String(item.id) : "-",
5223
+ title: item.title || "-",
5224
+ type: item.type || "-",
5225
+ score: item.score != null ? String(item.score) : "-",
5226
+ url: item.url || "-"
5227
+ })),
5228
+ [
5229
+ { key: "id", header: "id" },
5230
+ { key: "title", header: "\u6807\u9898" },
5231
+ { key: "type", header: "\u7C7B\u578B" },
5232
+ { key: "score", header: "\u5206" },
5233
+ { key: "url", header: "\u94FE\u63A5" }
5234
+ ]
5235
+ );
5236
+ console.log();
5237
+ }
5238
+ function hintZaspIfNeeded(pluginOrSlug) {
5239
+ if (!pluginOrSlug.toLowerCase().includes("zasp-smart-recommender")) return;
5240
+ console.log(" \u63A5\u4E0B\u6765\u7528 `siluzan-website zasp settings / set / sync` \u914D\u7F6E AI \u63A8\u8350\uFF08\u89C1 references/zasp-recommender.md\uFF09\n");
5241
+ }
5242
+ function register11(program2) {
5243
+ const zasp = program2.command("zasp").description("zasp-smart-recommender\uFF08AI \u63A8\u8350\uFF09\u914D\u7F6E\u4E0E\u9A8C\u6536\uFF0C\u8D70\u7AD9\u70B9 /wp-json/zasp-b2b/v2");
5244
+ zasp.command("settings").description("\u67E5\u770B\u5F53\u524D AI \u63A8\u8350\u914D\u7F6E\uFF08GET /settings\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA\u5B8C\u6574 JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5245
+ await runZaspSettings(opts);
5246
+ });
5247
+ zasp.command("schema").description("\u67E5\u770B\u53EF\u5199\u5B57\u6BB5\u5B57\u5178\uFF08GET /settings/schema\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5248
+ await runZaspSchema(opts);
5249
+ });
5250
+ zasp.command("set").description("\u53EA\u6539\u8981\u6539\u7684\u5B57\u6BB5\uFF08PATCH /settings\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--body <json>", "PATCH JSON \u5BF9\u8C61\uFF0C\u53EA\u542B\u8981\u6539\u7684\u5B57\u6BB5").option("--body-file <file>", "\u4ECE\u6587\u4EF6\u8BFB PATCH JSON").option("--set <key=value>", "\u5355\u4E2A\u5B57\u6BB5\uFF0C\u53EF\u91CD\u590D", collectPair, []).option("--clear-ai-key", "\u6E05\u7A7A\u5DF2\u4FDD\u5B58\u7684 AI Key", false).option("--clear-vector-key", "\u6E05\u7A7A\u5DF2\u4FDD\u5B58\u7684\u5411\u91CF\u5E93 Key", false).option("--clear-vector-embed-key", "\u6E05\u7A7A\u5DF2\u4FDD\u5B58\u7684 Embedding Key", false).option("--json", "\u8F93\u51FA\u66F4\u65B0\u540E\u7684\u5B8C\u6574 JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5251
+ await runZaspSet(opts);
5252
+ });
5253
+ zasp.command("sync").description("\u5168\u91CF\u540C\u6B65\u5546\u54C1\u5230\u5411\u91CF\u5E93\uFF08POST /sync\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5254
+ await runZaspSync(opts);
5255
+ });
5256
+ zasp.command("status").description("\u516C\u5F00\u9A8C\u6536\uFF1Aready / \u662F\u5426\u914D\u597D\uFF08GET /status\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5257
+ await runZaspStatus(opts);
5258
+ });
5259
+ zasp.command("diagnostics").description("\u7BA1\u7406\u5458\u6DF1\u67E5\uFF08GET /diagnostics\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5260
+ await runZaspDiagnostics(opts);
5261
+ });
5262
+ zasp.command("recommend").description("\u524D\u53F0\u8BD5\u63A8\u4E00\u6761\uFF08POST /recommend\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--query <q>", "\u68C0\u7D22\u8BCD\uFF1B\u76F8\u5173\u63A8\u8350\u53EF\u7559\u7A7A").option("--placement <p>", "assistant \u6216 related_products", "assistant").option("--limit <n>", "\u6761\u6570", "5").option("--page-id <id>", "related_products \u65F6\u7684\u5546\u54C1\u9875 ID", "0").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5263
+ await runZaspRecommend(opts);
5264
+ });
5265
+ }
5266
+
4388
5267
  // src/commands/plugins.ts
4389
5268
  var MAX_ZIP_BYTES = 40 * 1024 * 1024;
4390
5269
  var PROTECTED_PLUGIN_PREFIXES = ["siluzan-helper-plugin", "wp-oauth2"];
@@ -4425,7 +5304,7 @@ function readZipPayload(zipPath) {
4425
5304
  `);
4426
5305
  process.exit(1);
4427
5306
  }
4428
- const buf = readFileSync6(abs);
5307
+ const buf = readFileSync7(abs);
4429
5308
  if (buf.length > MAX_ZIP_BYTES) {
4430
5309
  console.error("\n\u274C zip \u8D85\u8FC7 20MB\uFF0C\u8BF7\u6362\u66F4\u5C0F\u7684\u5305\n");
4431
5310
  process.exit(1);
@@ -4672,6 +5551,7 @@ async function runPluginsInstall(opts) {
4672
5551
  return;
4673
5552
  }
4674
5553
  printActionResult(result, site, base, "\u63D2\u4EF6\u5DF2\u5B89\u88C5\u5E76\u542F\u7528");
5554
+ hintZaspIfNeeded(`${result.plugin || ""} ${slug} ${zipPath}`);
4675
5555
  await runPluginsList({
4676
5556
  site: site.guid || opts.site,
4677
5557
  url: site.url,
@@ -4725,6 +5605,7 @@ async function runPluginsUpdate(opts) {
4725
5605
  return;
4726
5606
  }
4727
5607
  printActionResult(result, site, base, "\u63D2\u4EF6\u5DF2\u5347\u7EA7");
5608
+ hintZaspIfNeeded(`${result.plugin || ""} ${plugin}`);
4728
5609
  await runPluginsList({
4729
5610
  site: site.guid || opts.site,
4730
5611
  url: site.url,
@@ -4870,7 +5751,7 @@ async function runPluginsUninstall(opts) {
4870
5751
  exitOnError: false
4871
5752
  });
4872
5753
  }
4873
- function register7(program2) {
5754
+ function register12(program2) {
4874
5755
  const plugins = program2.command("plugins").description("WordPress \u63D2\u4EF6\uFF1A\u5217\u51FA\u3001\u76EE\u5F55\u3001\u5B89\u88C5\u3001\u5347\u7EA7\u3001\u5378\u8F7D");
4875
5756
  plugins.command("list").description("\u5217\u51FA\u7AD9\u70B9\u5DF2\u5B89\u88C5\u7684\u5168\u90E8\u63D2\u4EF6").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
4876
5757
  await runPluginsList(opts);
@@ -5157,7 +6038,7 @@ async function runContentTrash(opts) {
5157
6038
  \u2705 \u5DF2\u79FB\u5165\u56DE\u6536\u7AD9 ${restBase} #${id}\uFF08status=${item.status || "trash"}\uFF09
5158
6039
  `);
5159
6040
  }
5160
- function register8(program2) {
6041
+ function register13(program2) {
5161
6042
  const content = program2.command("content").description("\u901A\u7528\u5185\u5BB9\uFF1A\u6587\u7AE0/\u4EA7\u54C1\u7B49 REST \u7C7B\u578B\uFF08\u9875\u9762\u6B63\u6587\u8BF7\u7528 pages\uFF09");
5162
6043
  content.command("types").description("\u5217\u51FA\u7AD9\u70B9\u53EF REST \u7BA1\u7406\u7684\u5185\u5BB9\u7C7B\u578B").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5163
6044
  await runContentTypes(opts);
@@ -5180,7 +6061,7 @@ function register8(program2) {
5180
6061
  }
5181
6062
 
5182
6063
  // src/commands/media.ts
5183
- import { existsSync as existsSync4, readFileSync as readFileSync8 } from "fs";
6064
+ import { existsSync as existsSync4, readFileSync as readFileSync9 } from "fs";
5184
6065
  import { basename as basename3, extname, resolve as resolve3 } from "path";
5185
6066
  var MIME_BY_EXT = {
5186
6067
  ".jpg": "image/jpeg",
@@ -5305,7 +6186,7 @@ async function runMediaUpload(opts) {
5305
6186
  `);
5306
6187
  process.exit(1);
5307
6188
  }
5308
- const data = readFileSync8(abs);
6189
+ const data = readFileSync9(abs);
5309
6190
  if (data.length > MAX_MEDIA_BYTES) {
5310
6191
  console.error("\n\u274C \u6587\u4EF6\u8D85\u8FC7 20MB\n");
5311
6192
  process.exit(1);
@@ -5347,7 +6228,7 @@ async function runMediaUpload(opts) {
5347
6228
  console.log(` \u6807\u9898 : ${wpRenderedText(item.title) || filename}`);
5348
6229
  console.log();
5349
6230
  }
5350
- function register9(program2) {
6231
+ function register14(program2) {
5351
6232
  const media = program2.command("media").description("\u5A92\u4F53\u5E93\uFF1A\u5217\u51FA\u3001\u67E5\u770B\u3001\u4E0A\u4F20");
5352
6233
  media.command("list").description("\u5217\u51FA\u5A92\u4F53\u5E93\uFF08\u6700\u8FD1 50 \u6761\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5353
6234
  await runMediaList(opts);
@@ -5528,7 +6409,7 @@ async function runTermsDelete(opts) {
5528
6409
  \u2705 \u5DF2\u5220\u9664 ${restBase} #${id}
5529
6410
  `);
5530
6411
  }
5531
- function register10(program2) {
6412
+ function register15(program2) {
5532
6413
  const terms = program2.command("terms").description("\u5206\u7C7B / \u6807\u7B7E / \u81EA\u5B9A\u4E49\u5206\u7C7B\u6CD5");
5533
6414
  terms.command("taxonomies").description("\u5217\u51FA\u5206\u7C7B\u6CD5").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5534
6415
  await runTermsTaxonomies(opts);
@@ -5608,7 +6489,7 @@ ${target.site.name} \u641C\u7D22\u300C${q}\u300D\uFF08${hits.length}\uFF09
5608
6489
  );
5609
6490
  console.log();
5610
6491
  }
5611
- function register11(program2) {
6492
+ function register16(program2) {
5612
6493
  program2.command("search").description("\u5168\u7AD9\u641C\u7D22\uFF08\u9875\u9762/\u6587\u7AE0/\u5A92\u4F53\u7B49\uFF09").option("-s, --site <guidOrName>", "\u7AD9\u70B9 guid \u6216\u540D\u79F0").option("--url <url>", "\u76F4\u63A5\u6307\u5B9A\u7AD9\u70B9\u5730\u5740").requiredOption("-q, --q <keyword>", "\u5173\u952E\u8BCD").option("--type <subtype>", "\u9650\u5B9A rest \u5B50\u7C7B\u578B\uFF0C\u5982 page / post").option("--json", "\u8F93\u51FA JSON", false).option("--verbose", "\u8F93\u51FA\u8BF7\u6C42\u8BE6\u60C5", false).action(async (opts) => {
5613
6494
  await runSearch(opts);
5614
6495
  });
@@ -5617,19 +6498,24 @@ function register11(program2) {
5617
6498
  // src/index.ts
5618
6499
  installProcessHandlers();
5619
6500
  var program = new Command();
5620
- program.name("siluzan-website").description("Siluzan WordPress \u7AD9\u70B9\u7BA1\u7406\uFF1A\u7AD9\u70B9\u3001\u9875\u9762\u3001\u6587\u7AE0\u3001\u5A92\u4F53\u3001\u5206\u7C7B\u3001\u63D2\u4EF6").version(getCurrentVersion2());
6501
+ program.name("siluzan-website").description("Siluzan WordPress\uFF1A\u5F00\u901A\u5EFA\u7AD9\u3001\u7AD9\u70B9\u3001\u9875\u9762\u3001\u6587\u7AE0\u3001\u5A92\u4F53\u3001\u5206\u7C7B\u3001\u63D2\u4EF6\u3001AI \u63A8\u8350").version(getCurrentVersion2());
5621
6502
  var REGISTRARS = [
5622
6503
  register,
5623
6504
  register2,
5624
6505
  register3,
5625
6506
  register4,
5626
- register5,
5627
6507
  register6,
6508
+ register7,
5628
6509
  register8,
5629
6510
  register9,
6511
+ register5,
5630
6512
  register10,
5631
- register11,
5632
- register7
6513
+ register13,
6514
+ register14,
6515
+ register15,
6516
+ register16,
6517
+ register12,
6518
+ register11
5633
6519
  ];
5634
6520
  for (const reg of REGISTRARS) reg(program);
5635
6521
  program.parse();