siluzan-tso-cli 1.1.8-beta.5 → 1.1.8-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/README.md +1 -1
- package/dist/index.js +105 -319
- package/dist/skill/_meta.json +2 -2
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -20,7 +20,7 @@ siluzan-tso init -d /path/to/skills # 写入自定义目录
|
|
|
20
20
|
siluzan-tso init --force # 强制覆盖已存在文件
|
|
21
21
|
```
|
|
22
22
|
|
|
23
|
-
> **注意**:当前为测试版(1.1.8-beta.
|
|
23
|
+
> **注意**:当前为测试版(1.1.8-beta.6),供内部测试使用。正式发布后安装命令将改为 `npm install -g siluzan-tso-cli`。
|
|
24
24
|
|
|
25
25
|
| 助手 | 建议 `--ai` |
|
|
26
26
|
|------|-------------|
|
package/dist/index.js
CHANGED
|
@@ -1970,11 +1970,11 @@ import * as path from "path";
|
|
|
1970
1970
|
import * as os from "os";
|
|
1971
1971
|
import * as https from "https";
|
|
1972
1972
|
import * as http from "http";
|
|
1973
|
-
import * as os2 from "os";
|
|
1974
1973
|
var import_semver = __toESM(require_semver2(), 1);
|
|
1975
1974
|
import * as fs2 from "fs";
|
|
1976
1975
|
import * as path2 from "path";
|
|
1977
1976
|
import { fileURLToPath } from "url";
|
|
1977
|
+
import * as os2 from "os";
|
|
1978
1978
|
var SILUZAN_DIR = path.join(os.homedir(), ".siluzan");
|
|
1979
1979
|
var CONFIG_FILE = path.join(SILUZAN_DIR, "config.json");
|
|
1980
1980
|
function readStr(raw, key) {
|
|
@@ -2087,6 +2087,110 @@ function rawRequest(url, options) {
|
|
|
2087
2087
|
req.end();
|
|
2088
2088
|
});
|
|
2089
2089
|
}
|
|
2090
|
+
function redactSensitive(input) {
|
|
2091
|
+
let output = input;
|
|
2092
|
+
output = output.replace(/(Bearer\s+)[^\s",]+/gi, "$1***");
|
|
2093
|
+
output = output.replace(
|
|
2094
|
+
/("?(?:apiKey|authToken|accessToken|refreshToken|token|authorization)"?\s*[:=]\s*"?)([^"\s,}]+)/gi,
|
|
2095
|
+
"$1***"
|
|
2096
|
+
);
|
|
2097
|
+
return output;
|
|
2098
|
+
}
|
|
2099
|
+
async function apiFetch(url, config, options = {}, verbose = false) {
|
|
2100
|
+
const method = options.method ?? "GET";
|
|
2101
|
+
const authHeaders = config.apiKey ? { "x-api-key": config.apiKey } : { Authorization: `Bearer ${config.authToken}` };
|
|
2102
|
+
const reqHeaders = {
|
|
2103
|
+
"Content-Type": "application/json",
|
|
2104
|
+
"Accept-Language": "zh-CN",
|
|
2105
|
+
...authHeaders,
|
|
2106
|
+
// dataPermission 仅 TSO 使用;CSO 未设置时为空字符串,服务端忽略该头
|
|
2107
|
+
Datapermission: config.dataPermission ?? "",
|
|
2108
|
+
...options.headers ?? {}
|
|
2109
|
+
};
|
|
2110
|
+
const body = typeof options.body === "string" ? options.body : void 0;
|
|
2111
|
+
const res = await rawRequest(url, {
|
|
2112
|
+
method,
|
|
2113
|
+
headers: reqHeaders,
|
|
2114
|
+
body
|
|
2115
|
+
});
|
|
2116
|
+
const text = res.text;
|
|
2117
|
+
if (res.status < 200 || res.status >= 300) {
|
|
2118
|
+
const detail = verbose ? `\uFF1A${redactSensitive(text).slice(0, 300)}` : "";
|
|
2119
|
+
throw new Error(`HTTP ${res.status}${detail}`);
|
|
2120
|
+
}
|
|
2121
|
+
if (!text.trim()) return null;
|
|
2122
|
+
try {
|
|
2123
|
+
return JSON.parse(text);
|
|
2124
|
+
} catch {
|
|
2125
|
+
if (verbose) {
|
|
2126
|
+
console.error(` \u26A0\uFE0F \u54CD\u5E94\u975E JSON\uFF0C\u539F\u59CB\u5185\u5BB9\uFF1A${redactSensitive(text).slice(0, 200)}`);
|
|
2127
|
+
}
|
|
2128
|
+
return text;
|
|
2129
|
+
}
|
|
2130
|
+
}
|
|
2131
|
+
async function apiFetchWithHeaders(url, config, options = {}, verbose = false) {
|
|
2132
|
+
const method = options.method ?? "GET";
|
|
2133
|
+
const authHeaders = config.apiKey ? { "x-api-key": config.apiKey } : { Authorization: `Bearer ${config.authToken}` };
|
|
2134
|
+
const reqHeaders = {
|
|
2135
|
+
"Content-Type": "application/json",
|
|
2136
|
+
"Accept-Language": "zh-CN",
|
|
2137
|
+
...authHeaders,
|
|
2138
|
+
Datapermission: config.dataPermission ?? "",
|
|
2139
|
+
...options.headers ?? {}
|
|
2140
|
+
};
|
|
2141
|
+
const body = typeof options.body === "string" ? options.body : void 0;
|
|
2142
|
+
const res = await rawRequest(url, { method, headers: reqHeaders, body });
|
|
2143
|
+
const text = res.text;
|
|
2144
|
+
if (res.status < 200 || res.status >= 300) {
|
|
2145
|
+
const detail = verbose ? `\uFF1A${redactSensitive(text).slice(0, 300)}` : "";
|
|
2146
|
+
throw new Error(`HTTP ${res.status}${detail}`);
|
|
2147
|
+
}
|
|
2148
|
+
let data;
|
|
2149
|
+
if (!text.trim()) {
|
|
2150
|
+
data = null;
|
|
2151
|
+
} else {
|
|
2152
|
+
try {
|
|
2153
|
+
data = JSON.parse(text);
|
|
2154
|
+
} catch {
|
|
2155
|
+
data = text;
|
|
2156
|
+
}
|
|
2157
|
+
}
|
|
2158
|
+
return { data, headers: res.headers };
|
|
2159
|
+
}
|
|
2160
|
+
function getCurrentVersion(importMetaUrl) {
|
|
2161
|
+
try {
|
|
2162
|
+
const __dirname3 = path2.dirname(fileURLToPath(importMetaUrl));
|
|
2163
|
+
const pkgPath = path2.join(__dirname3, "..", "package.json");
|
|
2164
|
+
const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf8"));
|
|
2165
|
+
return pkg.version ?? "0.0.0";
|
|
2166
|
+
} catch {
|
|
2167
|
+
return "0.0.0";
|
|
2168
|
+
}
|
|
2169
|
+
}
|
|
2170
|
+
function npmDistTagForCurrentVersion(version) {
|
|
2171
|
+
const v = version.trim().replace(/^v/i, "");
|
|
2172
|
+
return /^\d+\.\d+\.\d+$/.test(v) ? "latest" : "beta";
|
|
2173
|
+
}
|
|
2174
|
+
function npmMinRequiredTagForBuildEnv(buildEnv) {
|
|
2175
|
+
return buildEnv === "test" ? "min-required-beta" : "min-required";
|
|
2176
|
+
}
|
|
2177
|
+
function isNewer(a, b) {
|
|
2178
|
+
return import_semver.default.gt(b, a) === true;
|
|
2179
|
+
}
|
|
2180
|
+
async function fetchNpmVersion(pkgName, tag, timeoutMs = 4e3) {
|
|
2181
|
+
try {
|
|
2182
|
+
const url = `https://registry.npmjs.org/${pkgName}/${tag}`;
|
|
2183
|
+
const controller = new AbortController();
|
|
2184
|
+
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
2185
|
+
const res = await fetch(url, { signal: controller.signal });
|
|
2186
|
+
clearTimeout(timer);
|
|
2187
|
+
if (!res.ok) return null;
|
|
2188
|
+
const data = await res.json();
|
|
2189
|
+
return data.version ?? null;
|
|
2190
|
+
} catch {
|
|
2191
|
+
return null;
|
|
2192
|
+
}
|
|
2193
|
+
}
|
|
2090
2194
|
var DEFAULT_SENTRY_DSN = "https://bafcf42aab6fe7b485310619ae041b5e@o4510436169285632.ingest.us.sentry.io/4511103054708736";
|
|
2091
2195
|
function isSentryDisabled() {
|
|
2092
2196
|
return process.env.SILUZAN_SENTRY_DISABLED === "1" || process.env.SILUZAN_SENTRY_DISABLED === "true";
|
|
@@ -2126,11 +2230,6 @@ function redactCliArgvForSentry(argv) {
|
|
|
2126
2230
|
}
|
|
2127
2231
|
return out.join(" ");
|
|
2128
2232
|
}
|
|
2129
|
-
function isApiTrackingEnabled() {
|
|
2130
|
-
const v = process.env.SILUZAN_SENTRY_TRACKING?.trim().toLowerCase();
|
|
2131
|
-
if (v === "0" || v === "false" || v === "off" || v === "no") return false;
|
|
2132
|
-
return true;
|
|
2133
|
-
}
|
|
2134
2233
|
function setSiluzanCliMeta(name, version) {
|
|
2135
2234
|
cliMeta = { name, version };
|
|
2136
2235
|
if (sentryReady) {
|
|
@@ -2219,178 +2318,6 @@ function inferSiluzanRuntimeEnvironment(requestUrl) {
|
|
|
2219
2318
|
return "production";
|
|
2220
2319
|
}
|
|
2221
2320
|
}
|
|
2222
|
-
function breadcrumbUrl(requestUrl) {
|
|
2223
|
-
try {
|
|
2224
|
-
const u = new URL(requestUrl);
|
|
2225
|
-
return `${u.origin}${u.pathname}`;
|
|
2226
|
-
} catch {
|
|
2227
|
-
return requestUrl.slice(0, 120);
|
|
2228
|
-
}
|
|
2229
|
-
}
|
|
2230
|
-
function trackingPathParts(requestUrl) {
|
|
2231
|
-
try {
|
|
2232
|
-
const u = new URL(requestUrl);
|
|
2233
|
-
return { host: u.hostname.toLowerCase(), pathname: u.pathname || "/" };
|
|
2234
|
-
} catch {
|
|
2235
|
-
return { host: "unknown", pathname: "/" };
|
|
2236
|
-
}
|
|
2237
|
-
}
|
|
2238
|
-
var SENSITIVE_QUERY_KEYS = /* @__PURE__ */ new Set([
|
|
2239
|
-
"token",
|
|
2240
|
-
"password",
|
|
2241
|
-
"api_key",
|
|
2242
|
-
"apikey",
|
|
2243
|
-
"key",
|
|
2244
|
-
"secret",
|
|
2245
|
-
"authorization",
|
|
2246
|
-
"auth"
|
|
2247
|
-
]);
|
|
2248
|
-
function redactUrlForTracking(url) {
|
|
2249
|
-
try {
|
|
2250
|
-
const u = new URL(url);
|
|
2251
|
-
const q = new URLSearchParams(u.search);
|
|
2252
|
-
const out = new URLSearchParams();
|
|
2253
|
-
for (const [k, v] of q.entries()) {
|
|
2254
|
-
out.set(k, SENSITIVE_QUERY_KEYS.has(k.toLowerCase()) ? "[REDACTED]" : v);
|
|
2255
|
-
}
|
|
2256
|
-
const qs = out.toString();
|
|
2257
|
-
return `${u.origin}${u.pathname}${qs ? `?${qs}` : ""}`;
|
|
2258
|
-
} catch {
|
|
2259
|
-
return url.slice(0, 800);
|
|
2260
|
-
}
|
|
2261
|
-
}
|
|
2262
|
-
function redactTrackingHeaders(h) {
|
|
2263
|
-
const out = {};
|
|
2264
|
-
for (const [k, v] of Object.entries(h)) {
|
|
2265
|
-
const low = k.toLowerCase();
|
|
2266
|
-
if (low === "authorization" || low === "x-api-key") {
|
|
2267
|
-
out[k] = "[REDACTED]";
|
|
2268
|
-
} else if (v.length > 2e3) {
|
|
2269
|
-
out[k] = `${v.slice(0, 500)}\u2026[truncated ${v.length} chars]`;
|
|
2270
|
-
} else {
|
|
2271
|
-
out[k] = v;
|
|
2272
|
-
}
|
|
2273
|
-
}
|
|
2274
|
-
return out;
|
|
2275
|
-
}
|
|
2276
|
-
var SENSITIVE_JSON_KEY = /* @__PURE__ */ new Set([
|
|
2277
|
-
"password",
|
|
2278
|
-
"token",
|
|
2279
|
-
"apikey",
|
|
2280
|
-
"api_key",
|
|
2281
|
-
"authorization",
|
|
2282
|
-
"authtoken",
|
|
2283
|
-
"accesstoken",
|
|
2284
|
-
"refreshtoken",
|
|
2285
|
-
"secret",
|
|
2286
|
-
"client_secret",
|
|
2287
|
-
"privatekey",
|
|
2288
|
-
"private_key"
|
|
2289
|
-
]);
|
|
2290
|
-
function deepRedactJson(value, depth) {
|
|
2291
|
-
if (depth > 14) return "[MAX_DEPTH]";
|
|
2292
|
-
if (value === null || typeof value !== "object") return value;
|
|
2293
|
-
if (Array.isArray(value)) {
|
|
2294
|
-
return value.map((v) => deepRedactJson(v, depth + 1));
|
|
2295
|
-
}
|
|
2296
|
-
const o = value;
|
|
2297
|
-
const out = {};
|
|
2298
|
-
for (const [k, v] of Object.entries(o)) {
|
|
2299
|
-
const low = k.toLowerCase().replace(/_/g, "");
|
|
2300
|
-
if (SENSITIVE_JSON_KEY.has(low) || low.includes("password") || low.includes("secret")) {
|
|
2301
|
-
out[k] = "[REDACTED]";
|
|
2302
|
-
} else {
|
|
2303
|
-
out[k] = deepRedactJson(v, depth + 1);
|
|
2304
|
-
}
|
|
2305
|
-
}
|
|
2306
|
-
return out;
|
|
2307
|
-
}
|
|
2308
|
-
function redactPlainTextSnippet(input) {
|
|
2309
|
-
let s = input;
|
|
2310
|
-
s = s.replace(/(Bearer\s+)[^\s'",}]+/gi, "$1***");
|
|
2311
|
-
s = s.replace(
|
|
2312
|
-
/("?(?:apiKey|authToken|accessToken|refreshToken|token|password)"?\s*[:=]\s*"?)([^"\s,}]{4,})/gi,
|
|
2313
|
-
"$1***"
|
|
2314
|
-
);
|
|
2315
|
-
return s;
|
|
2316
|
-
}
|
|
2317
|
-
function trackingBodyMaxChars() {
|
|
2318
|
-
const n = Number(process.env.SILUZAN_SENTRY_BODY_MAX);
|
|
2319
|
-
if (Number.isFinite(n) && n > 256) return Math.min(n, 5e5);
|
|
2320
|
-
return 12e3;
|
|
2321
|
-
}
|
|
2322
|
-
function trackingOmitBodies() {
|
|
2323
|
-
const v = process.env.SILUZAN_SENTRY_NO_API_BODY?.trim().toLowerCase();
|
|
2324
|
-
return v === "1" || v === "true" || v === "yes";
|
|
2325
|
-
}
|
|
2326
|
-
function formatTrackingBody(raw) {
|
|
2327
|
-
if (trackingOmitBodies()) return "[omitted: SILUZAN_SENTRY_NO_API_BODY]";
|
|
2328
|
-
if (raw === void 0 || raw === "") return "";
|
|
2329
|
-
const max = trackingBodyMaxChars();
|
|
2330
|
-
let text;
|
|
2331
|
-
try {
|
|
2332
|
-
const parsed = JSON.parse(raw);
|
|
2333
|
-
text = JSON.stringify(deepRedactJson(parsed, 0));
|
|
2334
|
-
} catch {
|
|
2335
|
-
text = redactPlainTextSnippet(raw);
|
|
2336
|
-
}
|
|
2337
|
-
if (text.length > max) {
|
|
2338
|
-
return `${text.slice(0, max)}\u2026[truncated ${text.length} chars]`;
|
|
2339
|
-
}
|
|
2340
|
-
return text;
|
|
2341
|
-
}
|
|
2342
|
-
async function reportSiluzanApiCall(payload) {
|
|
2343
|
-
if (isSentryDisabled() || !getDsn() || !isApiTrackingEnabled()) return;
|
|
2344
|
-
try {
|
|
2345
|
-
const okInit = await ensureSentryInitialized(payload.url);
|
|
2346
|
-
if (!okInit) return;
|
|
2347
|
-
const Sentry = await import("@sentry/node");
|
|
2348
|
-
const { host, pathname } = trackingPathParts(payload.url);
|
|
2349
|
-
const siluzanEnv = inferSiluzanRuntimeEnvironment(payload.url);
|
|
2350
|
-
const authType = payload.config.apiKey ? "apiKey" : "token";
|
|
2351
|
-
const statusOk = payload.status >= 200 && payload.status < 300;
|
|
2352
|
-
Sentry.captureMessage(
|
|
2353
|
-
`siluzan.cli.api ${payload.method} ${host}${pathname} \u2192 ${payload.status}`,
|
|
2354
|
-
{
|
|
2355
|
-
level: statusOk ? "info" : "warning",
|
|
2356
|
-
tags: {
|
|
2357
|
-
siluzan_tracking: "api",
|
|
2358
|
-
cli: cliMeta.name,
|
|
2359
|
-
cli_version: cliMeta.version,
|
|
2360
|
-
http_method: payload.method,
|
|
2361
|
-
http_host: host,
|
|
2362
|
-
http_status: String(payload.status),
|
|
2363
|
-
siluzan_env: siluzanEnv,
|
|
2364
|
-
auth_type: authType
|
|
2365
|
-
},
|
|
2366
|
-
fingerprint: [
|
|
2367
|
-
"siluzan-cli-api",
|
|
2368
|
-
cliMeta.name,
|
|
2369
|
-
payload.method,
|
|
2370
|
-
host,
|
|
2371
|
-
pathname,
|
|
2372
|
-
statusOk ? "2xx" : payload.status >= 500 ? "5xx" : "4xx"
|
|
2373
|
-
],
|
|
2374
|
-
contexts: {
|
|
2375
|
-
siluzan_cli: {
|
|
2376
|
-
command: cliInvocation || "(pre-action \u672A\u6CE8\u518C\u6216\u5148\u4E8E parse \u53D1\u8D77\u8BF7\u6C42)"
|
|
2377
|
-
},
|
|
2378
|
-
siluzan_request: {
|
|
2379
|
-
url: redactUrlForTracking(payload.url),
|
|
2380
|
-
method: payload.method,
|
|
2381
|
-
headers: redactTrackingHeaders(payload.reqHeaders),
|
|
2382
|
-
body: formatTrackingBody(payload.requestBody)
|
|
2383
|
-
},
|
|
2384
|
-
siluzan_response: {
|
|
2385
|
-
status: payload.status,
|
|
2386
|
-
body: formatTrackingBody(payload.responseText)
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
}
|
|
2390
|
-
);
|
|
2391
|
-
} catch {
|
|
2392
|
-
}
|
|
2393
|
-
}
|
|
2394
2321
|
function cacheKeyForUser(mainOrigin, config) {
|
|
2395
2322
|
const cred = config.apiKey ? `k:${config.apiKey}` : `t:${config.authToken}`;
|
|
2396
2323
|
return `${mainOrigin}\0${cred}`;
|
|
@@ -2478,147 +2405,6 @@ function refreshSiluzanUser(apiBase, config) {
|
|
|
2478
2405
|
}
|
|
2479
2406
|
})();
|
|
2480
2407
|
}
|
|
2481
|
-
async function prepareSiluzanSentryForApiFetch(url, config, options) {
|
|
2482
|
-
if (isSentryDisabled()) return;
|
|
2483
|
-
if (!getDsn()) return;
|
|
2484
|
-
try {
|
|
2485
|
-
const ok = await ensureSentryInitialized(url);
|
|
2486
|
-
if (!ok) return;
|
|
2487
|
-
const Sentry = await import("@sentry/node");
|
|
2488
|
-
const method = options.method ?? "GET";
|
|
2489
|
-
const siluzanEnv = inferSiluzanRuntimeEnvironment(url);
|
|
2490
|
-
const authType = config.apiKey ? "apiKey" : "token";
|
|
2491
|
-
Sentry.addBreadcrumb({
|
|
2492
|
-
category: "siluzan.api",
|
|
2493
|
-
type: "http",
|
|
2494
|
-
level: "info",
|
|
2495
|
-
message: `${method} ${breadcrumbUrl(url)}`,
|
|
2496
|
-
data: {
|
|
2497
|
-
siluzan_env: siluzanEnv,
|
|
2498
|
-
auth_type: authType
|
|
2499
|
-
}
|
|
2500
|
-
});
|
|
2501
|
-
const mainOrigin = deriveMainApiOriginFromRequestUrl(url);
|
|
2502
|
-
if (mainOrigin) {
|
|
2503
|
-
scheduleUserContext(mainOrigin, config);
|
|
2504
|
-
}
|
|
2505
|
-
} catch {
|
|
2506
|
-
}
|
|
2507
|
-
}
|
|
2508
|
-
function redactSensitive(input) {
|
|
2509
|
-
let output = input;
|
|
2510
|
-
output = output.replace(/(Bearer\s+)[^\s",]+/gi, "$1***");
|
|
2511
|
-
output = output.replace(
|
|
2512
|
-
/("?(?:apiKey|authToken|accessToken|refreshToken|token|authorization)"?\s*[:=]\s*"?)([^"\s,}]+)/gi,
|
|
2513
|
-
"$1***"
|
|
2514
|
-
);
|
|
2515
|
-
return output;
|
|
2516
|
-
}
|
|
2517
|
-
async function apiFetch(url, config, options = {}, verbose = false) {
|
|
2518
|
-
const method = options.method ?? "GET";
|
|
2519
|
-
const authHeaders = config.apiKey ? { "x-api-key": config.apiKey } : { Authorization: `Bearer ${config.authToken}` };
|
|
2520
|
-
const reqHeaders = {
|
|
2521
|
-
"Content-Type": "application/json",
|
|
2522
|
-
"Accept-Language": "zh-CN",
|
|
2523
|
-
...authHeaders,
|
|
2524
|
-
// dataPermission 仅 TSO 使用;CSO 未设置时为空字符串,服务端忽略该头
|
|
2525
|
-
Datapermission: config.dataPermission ?? "",
|
|
2526
|
-
...options.headers ?? {}
|
|
2527
|
-
};
|
|
2528
|
-
const body = typeof options.body === "string" ? options.body : void 0;
|
|
2529
|
-
const res = await rawRequest(url, {
|
|
2530
|
-
method,
|
|
2531
|
-
headers: reqHeaders,
|
|
2532
|
-
body
|
|
2533
|
-
});
|
|
2534
|
-
const text = res.text;
|
|
2535
|
-
if (res.status < 200 || res.status >= 300) {
|
|
2536
|
-
const detail = verbose ? `\uFF1A${redactSensitive(text).slice(0, 300)}` : "";
|
|
2537
|
-
throw new Error(`HTTP ${res.status}${detail}`);
|
|
2538
|
-
}
|
|
2539
|
-
if (!text.trim()) return null;
|
|
2540
|
-
try {
|
|
2541
|
-
return JSON.parse(text);
|
|
2542
|
-
} catch {
|
|
2543
|
-
if (verbose) {
|
|
2544
|
-
console.error(` \u26A0\uFE0F \u54CD\u5E94\u975E JSON\uFF0C\u539F\u59CB\u5185\u5BB9\uFF1A${redactSensitive(text).slice(0, 200)}`);
|
|
2545
|
-
}
|
|
2546
|
-
return text;
|
|
2547
|
-
}
|
|
2548
|
-
}
|
|
2549
|
-
async function apiFetchWithHeaders(url, config, options = {}, verbose = false) {
|
|
2550
|
-
await prepareSiluzanSentryForApiFetch(url, config, options);
|
|
2551
|
-
const method = options.method ?? "GET";
|
|
2552
|
-
const authHeaders = config.apiKey ? { "x-api-key": config.apiKey } : { Authorization: `Bearer ${config.authToken}` };
|
|
2553
|
-
const reqHeaders = {
|
|
2554
|
-
"Content-Type": "application/json",
|
|
2555
|
-
"Accept-Language": "zh-CN",
|
|
2556
|
-
...authHeaders,
|
|
2557
|
-
Datapermission: config.dataPermission ?? "",
|
|
2558
|
-
...options.headers ?? {}
|
|
2559
|
-
};
|
|
2560
|
-
const body = typeof options.body === "string" ? options.body : void 0;
|
|
2561
|
-
const res = await rawRequest(url, { method, headers: reqHeaders, body });
|
|
2562
|
-
const text = res.text;
|
|
2563
|
-
await reportSiluzanApiCall({
|
|
2564
|
-
url,
|
|
2565
|
-
config,
|
|
2566
|
-
method,
|
|
2567
|
-
reqHeaders,
|
|
2568
|
-
requestBody: body,
|
|
2569
|
-
status: res.status,
|
|
2570
|
-
responseText: text
|
|
2571
|
-
});
|
|
2572
|
-
if (res.status < 200 || res.status >= 300) {
|
|
2573
|
-
const detail = verbose ? `\uFF1A${redactSensitive(text).slice(0, 300)}` : "";
|
|
2574
|
-
throw new Error(`HTTP ${res.status}${detail}`);
|
|
2575
|
-
}
|
|
2576
|
-
let data;
|
|
2577
|
-
if (!text.trim()) {
|
|
2578
|
-
data = null;
|
|
2579
|
-
} else {
|
|
2580
|
-
try {
|
|
2581
|
-
data = JSON.parse(text);
|
|
2582
|
-
} catch {
|
|
2583
|
-
data = text;
|
|
2584
|
-
}
|
|
2585
|
-
}
|
|
2586
|
-
return { data, headers: res.headers };
|
|
2587
|
-
}
|
|
2588
|
-
function getCurrentVersion(importMetaUrl) {
|
|
2589
|
-
try {
|
|
2590
|
-
const __dirname3 = path2.dirname(fileURLToPath(importMetaUrl));
|
|
2591
|
-
const pkgPath = path2.join(__dirname3, "..", "package.json");
|
|
2592
|
-
const pkg = JSON.parse(fs2.readFileSync(pkgPath, "utf8"));
|
|
2593
|
-
return pkg.version ?? "0.0.0";
|
|
2594
|
-
} catch {
|
|
2595
|
-
return "0.0.0";
|
|
2596
|
-
}
|
|
2597
|
-
}
|
|
2598
|
-
function npmDistTagForCurrentVersion(version) {
|
|
2599
|
-
const v = version.trim().replace(/^v/i, "");
|
|
2600
|
-
return /^\d+\.\d+\.\d+$/.test(v) ? "latest" : "beta";
|
|
2601
|
-
}
|
|
2602
|
-
function npmMinRequiredTagForBuildEnv(buildEnv) {
|
|
2603
|
-
return buildEnv === "test" ? "min-required-beta" : "min-required";
|
|
2604
|
-
}
|
|
2605
|
-
function isNewer(a, b) {
|
|
2606
|
-
return import_semver.default.gt(b, a) === true;
|
|
2607
|
-
}
|
|
2608
|
-
async function fetchNpmVersion(pkgName, tag, timeoutMs = 4e3) {
|
|
2609
|
-
try {
|
|
2610
|
-
const url = `https://registry.npmjs.org/${pkgName}/${tag}`;
|
|
2611
|
-
const controller = new AbortController();
|
|
2612
|
-
const timer = setTimeout(() => controller.abort(), timeoutMs);
|
|
2613
|
-
const res = await fetch(url, { signal: controller.signal });
|
|
2614
|
-
clearTimeout(timer);
|
|
2615
|
-
if (!res.ok) return null;
|
|
2616
|
-
const data = await res.json();
|
|
2617
|
-
return data.version ?? null;
|
|
2618
|
-
} catch {
|
|
2619
|
-
return null;
|
|
2620
|
-
}
|
|
2621
|
-
}
|
|
2622
2408
|
|
|
2623
2409
|
// src/utils/version.ts
|
|
2624
2410
|
import * as fs3 from "fs";
|
package/dist/skill/_meta.json
CHANGED