siluzan-cso-cli 1.1.16-beta.1 → 1.1.17-beta.1
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 +138 -10
- package/dist/skill/SKILL.md +2 -0
- package/dist/skill/_meta.json +2 -2
- package/dist/skill/scripts/install.ps1 +4 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -54,7 +54,7 @@ siluzan-cso init -d /path/to/skills # 写入自定义目录
|
|
|
54
54
|
siluzan-cso init --force # 强制覆盖已存在文件
|
|
55
55
|
```
|
|
56
56
|
|
|
57
|
-
> **注意**:当前为测试版(1.1.
|
|
57
|
+
> **注意**:当前为测试版(1.1.17-beta.1),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-cso-cli`。
|
|
58
58
|
|
|
59
59
|
| 助手 | 建议 `--ai` |
|
|
60
60
|
| ----------------------- | ------------------------------------ |
|
package/dist/index.js
CHANGED
|
@@ -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
|
-
|
|
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 || (
|
|
2297
|
+
port: parsed.port || (isHttps ? 443 : 80),
|
|
2245
2298
|
path: parsed.pathname + parsed.search,
|
|
2246
|
-
method
|
|
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
|
-
|
|
2254
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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${
|
|
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",
|
|
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 ?? "",
|
package/dist/skill/SKILL.md
CHANGED
|
@@ -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
|
---
|
package/dist/skill/_meta.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"slug": "siluzan-cso",
|
|
3
|
-
"version": "1.1.
|
|
4
|
-
"publishedAt":
|
|
3
|
+
"version": "1.1.17-beta.1",
|
|
4
|
+
"publishedAt": 1778229754485,
|
|
5
5
|
"homepage": "https://www.siluzan.com",
|
|
6
6
|
"source": "https://dev.azure.com/jack4it/Sammamish/_git/siluzan-skill",
|
|
7
7
|
"requiredBinaries": [
|
|
@@ -87,6 +87,10 @@ function Main {
|
|
|
87
87
|
Write-Host "| $SKILL_LABEL -- Install |" -ForegroundColor White
|
|
88
88
|
Write-Host '+---------------------------------------------+' -ForegroundColor White
|
|
89
89
|
Write-Host ''
|
|
90
|
+
Write-Warn 'Windows note: some agent clients may fail when running PowerShell/cmd commands.'
|
|
91
|
+
Write-Host ' If this install fails unexpectedly, install Git for Windows and rerun the Bash installer in Git Bash:' -ForegroundColor DarkGray
|
|
92
|
+
Write-Host ' https://git-scm.com/download/win' -ForegroundColor DarkGray
|
|
93
|
+
Write-Host ''
|
|
90
94
|
|
|
91
95
|
# Step 1: Environment check
|
|
92
96
|
Write-Step 'Step 1/4: Environment check'
|
package/package.json
CHANGED