siluzan-cso-cli 1.1.16 → 1.1.17-beta.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -46,7 +46,7 @@
46
46
  在**用户的目标项目根目录**执行(根据用户使用的助手选择 `--ai`):
47
47
 
48
48
  ```bash
49
- npm install -g siluzan-cso-cli
49
+ npm install -g siluzan-cso-cli@beta
50
50
  siluzan-cso init --ai cursor # 写入 Cursor(默认)
51
51
  siluzan-cso init --ai cursor,claude # 同时写入多个平台
52
52
  siluzan-cso init --ai all # 写入所有支持的平台
@@ -54,6 +54,7 @@ siluzan-cso init -d /path/to/skills # 写入自定义目录
54
54
  siluzan-cso init --force # 强制覆盖已存在文件
55
55
  ```
56
56
 
57
+ > **注意**:当前为测试版(1.1.17-beta.2),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-cso-cli`。
57
58
 
58
59
  | 助手 | 建议 `--ai` |
59
60
  | ----------------------- | ------------------------------------ |
package/dist/index.js CHANGED
@@ -1939,11 +1939,11 @@ var require_semver2 = __commonJS({
1939
1939
  import { Command, Option } from "commander";
1940
1940
 
1941
1941
  // src/config/defaults.ts
1942
- var BUILD_ENV = "production";
1943
- var DEFAULT_API_BASE = "https://api.siluzan.com";
1944
- var DEFAULT_CSO_BASE = "https://cso.siluzan.com";
1945
- var DEFAULT_WEB_BASE = "https://www.siluzan.com";
1946
- var DEFAULT_AGENT_BASE = "https://agent.mysiluzan.com";
1942
+ var BUILD_ENV = "test";
1943
+ var DEFAULT_API_BASE = "https://api-ci.siluzan.com";
1944
+ var DEFAULT_CSO_BASE = "https://cso-ci.siluzan.com";
1945
+ var DEFAULT_WEB_BASE = "https://www-ci.siluzan.com";
1946
+ var DEFAULT_AGENT_BASE = "https://agent-ci.mysiluzan.com";
1947
1947
 
1948
1948
  // src/commands/init.ts
1949
1949
  import * as fs2 from "fs/promises";
@@ -2151,12 +2151,35 @@ import * as path3 from "path";
2151
2151
  import * as os2 from "os";
2152
2152
  import * as https from "https";
2153
2153
  import * as http from "http";
2154
+ import * as zlib from "zlib";
2155
+ import { performance } from "perf_hooks";
2154
2156
  import { randomUUID as _randomUUID } from "crypto";
2155
2157
  import * as fs22 from "fs";
2156
2158
  import * as path22 from "path";
2157
2159
  import { fileURLToPath as fileURLToPath2 } from "url";
2158
2160
  var SILUZAN_DIR = path3.join(os2.homedir(), ".siluzan");
2159
2161
  var CONFIG_FILE = path3.join(SILUZAN_DIR, "config.json");
2162
+ function atomicWriteFileSync(targetPath, content, encoding = "utf8") {
2163
+ const dir = path3.dirname(targetPath);
2164
+ const tmp = path3.join(
2165
+ dir,
2166
+ `.${path3.basename(targetPath)}.tmp.${process.pid}.${Date.now()}.${Math.random().toString(36).slice(2, 8)}`
2167
+ );
2168
+ try {
2169
+ fs3.writeFileSync(tmp, content, encoding);
2170
+ fs3.renameSync(tmp, targetPath);
2171
+ } catch (err) {
2172
+ try {
2173
+ fs3.unlinkSync(tmp);
2174
+ } catch {
2175
+ }
2176
+ try {
2177
+ fs3.writeFileSync(targetPath, content, encoding);
2178
+ } catch {
2179
+ throw err;
2180
+ }
2181
+ }
2182
+ }
2160
2183
  function readStr(raw, key) {
2161
2184
  const v = raw[key];
2162
2185
  return typeof v === "string" && v ? v : void 0;
@@ -2189,7 +2212,7 @@ function writeSharedConfig(partial) {
2189
2212
  for (const k of keys) {
2190
2213
  if (partial[k] !== void 0) existing[k] = partial[k];
2191
2214
  }
2192
- fs3.writeFileSync(CONFIG_FILE, JSON.stringify(existing, null, 2), "utf8");
2215
+ atomicWriteFileSync(CONFIG_FILE, JSON.stringify(existing, null, 2));
2193
2216
  if (process.platform !== "win32") {
2194
2217
  try {
2195
2218
  fs3.chmodSync(CONFIG_FILE, 384);
@@ -2233,28 +2256,96 @@ function validateBaseUrl(raw) {
2233
2256
  }
2234
2257
  var DEFAULT_TIMEOUT_MS = 10 * 60 * 1e3;
2235
2258
  var MAX_RESPONSE_BYTES = 50 * 1024 * 1024;
2259
+ var httpsAgent = new https.Agent({
2260
+ keepAlive: true,
2261
+ keepAliveMsecs: 3e4,
2262
+ maxSockets: 16,
2263
+ maxFreeSockets: 8,
2264
+ scheduling: "lifo"
2265
+ });
2266
+ var httpAgent = new http.Agent({
2267
+ keepAlive: true,
2268
+ keepAliveMsecs: 3e4,
2269
+ maxSockets: 16,
2270
+ maxFreeSockets: 8,
2271
+ scheduling: "lifo"
2272
+ });
2273
+ var PERF_PREFIX = "[SILUZAN_HTTP_PERF]";
2274
+ function isPerfEnabled() {
2275
+ const v = process.env.SILUZAN_HTTP_PERF;
2276
+ return v === "1" || v === "true";
2277
+ }
2278
+ function emitPerf(record) {
2279
+ try {
2280
+ process.stderr.write(`${PERF_PREFIX} ${JSON.stringify(record)}
2281
+ `);
2282
+ } catch {
2283
+ }
2284
+ }
2236
2285
  function rawRequest(url, options) {
2286
+ const perfOn = isPerfEnabled();
2287
+ const t0 = perfOn ? performance.now() : 0;
2288
+ const method = options.method ?? "GET";
2237
2289
  return new Promise((resolve22, reject) => {
2238
2290
  const parsed = new URL(url);
2239
2291
  const transport = parsed.protocol === "https:" ? https : http;
2240
2292
  const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;
2241
2293
  const maxBytes = options.maxResponseBytes ?? MAX_RESPONSE_BYTES;
2294
+ const isHttps = parsed.protocol === "https:";
2242
2295
  const reqOpts = {
2243
2296
  hostname: parsed.hostname,
2244
- port: parsed.port || (parsed.protocol === "https:" ? 443 : 80),
2297
+ port: parsed.port || (isHttps ? 443 : 80),
2245
2298
  path: parsed.pathname + parsed.search,
2246
- method: options.method ?? "GET",
2299
+ method,
2247
2300
  headers: options.headers,
2248
- timeout: timeoutMs || void 0
2301
+ timeout: timeoutMs || void 0,
2302
+ agent: isHttps ? httpsAgent : httpAgent
2249
2303
  };
2250
2304
  const req = transport.request(reqOpts, (res) => {
2305
+ const encoding = (res.headers["content-encoding"] ?? "").toString().toLowerCase().trim();
2306
+ let stream = res;
2307
+ if (encoding === "gzip" || encoding === "x-gzip") {
2308
+ stream = res.pipe(zlib.createGunzip());
2309
+ } else if (encoding === "deflate") {
2310
+ stream = res.pipe(zlib.createInflate());
2311
+ } else if (encoding === "br") {
2312
+ stream = res.pipe(zlib.createBrotliDecompress());
2313
+ }
2314
+ const handleStreamError = (err) => {
2315
+ res.destroy();
2316
+ if (perfOn) {
2317
+ emitPerf({
2318
+ method,
2319
+ url,
2320
+ status: res.statusCode ?? 0,
2321
+ elapsedMs: performance.now() - t0,
2322
+ bytes: 0,
2323
+ ok: false,
2324
+ error: `decompress error: ${err.message}`
2325
+ });
2326
+ }
2327
+ reject(new Error(`\u54CD\u5E94\u89E3\u538B\u5931\u8D25\uFF08${encoding || "identity"}\uFF09\uFF1A${err.message}`));
2328
+ };
2329
+ if (stream !== res) stream.on("error", handleStreamError);
2330
+ res.on("error", handleStreamError);
2251
2331
  let data = "";
2252
2332
  let byteLen = 0;
2253
- res.setEncoding("utf8");
2254
- res.on("data", (chunk) => {
2333
+ stream.setEncoding("utf8");
2334
+ stream.on("data", (chunk) => {
2255
2335
  byteLen += Buffer.byteLength(chunk, "utf8");
2256
2336
  if (maxBytes && byteLen > maxBytes) {
2257
2337
  res.destroy();
2338
+ if (perfOn) {
2339
+ emitPerf({
2340
+ method,
2341
+ url,
2342
+ status: res.statusCode ?? 0,
2343
+ elapsedMs: performance.now() - t0,
2344
+ bytes: byteLen,
2345
+ ok: false,
2346
+ error: "response body exceeded limit"
2347
+ });
2348
+ }
2258
2349
  reject(
2259
2350
  new Error(`\u54CD\u5E94\u4F53\u8D85\u8FC7\u4E0A\u9650\uFF08${(maxBytes / 1024 / 1024).toFixed(0)} MB\uFF09\uFF0C\u5DF2\u4E2D\u65AD\u8FDE\u63A5`)
2260
2351
  );
@@ -2262,25 +2353,60 @@ function rawRequest(url, options) {
2262
2353
  }
2263
2354
  data += chunk;
2264
2355
  });
2265
- res.on("end", () => {
2356
+ stream.on("end", () => {
2266
2357
  const headers = {};
2267
2358
  for (const [key, val] of Object.entries(res.headers)) {
2268
2359
  if (val !== void 0) {
2269
2360
  headers[key.toLowerCase()] = Array.isArray(val) ? val[0] : val;
2270
2361
  }
2271
2362
  }
2272
- resolve22({ status: res.statusCode ?? 0, text: data, headers });
2363
+ const status = res.statusCode ?? 0;
2364
+ if (perfOn) {
2365
+ emitPerf({
2366
+ method,
2367
+ url,
2368
+ status,
2369
+ elapsedMs: performance.now() - t0,
2370
+ bytes: byteLen,
2371
+ ok: status >= 200 && status < 300
2372
+ });
2373
+ }
2374
+ resolve22({ status, text: data, headers });
2273
2375
  });
2274
2376
  });
2275
2377
  req.on("timeout", () => {
2276
2378
  req.destroy();
2379
+ if (perfOn) {
2380
+ emitPerf({
2381
+ method,
2382
+ url,
2383
+ status: 0,
2384
+ elapsedMs: performance.now() - t0,
2385
+ bytes: 0,
2386
+ ok: false,
2387
+ error: "timeout"
2388
+ });
2389
+ }
2277
2390
  reject(
2278
2391
  new Error(
2279
- `\u8BF7\u6C42\u8D85\u65F6\uFF08${(timeoutMs / 1e3).toFixed(0)} \u79D2\uFF09\uFF1A${options.method ?? "GET"} ${url}`
2392
+ `\u8BF7\u6C42\u8D85\u65F6\uFF08${(timeoutMs / 1e3).toFixed(0)} \u79D2\uFF09\uFF1A${method} ${url}`
2280
2393
  )
2281
2394
  );
2282
2395
  });
2283
- req.on("error", reject);
2396
+ req.on("error", (err) => {
2397
+ if (perfOn) {
2398
+ emitPerf({
2399
+ method,
2400
+ url,
2401
+ status: 0,
2402
+ elapsedMs: performance.now() - t0,
2403
+ bytes: 0,
2404
+ ok: false,
2405
+ error: err.message
2406
+ });
2407
+ }
2408
+ reject(err);
2409
+ });
2284
2410
  if (options.body) req.write(options.body);
2285
2411
  req.end();
2286
2412
  });
@@ -2300,6 +2426,8 @@ async function apiFetch(url, config, options = {}, verbose = false) {
2300
2426
  const reqHeaders = {
2301
2427
  "Content-Type": "application/json",
2302
2428
  "Accept-Language": "zh-CN",
2429
+ // 声明支持 gzip/deflate/br;服务端不支持则按 identity 返回,rawRequest 会原样收取
2430
+ "Accept-Encoding": "gzip, deflate, br",
2303
2431
  ...authHeaders,
2304
2432
  // dataPermission 仅 TSO 使用;CSO 未设置时为空字符串,服务端忽略该头
2305
2433
  Datapermission: config.dataPermission ?? "",
@@ -19,6 +19,8 @@ compatibility: Requires siluzan-cso-cli installed and authenticated via `siluzan
19
19
  irm https://unpkg.com/siluzan-cso-cli@latest/dist/skill/scripts/install.ps1 | iex
20
20
  ```
21
21
 
22
+ Windows 注意:部分 Agent 客户端通过 PowerShell / cmd 代执行命令时存在兼容性问题。若上述命令异常失败,请先安装 [Git for Windows](https://git-scm.com/download/win),然后在 Git Bash 中执行 macOS / Linux / WSL 的 Bash 安装命令。
23
+
22
24
  脚本会自动完成 Node.js 检测/安装、CLI 安装、Skill 全局注册,并引导用户配置 API Key。无需选择,本脚本专为 siluzan-cso-cli 定制。
23
25
 
24
26
  ---
@@ -210,6 +212,6 @@ siluzan-cso rag query -q "产品 卖点 故事" --tags "产品资产库"
210
212
 
211
213
  > 无对应 CLI 命令的模块,或需要引导用户在网页端查看数据时,查阅 `references/web-pages.md` 获取完整页面清单与链接。
212
214
 
213
- URL 格式:`https://www.siluzan.com/v3/foreign_trade/cso/{页面}`
215
+ URL 格式:`https://www-ci.siluzan.com/v3/foreign_trade/cso/{页面}`
214
216
 
215
217
  常用页面:`task`(任务管理)· `postVideo`(发布页)· `ManageAccounts`(账号管理)· `planning`(AI 内容规划)· `table`(绩效报表)· `Workdata`(作品数据)
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "slug": "siluzan-cso",
3
- "version": "1.1.16",
4
- "publishedAt": 1777543619814,
3
+ "version": "1.1.17-beta.2",
4
+ "publishedAt": 1778230897370,
5
5
  "homepage": "https://www.siluzan.com",
6
6
  "source": "https://dev.azure.com/jack4it/Sammamish/_git/siluzan-skill",
7
7
  "requiredBinaries": [
@@ -207,7 +207,7 @@ siluzan-cso publish -c publish-config.json
207
207
 
208
208
  > 查询发布状态、处理失败项 → 参见 `references/task.md`
209
209
 
210
- 前往 CSO 任务管理页面查看进度:`https://www.siluzan.com/v3/foreign_trade/cso/task`
210
+ 前往 CSO 任务管理页面查看进度:`https://www-ci.siluzan.com/v3/foreign_trade/cso/task`
211
211
 
212
212
  ---
213
213
 
@@ -1,5 +1,5 @@
1
1
  # rag:RAG 知识库检索
2
- 知识库管理页面在https://www.siluzan.com/knowledge-base/
2
+ 知识库管理页面在https://www-ci.siluzan.com/knowledge-base/
3
3
 
4
4
  用于写稿、产品知识问答、三库素材提取等场景;凡回答依赖「本企业已入库素材」且不应凭模型记忆编造时,优先走 RAG。
5
5
 
@@ -3,7 +3,7 @@
3
3
  ## 安装 CLI
4
4
 
5
5
  ```bash
6
- npm install -g siluzan-cso-cli
6
+ npm install -g siluzan-cso-cli@beta
7
7
  ```
8
8
 
9
9
  环境要求:Node.js 18+
@@ -44,7 +44,7 @@ siluzan-cso config set --token <Token> # 备用:设置 JWT Token
44
44
 
45
45
  > **⚠️ 不要使用 `config set --token <token>` 的方式。** 该方式会将 Token 明文写入 shell history(`~/.bash_history`、`~/.zsh_history`、PowerShell 历史),存在凭证泄露风险。推荐使用 `siluzan-cso login` 交互式输入。
46
46
 
47
- API Key 获取入口:`https://www.siluzan.com/v3/foreign_trade/settings/apiKeyManagement`
47
+ API Key 获取入口:`https://www-ci.siluzan.com/v3/foreign_trade/settings/apiKeyManagement`
48
48
 
49
49
  ### 通过环境变量传入凭据(CI/CD 推荐)
50
50
 
@@ -81,8 +81,8 @@ siluzan-cso config show
81
81
 
82
82
  ```
83
83
  构建环境 : production
84
- apiBaseUrl : https://api.siluzan.com
85
- csoBaseUrl : https://cso.siluzan.com
84
+ apiBaseUrl : https://api-ci.siluzan.com
85
+ csoBaseUrl : https://cso-ci.siluzan.com
86
86
  apiKey : abcd****1234
87
87
  ```
88
88
 
@@ -1,7 +1,7 @@
1
1
  # web-pages — CSO 后台页面速查
2
2
 
3
3
  > 当需要引导用户前往网页端查看数据或执行操作时,使用本文件中的页面链接。
4
- > URL 格式:`https://www.siluzan.com/v3/foreign_trade/cso/{页面路径}`
4
+ > URL 格式:`https://www-ci.siluzan.com/v3/foreign_trade/cso/{页面路径}`
5
5
 
6
6
  ---
7
7
 
@@ -11,9 +11,9 @@
11
11
 
12
12
  | 页面 | 完整链接 | 功能说明 |
13
13
  | -------- | --------------------------------------------------------- | ---------------------------------------------------- |
14
- | 账号管理 | `https://www.siluzan.com/v3/foreign_trade/cso/ManageAccounts` | 绑定/授权/查看媒体账号列表、账号状态、Token 到期时间 |
15
- | 账号分组 | `https://www.siluzan.com/v3/foreign_trade/cso/AccountGroup` | 新建分组、管理分组内账号 |
16
- | 重点账号 | `https://www.siluzan.com/v3/foreign_trade/cso/KeyAccounts` | 配置重点关注账号、数据备份 |
14
+ | 账号管理 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/ManageAccounts` | 绑定/授权/查看媒体账号列表、账号状态、Token 到期时间 |
15
+ | 账号分组 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/AccountGroup` | 新建分组、管理分组内账号 |
16
+ | 重点账号 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/KeyAccounts` | 配置重点关注账号、数据备份 |
17
17
 
18
18
  ---
19
19
 
@@ -21,10 +21,10 @@
21
21
 
22
22
  | 页面 | 完整链接 | 功能说明 |
23
23
  | -------- | ------------------------------------------------------------------ | ------------------------------------------------------------------------------ |
24
- | 发布作品 | `https://www.siluzan.com/v3/foreign_trade/cso/postVideo?contentType=1` | 矩阵发布视频、图文、草稿管理、话题组 contentType=1 是视频,contentType=2是图文 |
24
+ | 发布作品 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/postVideo?contentType=1` | 矩阵发布视频、图文、草稿管理、话题组 contentType=1 是视频,contentType=2是图文 |
25
25
 
26
- | 发布日历 | `https://www.siluzan.com/v3/foreign_trade/cso/publishCalendar` | 日历视图规划发布任务、创建/编辑发布任务 |
27
- | 营销日历 | `https://www.siluzan.com/v3/foreign_trade/cso/marketingCalendar` | 营销节点日历、跳转创建发布任务 |
26
+ | 发布日历 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/publishCalendar` | 日历视图规划发布任务、创建/编辑发布任务 |
27
+ | 营销日历 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/marketingCalendar` | 营销节点日历、跳转创建发布任务 |
28
28
 
29
29
  ---
30
30
 
@@ -32,10 +32,10 @@
32
32
 
33
33
  | 页面 | 完整链接 | 功能说明 |
34
34
  | -------- | ------------------------------------------------------- | ----------------------------------------- |
35
- | 任务列表 | `https://www.siluzan.com/v3/foreign_trade/cso/task` | 发布任务列表、状态筛选、任务详情抽屉 |
36
- | 视频管理 | `https://www.siluzan.com/v3/foreign_trade/cso/VideoMgr` | 已发布视频/图文列表、删除、重发、评论查看 |
37
- | 视频搬家 | `https://www.siluzan.com/v3/foreign_trade/cso/relocation` | 将视频搬运到其他平台 |
38
- | 搬家记录 | `https://www.siluzan.com/v3/foreign_trade/cso/MovingRecord` | 搬家任务列表与执行状态 |
35
+ | 任务列表 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/task` | 发布任务列表、状态筛选、任务详情抽屉 |
36
+ | 视频管理 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/VideoMgr` | 已发布视频/图文列表、删除、重发、评论查看 |
37
+ | 视频搬家 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/relocation` | 将视频搬运到其他平台 |
38
+ | 搬家记录 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/MovingRecord` | 搬家任务列表与执行状态 |
39
39
 
40
40
  ---
41
41
 
@@ -43,9 +43,9 @@
43
43
 
44
44
  | 页面 | 完整链接 | 功能说明 |
45
45
  | -------- | ------------------------------------------------------ | --------------------------------------- |
46
- | 私信管理 | `https://www.siluzan.com/v3/foreign_trade/cso/letter` | 按渠道/时间查看与处理私信(多平台 Tab) |
47
- | 评论管理 | `https://www.siluzan.com/v3/foreign_trade/cso/comment` | 收到的评论列表、回复、账号组筛选 |
48
- | 智能互动 | `https://www.siluzan.com/v3/foreign_trade/cso/interaction` | 私信欢迎语、自动回复规则配置 |
46
+ | 私信管理 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/letter` | 按渠道/时间查看与处理私信(多平台 Tab) |
47
+ | 评论管理 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/comment` | 收到的评论列表、回复、账号组筛选 |
48
+ | 智能互动 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/interaction` | 私信欢迎语、自动回复规则配置 |
49
49
 
50
50
  ---
51
51
 
@@ -53,9 +53,9 @@
53
53
 
54
54
  | 页面 | 完整链接 | 功能说明 |
55
55
  | -------- | ------------------------------------------------------ | -------------------------------------------------------------------- |
56
- | 作品数据 | `https://www.siluzan.com/v3/foreign_trade/cso/Workdata` | 作品维度统计、图表、明细(对应 CLI `report fetch`) |
57
- | 账户数据 | `https://www.siluzan.com/v3/foreign_trade/cso/accountdata` | 账户维度汇总数据、趋势图表 |
58
- | 绩效报表 | `https://www.siluzan.com/v3/foreign_trade/cso/table` | 多维度绩效报表、PDF 导出(对应 CLI `report fetch/records/download`) |
56
+ | 作品数据 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/Workdata` | 作品维度统计、图表、明细(对应 CLI `report fetch`) |
57
+ | 账户数据 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/accountdata` | 账户维度汇总数据、趋势图表 |
58
+ | 绩效报表 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/table` | 多维度绩效报表、PDF 导出(对应 CLI `report fetch/records/download`) |
59
59
 
60
60
  ---
61
61
 
@@ -63,10 +63,10 @@
63
63
 
64
64
  | 页面 | 完整链接 | 功能说明 |
65
65
  | -------- | ------------------------------------------------------ | -------------------------------------------------------------- |
66
- | 内容规划 | `https://www.siluzan.com/v3/foreign_trade/cso/planning` | AI 内容规划列表、生成规划、企业维度筛选(对应 CLI `planning`) |
67
- | 营销首页 | `https://www.siluzan.com/v3/foreign_trade/cso/ContentHome` | 工作台总览:账号数、视频数、最新评论与视频 |
66
+ | 内容规划 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/planning` | AI 内容规划列表、生成规划、企业维度筛选(对应 CLI `planning`) |
67
+ | 营销首页 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/ContentHome` | 工作台总览:账号数、视频数、最新评论与视频 |
68
68
 
69
- | 话题组 | `https://www.siluzan.com/v3/foreign_trade/cso/TopicGroup` | 话题组维护、话题内容管理 |
69
+ | 话题组 | `https://www-ci.siluzan.com/v3/foreign_trade/cso/TopicGroup` | 话题组维护、话题内容管理 |
70
70
 
71
71
  ---
72
72
 
@@ -10,12 +10,14 @@ $ErrorActionPreference = 'Stop'
10
10
  $PKG_NAME = 'siluzan-cso-cli'
11
11
  $CLI_BIN = 'siluzan-cso'
12
12
  $SKILL_LABEL = 'Siluzan CSO'
13
- $INSTALL_CMD = 'npm install -g siluzan-cso-cli'
14
- $WEB_BASE = 'https://www.siluzan.com'
13
+ $INSTALL_CMD = 'npm install -g siluzan-cso-cli@beta'
14
+ $WEB_BASE = 'https://www-ci.siluzan.com'
15
15
 
16
16
  # -- Constants ----------------------------------------------------------------
17
- $NODE_MAJOR_MIN = 18
18
- $NPM_MIRROR = 'https://registry.npmmirror.com'
17
+ $NODE_MAJOR_MIN = 18
18
+ $NPM_MIRROR = 'https://registry.npmmirror.com'
19
+ # Git for Windows installer (mirrored on Siluzan CDN; bump version here when needed)
20
+ $GIT_INSTALLER_URL = 'https://staticpn.siluzan.com/assets/git/Git-2.54.0-64-bit.exe'
19
21
 
20
22
  # -- Helpers ------------------------------------------------------------------
21
23
  function Write-Info { param([string]$Msg) Write-Host "[OK] $Msg" -ForegroundColor Green }
@@ -80,6 +82,85 @@ function Install-NodeFallback {
80
82
  throw 'Node.js is required'
81
83
  }
82
84
 
85
+ # -- Git for Windows ----------------------------------------------------------
86
+ # Some agent clients (Cursor / Claude Code / etc.) have known quirks running
87
+ # PowerShell or cmd commands. We install Git for Windows ahead of time so the
88
+ # user always has a Git Bash fallback to run the equivalent bash installer
89
+ # (`bash <(curl -fsSL .../install.sh)`) when the PowerShell channel misbehaves.
90
+ function Test-GitInstalled {
91
+ return $null -ne (Get-Command git -ErrorAction SilentlyContinue)
92
+ }
93
+
94
+ function Test-IsAdmin {
95
+ try {
96
+ $id = [Security.Principal.WindowsIdentity]::GetCurrent()
97
+ $principal = New-Object Security.Principal.WindowsPrincipal($id)
98
+ return $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
99
+ } catch {
100
+ return $false
101
+ }
102
+ }
103
+
104
+ function Install-Git {
105
+ $tmpFile = Join-Path $env:TEMP 'siluzan-git-installer.exe'
106
+
107
+ Write-Info "Downloading Git for Windows: $GIT_INSTALLER_URL"
108
+ try {
109
+ $prevProgress = $ProgressPreference
110
+ $ProgressPreference = 'SilentlyContinue'
111
+ Invoke-WebRequest -Uri $GIT_INSTALLER_URL -OutFile $tmpFile -UseBasicParsing
112
+ $ProgressPreference = $prevProgress
113
+ } catch {
114
+ Write-Warn "Git installer download failed: $($_.Exception.Message)"
115
+ return $false
116
+ }
117
+
118
+ if (-not (Test-Path $tmpFile)) {
119
+ Write-Warn 'Git installer file not found after download'
120
+ return $false
121
+ }
122
+
123
+ # Inno Setup silent flags. When not admin we point /DIR to %LOCALAPPDATA% so
124
+ # the installer doesn't try to write to Program Files (which would trigger UAC
125
+ # or just fail). The installer auto-detects ALLUSERS vs CURRENTUSER mode based
126
+ # on whether the current process is elevated, so we don't pass /CURRENTUSER
127
+ # explicitly (not all Git for Windows builds accept that flag).
128
+ $installArgs = @('/VERYSILENT', '/NORESTART', '/NOCANCEL', '/SP-', '/CLOSEAPPLICATIONS', '/RESTARTAPPLICATIONS')
129
+ if (Test-IsAdmin) {
130
+ Write-Info 'Installing Git for Windows system-wide (admin detected)...'
131
+ } else {
132
+ $userDir = Join-Path $env:LOCALAPPDATA 'Programs\Git'
133
+ Write-Info "Installing Git for Windows for current user: $userDir"
134
+ $installArgs += @("/DIR=$userDir")
135
+ }
136
+
137
+ try {
138
+ Start-Process -FilePath $tmpFile -ArgumentList $installArgs -Wait -NoNewWindow
139
+ } catch {
140
+ Write-Warn "Git installer launch failed: $($_.Exception.Message)"
141
+ Remove-Item $tmpFile -ErrorAction SilentlyContinue
142
+ return $false
143
+ }
144
+ Remove-Item $tmpFile -ErrorAction SilentlyContinue
145
+
146
+ Refresh-Path
147
+ if (-not (Test-GitInstalled)) {
148
+ # 安装器有时不会立刻刷新 PATH,按已知路径手动补一次
149
+ $candidates = @(
150
+ (Join-Path $env:LOCALAPPDATA 'Programs\Git\cmd'),
151
+ (Join-Path $env:ProgramFiles 'Git\cmd')
152
+ )
153
+ foreach ($p in $candidates) {
154
+ if (Test-Path (Join-Path $p 'git.exe')) {
155
+ $env:Path = "$p;$env:Path"
156
+ break
157
+ }
158
+ }
159
+ }
160
+
161
+ return Test-GitInstalled
162
+ }
163
+
83
164
  # -- Main ---------------------------------------------------------------------
84
165
  function Main {
85
166
  Write-Host ''
@@ -119,6 +200,23 @@ function Main {
119
200
  }
120
201
  Write-Info 'npm ready'
121
202
 
203
+ # Git for Windows: pre-install as a Bash fallback path for agent clients
204
+ # whose PowerShell/cmd channel is unreliable. Failure here is non-fatal.
205
+ if (Test-GitInstalled) {
206
+ Write-Info 'Git for Windows already installed (Git Bash fallback ready)'
207
+ } else {
208
+ Write-Warn 'Git for Windows not found, installing as Bash fallback for agent clients...'
209
+ $gitOk = $false
210
+ try { $gitOk = Install-Git } catch { Write-Warn "Git install error: $($_.Exception.Message)" }
211
+ if ($gitOk) {
212
+ Write-Info 'Git for Windows installed (Git Bash fallback ready)'
213
+ } else {
214
+ Write-Warn 'Git for Windows install was skipped or failed; CLI install will continue.'
215
+ Write-Host ' If your agent later fails to run PowerShell commands, install Git manually:' -ForegroundColor DarkGray
216
+ Write-Host " $GIT_INSTALLER_URL" -ForegroundColor DarkGray
217
+ }
218
+ }
219
+
122
220
  $currentRegistry = ''
123
221
  try { $currentRegistry = (npm config get registry 2>$null).Trim() } catch {}
124
222
  if ($currentRegistry -ne $NPM_MIRROR -and $currentRegistry -ne "$NPM_MIRROR/") {
@@ -160,6 +258,11 @@ function Main {
160
258
  Write-Host ''
161
259
  Write-Host " Update CLI & Skill files: $CLI_BIN update"
162
260
  Write-Host ''
261
+ if (Test-GitInstalled) {
262
+ Write-Host ' Tip: if your agent client has trouble running PowerShell/cmd commands later,' -ForegroundColor DarkGray
263
+ Write-Host ' open Git Bash and re-run the equivalent bash installer instead.' -ForegroundColor DarkGray
264
+ Write-Host ''
265
+ }
163
266
  Write-Info "Need help? Visit $WEB_BASE"
164
267
  Write-Host ''
165
268
  }
@@ -10,8 +10,8 @@ set -euo pipefail
10
10
  readonly PKG_NAME="siluzan-cso-cli"
11
11
  readonly CLI_BIN="siluzan-cso"
12
12
  readonly SKILL_LABEL="Siluzan CSO"
13
- readonly INSTALL_CMD="npm install -g siluzan-cso-cli"
14
- readonly WEB_BASE="https://www.siluzan.com"
13
+ readonly INSTALL_CMD="npm install -g siluzan-cso-cli@beta"
14
+ readonly WEB_BASE="https://www-ci.siluzan.com"
15
15
 
16
16
  # -- Constants ----------------------------------------------------------------
17
17
  readonly NODE_MAJOR_MIN=18
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "siluzan-cso-cli",
3
- "version": "1.1.16",
3
+ "version": "1.1.17-beta.2",
4
4
  "description": "Siluzan platform AI Skill CLI — multi-platform content publishing (video/image-text) for Cursor, Claude Code, and OpenClaw.",
5
5
  "keywords": [
6
6
  "ai-skill",