siluzan-cso-cli 1.1.8-beta.4 → 1.1.8-beta.5
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 +0 -214
- package/dist/skill/_meta.json +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ siluzan-cso init -d /path/to/skills # 写入自定义目录
|
|
|
20
20
|
siluzan-cso init --force # 强制覆盖已存在文件
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
> **注意**:当前为测试版(1.1.8-beta.
|
|
23
|
+
> **注意**:当前为测试版(1.1.8-beta.5),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-cso-cli`。
|
|
24
24
|
|
|
25
25
|
| 助手 | 建议 `--ai` |
|
|
26
26
|
|------|-------------|
|
package/dist/index.js
CHANGED
|
@@ -2281,11 +2281,6 @@ function redactCliArgvForSentry(argv) {
|
|
|
2281
2281
|
}
|
|
2282
2282
|
return out.join(" ");
|
|
2283
2283
|
}
|
|
2284
|
-
function isApiTrackingEnabled() {
|
|
2285
|
-
const v = process.env.SILUZAN_SENTRY_TRACKING?.trim().toLowerCase();
|
|
2286
|
-
if (v === "0" || v === "false" || v === "off" || v === "no") return false;
|
|
2287
|
-
return true;
|
|
2288
|
-
}
|
|
2289
2284
|
function setSiluzanCliMeta(name, version) {
|
|
2290
2285
|
cliMeta = { name, version };
|
|
2291
2286
|
if (sentryReady) {
|
|
@@ -2374,178 +2369,6 @@ function inferSiluzanRuntimeEnvironment(requestUrl) {
|
|
|
2374
2369
|
return "production";
|
|
2375
2370
|
}
|
|
2376
2371
|
}
|
|
2377
|
-
function breadcrumbUrl(requestUrl) {
|
|
2378
|
-
try {
|
|
2379
|
-
const u = new URL(requestUrl);
|
|
2380
|
-
return `${u.origin}${u.pathname}`;
|
|
2381
|
-
} catch {
|
|
2382
|
-
return requestUrl.slice(0, 120);
|
|
2383
|
-
}
|
|
2384
|
-
}
|
|
2385
|
-
function trackingPathParts(requestUrl) {
|
|
2386
|
-
try {
|
|
2387
|
-
const u = new URL(requestUrl);
|
|
2388
|
-
return { host: u.hostname.toLowerCase(), pathname: u.pathname || "/" };
|
|
2389
|
-
} catch {
|
|
2390
|
-
return { host: "unknown", pathname: "/" };
|
|
2391
|
-
}
|
|
2392
|
-
}
|
|
2393
|
-
var SENSITIVE_QUERY_KEYS = /* @__PURE__ */ new Set([
|
|
2394
|
-
"token",
|
|
2395
|
-
"password",
|
|
2396
|
-
"api_key",
|
|
2397
|
-
"apikey",
|
|
2398
|
-
"key",
|
|
2399
|
-
"secret",
|
|
2400
|
-
"authorization",
|
|
2401
|
-
"auth"
|
|
2402
|
-
]);
|
|
2403
|
-
function redactUrlForTracking(url) {
|
|
2404
|
-
try {
|
|
2405
|
-
const u = new URL(url);
|
|
2406
|
-
const q = new URLSearchParams(u.search);
|
|
2407
|
-
const out = new URLSearchParams();
|
|
2408
|
-
for (const [k, v] of q.entries()) {
|
|
2409
|
-
out.set(k, SENSITIVE_QUERY_KEYS.has(k.toLowerCase()) ? "[REDACTED]" : v);
|
|
2410
|
-
}
|
|
2411
|
-
const qs = out.toString();
|
|
2412
|
-
return `${u.origin}${u.pathname}${qs ? `?${qs}` : ""}`;
|
|
2413
|
-
} catch {
|
|
2414
|
-
return url.slice(0, 800);
|
|
2415
|
-
}
|
|
2416
|
-
}
|
|
2417
|
-
function redactTrackingHeaders(h) {
|
|
2418
|
-
const out = {};
|
|
2419
|
-
for (const [k, v] of Object.entries(h)) {
|
|
2420
|
-
const low = k.toLowerCase();
|
|
2421
|
-
if (low === "authorization" || low === "x-api-key") {
|
|
2422
|
-
out[k] = "[REDACTED]";
|
|
2423
|
-
} else if (v.length > 2e3) {
|
|
2424
|
-
out[k] = `${v.slice(0, 500)}\u2026[truncated ${v.length} chars]`;
|
|
2425
|
-
} else {
|
|
2426
|
-
out[k] = v;
|
|
2427
|
-
}
|
|
2428
|
-
}
|
|
2429
|
-
return out;
|
|
2430
|
-
}
|
|
2431
|
-
var SENSITIVE_JSON_KEY = /* @__PURE__ */ new Set([
|
|
2432
|
-
"password",
|
|
2433
|
-
"token",
|
|
2434
|
-
"apikey",
|
|
2435
|
-
"api_key",
|
|
2436
|
-
"authorization",
|
|
2437
|
-
"authtoken",
|
|
2438
|
-
"accesstoken",
|
|
2439
|
-
"refreshtoken",
|
|
2440
|
-
"secret",
|
|
2441
|
-
"client_secret",
|
|
2442
|
-
"privatekey",
|
|
2443
|
-
"private_key"
|
|
2444
|
-
]);
|
|
2445
|
-
function deepRedactJson(value, depth) {
|
|
2446
|
-
if (depth > 14) return "[MAX_DEPTH]";
|
|
2447
|
-
if (value === null || typeof value !== "object") return value;
|
|
2448
|
-
if (Array.isArray(value)) {
|
|
2449
|
-
return value.map((v) => deepRedactJson(v, depth + 1));
|
|
2450
|
-
}
|
|
2451
|
-
const o = value;
|
|
2452
|
-
const out = {};
|
|
2453
|
-
for (const [k, v] of Object.entries(o)) {
|
|
2454
|
-
const low = k.toLowerCase().replace(/_/g, "");
|
|
2455
|
-
if (SENSITIVE_JSON_KEY.has(low) || low.includes("password") || low.includes("secret")) {
|
|
2456
|
-
out[k] = "[REDACTED]";
|
|
2457
|
-
} else {
|
|
2458
|
-
out[k] = deepRedactJson(v, depth + 1);
|
|
2459
|
-
}
|
|
2460
|
-
}
|
|
2461
|
-
return out;
|
|
2462
|
-
}
|
|
2463
|
-
function redactPlainTextSnippet(input) {
|
|
2464
|
-
let s = input;
|
|
2465
|
-
s = s.replace(/(Bearer\s+)[^\s'",}]+/gi, "$1***");
|
|
2466
|
-
s = s.replace(
|
|
2467
|
-
/("?(?:apiKey|authToken|accessToken|refreshToken|token|password)"?\s*[:=]\s*"?)([^"\s,}]{4,})/gi,
|
|
2468
|
-
"$1***"
|
|
2469
|
-
);
|
|
2470
|
-
return s;
|
|
2471
|
-
}
|
|
2472
|
-
function trackingBodyMaxChars() {
|
|
2473
|
-
const n = Number(process.env.SILUZAN_SENTRY_BODY_MAX);
|
|
2474
|
-
if (Number.isFinite(n) && n > 256) return Math.min(n, 5e5);
|
|
2475
|
-
return 12e3;
|
|
2476
|
-
}
|
|
2477
|
-
function trackingOmitBodies() {
|
|
2478
|
-
const v = process.env.SILUZAN_SENTRY_NO_API_BODY?.trim().toLowerCase();
|
|
2479
|
-
return v === "1" || v === "true" || v === "yes";
|
|
2480
|
-
}
|
|
2481
|
-
function formatTrackingBody(raw) {
|
|
2482
|
-
if (trackingOmitBodies()) return "[omitted: SILUZAN_SENTRY_NO_API_BODY]";
|
|
2483
|
-
if (raw === void 0 || raw === "") return "";
|
|
2484
|
-
const max = trackingBodyMaxChars();
|
|
2485
|
-
let text;
|
|
2486
|
-
try {
|
|
2487
|
-
const parsed = JSON.parse(raw);
|
|
2488
|
-
text = JSON.stringify(deepRedactJson(parsed, 0));
|
|
2489
|
-
} catch {
|
|
2490
|
-
text = redactPlainTextSnippet(raw);
|
|
2491
|
-
}
|
|
2492
|
-
if (text.length > max) {
|
|
2493
|
-
return `${text.slice(0, max)}\u2026[truncated ${text.length} chars]`;
|
|
2494
|
-
}
|
|
2495
|
-
return text;
|
|
2496
|
-
}
|
|
2497
|
-
async function reportSiluzanApiCall(payload) {
|
|
2498
|
-
if (isSentryDisabled() || !getDsn() || !isApiTrackingEnabled()) return;
|
|
2499
|
-
try {
|
|
2500
|
-
const okInit = await ensureSentryInitialized(payload.url);
|
|
2501
|
-
if (!okInit) return;
|
|
2502
|
-
const Sentry = await import("@sentry/node");
|
|
2503
|
-
const { host, pathname } = trackingPathParts(payload.url);
|
|
2504
|
-
const siluzanEnv = inferSiluzanRuntimeEnvironment(payload.url);
|
|
2505
|
-
const authType = payload.config.apiKey ? "apiKey" : "token";
|
|
2506
|
-
const statusOk = payload.status >= 200 && payload.status < 300;
|
|
2507
|
-
Sentry.captureMessage(
|
|
2508
|
-
`siluzan.cli.api ${payload.method} ${host}${pathname} \u2192 ${payload.status}`,
|
|
2509
|
-
{
|
|
2510
|
-
level: statusOk ? "info" : "warning",
|
|
2511
|
-
tags: {
|
|
2512
|
-
siluzan_tracking: "api",
|
|
2513
|
-
cli: cliMeta.name,
|
|
2514
|
-
cli_version: cliMeta.version,
|
|
2515
|
-
http_method: payload.method,
|
|
2516
|
-
http_host: host,
|
|
2517
|
-
http_status: String(payload.status),
|
|
2518
|
-
siluzan_env: siluzanEnv,
|
|
2519
|
-
auth_type: authType
|
|
2520
|
-
},
|
|
2521
|
-
fingerprint: [
|
|
2522
|
-
"siluzan-cli-api",
|
|
2523
|
-
cliMeta.name,
|
|
2524
|
-
payload.method,
|
|
2525
|
-
host,
|
|
2526
|
-
pathname,
|
|
2527
|
-
statusOk ? "2xx" : payload.status >= 500 ? "5xx" : "4xx"
|
|
2528
|
-
],
|
|
2529
|
-
contexts: {
|
|
2530
|
-
siluzan_cli: {
|
|
2531
|
-
command: cliInvocation || "(pre-action \u672A\u6CE8\u518C\u6216\u5148\u4E8E parse \u53D1\u8D77\u8BF7\u6C42)"
|
|
2532
|
-
},
|
|
2533
|
-
siluzan_request: {
|
|
2534
|
-
url: redactUrlForTracking(payload.url),
|
|
2535
|
-
method: payload.method,
|
|
2536
|
-
headers: redactTrackingHeaders(payload.reqHeaders),
|
|
2537
|
-
body: formatTrackingBody(payload.requestBody)
|
|
2538
|
-
},
|
|
2539
|
-
siluzan_response: {
|
|
2540
|
-
status: payload.status,
|
|
2541
|
-
body: formatTrackingBody(payload.responseText)
|
|
2542
|
-
}
|
|
2543
|
-
}
|
|
2544
|
-
}
|
|
2545
|
-
);
|
|
2546
|
-
} catch {
|
|
2547
|
-
}
|
|
2548
|
-
}
|
|
2549
2372
|
function cacheKeyForUser(mainOrigin, config) {
|
|
2550
2373
|
const cred = config.apiKey ? `k:${config.apiKey}` : `t:${config.authToken}`;
|
|
2551
2374
|
return `${mainOrigin}\0${cred}`;
|
|
@@ -2659,33 +2482,6 @@ function refreshSiluzanUser(apiBase, config) {
|
|
|
2659
2482
|
}
|
|
2660
2483
|
})();
|
|
2661
2484
|
}
|
|
2662
|
-
async function prepareSiluzanSentryForApiFetch(url, config, options) {
|
|
2663
|
-
if (isSentryDisabled()) return;
|
|
2664
|
-
if (!getDsn()) return;
|
|
2665
|
-
try {
|
|
2666
|
-
const ok = await ensureSentryInitialized(url);
|
|
2667
|
-
if (!ok) return;
|
|
2668
|
-
const Sentry = await import("@sentry/node");
|
|
2669
|
-
const method = options.method ?? "GET";
|
|
2670
|
-
const siluzanEnv = inferSiluzanRuntimeEnvironment(url);
|
|
2671
|
-
const authType = config.apiKey ? "apiKey" : "token";
|
|
2672
|
-
Sentry.addBreadcrumb({
|
|
2673
|
-
category: "siluzan.api",
|
|
2674
|
-
type: "http",
|
|
2675
|
-
level: "info",
|
|
2676
|
-
message: `${method} ${breadcrumbUrl(url)}`,
|
|
2677
|
-
data: {
|
|
2678
|
-
siluzan_env: siluzanEnv,
|
|
2679
|
-
auth_type: authType
|
|
2680
|
-
}
|
|
2681
|
-
});
|
|
2682
|
-
const mainOrigin = deriveMainApiOriginFromRequestUrl(url);
|
|
2683
|
-
if (mainOrigin) {
|
|
2684
|
-
scheduleUserContext(mainOrigin, config);
|
|
2685
|
-
}
|
|
2686
|
-
} catch {
|
|
2687
|
-
}
|
|
2688
|
-
}
|
|
2689
2485
|
function redactSensitive(input) {
|
|
2690
2486
|
let output = input;
|
|
2691
2487
|
output = output.replace(/(Bearer\s+)[^\s",]+/gi, "$1***");
|
|
@@ -2696,7 +2492,6 @@ function redactSensitive(input) {
|
|
|
2696
2492
|
return output;
|
|
2697
2493
|
}
|
|
2698
2494
|
async function apiFetch(url, config, options = {}, verbose = false) {
|
|
2699
|
-
await prepareSiluzanSentryForApiFetch(url, config, options);
|
|
2700
2495
|
const method = options.method ?? "GET";
|
|
2701
2496
|
const authHeaders = config.apiKey ? { "x-api-key": config.apiKey } : { Authorization: `Bearer ${config.authToken}` };
|
|
2702
2497
|
const reqHeaders = {
|
|
@@ -2714,15 +2509,6 @@ async function apiFetch(url, config, options = {}, verbose = false) {
|
|
|
2714
2509
|
body
|
|
2715
2510
|
});
|
|
2716
2511
|
const text = res.text;
|
|
2717
|
-
await reportSiluzanApiCall({
|
|
2718
|
-
url,
|
|
2719
|
-
config,
|
|
2720
|
-
method,
|
|
2721
|
-
reqHeaders,
|
|
2722
|
-
requestBody: body,
|
|
2723
|
-
status: res.status,
|
|
2724
|
-
responseText: text
|
|
2725
|
-
});
|
|
2726
2512
|
if (res.status < 200 || res.status >= 300) {
|
|
2727
2513
|
const detail = verbose ? `\uFF1A${redactSensitive(text).slice(0, 300)}` : "";
|
|
2728
2514
|
throw new Error(`HTTP ${res.status}${detail}`);
|
package/dist/skill/_meta.json
CHANGED
package/package.json
CHANGED