ali-skills 0.0.25 → 0.0.26
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.
|
@@ -2340,7 +2340,7 @@ function logSkillParseFailures(failures) {
|
|
|
2340
2340
|
if (f.hint) M.message(import_picocolors.default.yellow(` 提示: ${f.hint}`));
|
|
2341
2341
|
}
|
|
2342
2342
|
}
|
|
2343
|
-
var version$1 = "2.0.
|
|
2343
|
+
var version$1 = "2.0.27";
|
|
2344
2344
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
2345
2345
|
function redactSensitiveText(text) {
|
|
2346
2346
|
return text.replace(/(https?:\/\/)([^/\s:@]+)(?::([^@/\s]*))?@/gi, "$1").replace(/([?&](?:private_token|access_token|token|api_key|access_key|secret|password)=)[^&\s]+/gi, "$1***");
|
|
@@ -2531,6 +2531,18 @@ async function selectAgentsInteractive(options) {
|
|
|
2531
2531
|
return [];
|
|
2532
2532
|
}
|
|
2533
2533
|
setVersion(version$1);
|
|
2534
|
+
function isCiEnvironment() {
|
|
2535
|
+
if (process.env.CI) return true;
|
|
2536
|
+
if (process.env.GITHUB_ACTIONS) return true;
|
|
2537
|
+
if (process.env.GITLAB_CI) return true;
|
|
2538
|
+
if (process.env.BUILDKITE) return true;
|
|
2539
|
+
if (process.env.JENKINS_URL) return true;
|
|
2540
|
+
return false;
|
|
2541
|
+
}
|
|
2542
|
+
function resolveInstallMode(options) {
|
|
2543
|
+
if (options.installMode) return options.installMode;
|
|
2544
|
+
return options.copy ? "copy" : "symlink";
|
|
2545
|
+
}
|
|
2534
2546
|
async function handleWellKnownSkills(source, url, options, spinner) {
|
|
2535
2547
|
spinner.start("Discovering skills from well-known endpoint...");
|
|
2536
2548
|
const skills = await wellKnownProvider.fetchAllSkills(url);
|
|
@@ -2661,8 +2673,8 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2661
2673
|
}
|
|
2662
2674
|
installGlobally = scope;
|
|
2663
2675
|
}
|
|
2664
|
-
let installMode = options
|
|
2665
|
-
if (!options.copy && !options.yes) {
|
|
2676
|
+
let installMode = resolveInstallMode(options);
|
|
2677
|
+
if (!options.installMode && !options.copy && !options.yes) {
|
|
2666
2678
|
const modeChoice = await ve({
|
|
2667
2679
|
message: "Installation method",
|
|
2668
2680
|
options: getInstallMethodOptions()
|
|
@@ -2819,6 +2831,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2819
2831
|
async function runAdd(args, options = {}) {
|
|
2820
2832
|
const source = args[0];
|
|
2821
2833
|
let installTipShown = false;
|
|
2834
|
+
const ciMode = options.ci ?? isCiEnvironment();
|
|
2822
2835
|
const showInstallTip = () => {
|
|
2823
2836
|
if (installTipShown) return;
|
|
2824
2837
|
M.message(import_picocolors.default.dim("Tip: use the --yes (-y) and --global (-g) flags to install without prompts."));
|
|
@@ -2836,6 +2849,7 @@ async function runAdd(args, options = {}) {
|
|
|
2836
2849
|
console.log();
|
|
2837
2850
|
process.exit(1);
|
|
2838
2851
|
}
|
|
2852
|
+
if (ciMode && !options.yes) options.yes = true;
|
|
2839
2853
|
if (options.all) {
|
|
2840
2854
|
options.skill = ["*"];
|
|
2841
2855
|
options.agent = ["*"];
|
|
@@ -3161,8 +3175,8 @@ async function runAdd(args, options = {}) {
|
|
|
3161
3175
|
}
|
|
3162
3176
|
installGlobally = scope;
|
|
3163
3177
|
}
|
|
3164
|
-
let installMode = options
|
|
3165
|
-
if (!options.copy && !options.yes) {
|
|
3178
|
+
let installMode = resolveInstallMode(options);
|
|
3179
|
+
if (!options.installMode && !options.copy && !options.yes) {
|
|
3166
3180
|
const modeChoice = await ve({
|
|
3167
3181
|
message: "Installation method",
|
|
3168
3182
|
options: getInstallMethodOptions()
|
|
@@ -3498,6 +3512,12 @@ async function promptForFindSkills(options, targetAgents) {
|
|
|
3498
3512
|
function parseAddOptions(args) {
|
|
3499
3513
|
const options = {};
|
|
3500
3514
|
const source = [];
|
|
3515
|
+
const installModes = [
|
|
3516
|
+
"symlink",
|
|
3517
|
+
"copy",
|
|
3518
|
+
"symlink-isolated",
|
|
3519
|
+
"copy-isolated"
|
|
3520
|
+
];
|
|
3501
3521
|
for (let i = 0; i < args.length; i++) {
|
|
3502
3522
|
const arg = args[i];
|
|
3503
3523
|
if (arg === "-g" || arg === "--global") options.global = true;
|
|
@@ -3531,7 +3551,13 @@ function parseAddOptions(args) {
|
|
|
3531
3551
|
options.branch = args[i];
|
|
3532
3552
|
} else if (arg === "--full-depth") options.fullDepth = true;
|
|
3533
3553
|
else if (arg === "--copy") options.copy = true;
|
|
3534
|
-
else if (arg
|
|
3554
|
+
else if (arg === "--ci") options.ci = true;
|
|
3555
|
+
else if (arg === "--install-mode") {
|
|
3556
|
+
i++;
|
|
3557
|
+
const mode = args[i];
|
|
3558
|
+
if (!mode || !installModes.includes(mode)) throw new Error(`Invalid value for --install-mode: ${mode ?? "(empty)"} (expected: symlink, copy, symlink-isolated, copy-isolated)`);
|
|
3559
|
+
options.installMode = mode;
|
|
3560
|
+
} else if (arg && !arg.startsWith("-")) source.push(arg);
|
|
3535
3561
|
}
|
|
3536
3562
|
return {
|
|
3537
3563
|
source,
|
|
@@ -4720,6 +4746,10 @@ function readConfig() {
|
|
|
4720
4746
|
function saveConfig(config) {
|
|
4721
4747
|
safeWriteFile(CONFIG_FILE, JSON.stringify(config, null, 2));
|
|
4722
4748
|
}
|
|
4749
|
+
function getSsoRefreshCookieTtlMs() {
|
|
4750
|
+
const sec = Number(process.env.ALI_SKILLS_SSO_REFRESH_COOKIE_TTL_SECONDS?.trim() || process.env.BUC_SSO_REFRESH_COOKIE_TTL_SECONDS?.trim() || "7200");
|
|
4751
|
+
return (Number.isFinite(sec) && sec > 0 ? sec : 7200) * 1e3;
|
|
4752
|
+
}
|
|
4723
4753
|
function readAuth() {
|
|
4724
4754
|
try {
|
|
4725
4755
|
if (!existsSync(AUTH_FILE)) return null;
|
|
@@ -4951,6 +4981,9 @@ function startLocalServer() {
|
|
|
4951
4981
|
const name = url.searchParams.get("name") || "";
|
|
4952
4982
|
const privateToken = url.searchParams.get("private_token") || "";
|
|
4953
4983
|
const ssoRefreshToken = url.searchParams.get("sso_refresh_token") || "";
|
|
4984
|
+
const ssoRtExpRaw = url.searchParams.get("sso_refresh_token_expires_at") || "";
|
|
4985
|
+
const ssoRtExpSec = parseInt(ssoRtExpRaw, 10);
|
|
4986
|
+
const ssoRefreshTokenExpiresAtMs = ssoRefreshToken && ssoRtExpRaw !== "" && Number.isFinite(ssoRtExpSec) && ssoRtExpSec > 0 ? ssoRtExpSec * 1e3 : void 0;
|
|
4954
4987
|
const expiresAt = url.searchParams.get("expires_at") || "0";
|
|
4955
4988
|
if (!empId || !privateToken) {
|
|
4956
4989
|
res.writeHead(400, { "Content-Type": "text/html" });
|
|
@@ -5107,6 +5140,7 @@ function startLocalServer() {
|
|
|
5107
5140
|
name,
|
|
5108
5141
|
privateToken,
|
|
5109
5142
|
ssoRefreshToken,
|
|
5143
|
+
ssoRefreshTokenExpiresAtMs,
|
|
5110
5144
|
expiresAt: parseInt(expiresAt, 10)
|
|
5111
5145
|
});
|
|
5112
5146
|
setTimeout(() => server.close(), 1e3);
|
|
@@ -5132,13 +5166,51 @@ function openBrowser$2(url) {
|
|
|
5132
5166
|
stdio: "ignore"
|
|
5133
5167
|
});
|
|
5134
5168
|
}
|
|
5135
|
-
async function
|
|
5136
|
-
|
|
5137
|
-
|
|
5138
|
-
|
|
5139
|
-
|
|
5140
|
-
|
|
5141
|
-
|
|
5169
|
+
async function revokeGatewaySessionIfPossible(auth) {
|
|
5170
|
+
try {
|
|
5171
|
+
const revokeUrl = `${auth.gatewayUrl || getGatewayUrl()}/api/gateway/revoke`;
|
|
5172
|
+
const revokeRes = await fetch(revokeUrl, {
|
|
5173
|
+
method: "POST",
|
|
5174
|
+
headers: { "X-Private-Token": auth.privateToken }
|
|
5175
|
+
});
|
|
5176
|
+
if (revokeRes.ok) console.log(`${GREEN$2}✓ 已撤销当前网关会话${RESET$3}`);
|
|
5177
|
+
else if (revokeRes.status === 404) console.log(`${DIM$3}服务端暂不支持撤销网关会话,继续本机登出${RESET$3}`);
|
|
5178
|
+
else console.log(`${YELLOW$3}⚠️ 撤销网关会话失败,继续本机登出${RESET$3}`);
|
|
5179
|
+
} catch {
|
|
5180
|
+
console.log(`${YELLOW$3}⚠️ 撤销网关会话失败,继续本机登出${RESET$3}`);
|
|
5181
|
+
}
|
|
5182
|
+
}
|
|
5183
|
+
function getEffectiveSsoRefreshCookieExpiresAtMs(auth) {
|
|
5184
|
+
if (!auth.ssoRefreshToken?.trim()) return null;
|
|
5185
|
+
if (typeof auth.ssoRefreshTokenExpiresAt === "number" && auth.ssoRefreshTokenExpiresAt > 0) return auth.ssoRefreshTokenExpiresAt;
|
|
5186
|
+
if (typeof auth.ssoRefreshTokenFetchedAt === "number" && auth.ssoRefreshTokenFetchedAt > 0) return auth.ssoRefreshTokenFetchedAt + getSsoRefreshCookieTtlMs();
|
|
5187
|
+
return null;
|
|
5188
|
+
}
|
|
5189
|
+
function exitIfSsoRefreshCookieExpired(auth, opts) {
|
|
5190
|
+
const exp = getEffectiveSsoRefreshCookieExpiresAtMs(auth);
|
|
5191
|
+
if (exp === null) return;
|
|
5192
|
+
if (Date.now() < exp) return;
|
|
5193
|
+
if (!opts?.quiet) {
|
|
5194
|
+
console.error(`${YELLOW$3}SSO_REFRESH_TOKEN 已超过预估有效期,根域 cookie 直连会鉴权失败${RESET$3}`);
|
|
5195
|
+
console.log(`${DIM$3}请执行: npx ali-skills login --reauth${RESET$3}`);
|
|
5196
|
+
}
|
|
5197
|
+
process.exit(1);
|
|
5198
|
+
}
|
|
5199
|
+
async function login(options) {
|
|
5200
|
+
if (options?.reauth) {
|
|
5201
|
+
const auth = readAuth();
|
|
5202
|
+
if (auth) {
|
|
5203
|
+
await revokeGatewaySessionIfPossible(auth);
|
|
5204
|
+
removeAuth();
|
|
5205
|
+
}
|
|
5206
|
+
} else {
|
|
5207
|
+
const existingAuth = readAuth();
|
|
5208
|
+
if (existingAuth && !isAuthExpired(existingAuth)) {
|
|
5209
|
+
console.log(`${YELLOW$3}! 您已经登录为: ${existingAuth.name} (${existingAuth.account})${RESET$3}`);
|
|
5210
|
+
console.log();
|
|
5211
|
+
console.log(`${DIM$3}如需重新登录,请执行: npx ali-skills login --reauth${RESET$3}`);
|
|
5212
|
+
return;
|
|
5213
|
+
}
|
|
5142
5214
|
}
|
|
5143
5215
|
console.log(`${TEXT$3}正在启动本地服务...${RESET$3}`);
|
|
5144
5216
|
const { port, waitForCallback, close } = await startLocalServer();
|
|
@@ -5151,7 +5223,9 @@ async function login() {
|
|
|
5151
5223
|
openBrowser$2(loginUrl);
|
|
5152
5224
|
console.log(`${TEXT$3}等待授权完成...${RESET$3}`);
|
|
5153
5225
|
try {
|
|
5154
|
-
const { empId, account, name, privateToken, ssoRefreshToken, expiresAt } = await waitForCallback();
|
|
5226
|
+
const { empId, account, name, privateToken, ssoRefreshToken, ssoRefreshTokenExpiresAtMs, expiresAt } = await waitForCallback();
|
|
5227
|
+
let ssoRtExpStored;
|
|
5228
|
+
if (ssoRefreshToken) ssoRtExpStored = ssoRefreshTokenExpiresAtMs ?? Date.now() + getSsoRefreshCookieTtlMs();
|
|
5155
5229
|
saveAuth({
|
|
5156
5230
|
empId,
|
|
5157
5231
|
account,
|
|
@@ -5161,13 +5235,19 @@ async function login() {
|
|
|
5161
5235
|
ssoRefreshToken,
|
|
5162
5236
|
ssoRefreshTokenFetchedAt: ssoRefreshToken ? Date.now() : void 0,
|
|
5163
5237
|
ssoRefreshTokenLastCheckedAt: ssoRefreshToken ? Date.now() : void 0,
|
|
5238
|
+
ssoRefreshTokenExpiresAt: ssoRtExpStored,
|
|
5164
5239
|
expiresAt: expiresAt * 1e3
|
|
5165
5240
|
});
|
|
5166
5241
|
console.log();
|
|
5167
5242
|
console.log(`${GREEN$2}✓ 登录成功!${RESET$3}`);
|
|
5168
5243
|
console.log(`${TEXT$3}欢迎: ${name} (${account})${RESET$3}`);
|
|
5169
5244
|
console.log(`${DIM$3}Token 有效期至: ${(/* @__PURE__ */ new Date(expiresAt * 1e3)).toLocaleDateString()}${RESET$3}`);
|
|
5170
|
-
if (
|
|
5245
|
+
if (ssoRefreshToken && ssoRtExpStored) console.log(`${DIM$3}SSO_REFRESH 预估过期: ${new Date(ssoRtExpStored).toLocaleString()}${RESET$3}`);
|
|
5246
|
+
if (!ssoRefreshToken) {
|
|
5247
|
+
console.log();
|
|
5248
|
+
console.log(`${YELLOW$3}⚠ SSO_REFRESH_TOKEN 获取异常:本次授权回调未携带该凭证,网关代理等依赖 SSO Cookie 的能力可能不可用${RESET$3}`);
|
|
5249
|
+
console.log(`${DIM$3}可尝试:在网页端(https://ali-skills.alibaba-inc.com)退出平台登录后重新执行 login 命令。同时请将此问题反馈给本工具开发者处理,感谢!${RESET$3}`);
|
|
5250
|
+
}
|
|
5171
5251
|
} catch (error) {
|
|
5172
5252
|
close();
|
|
5173
5253
|
throw error;
|
|
@@ -5262,18 +5342,7 @@ async function logout(platformInput, yuqueGroup, clearAll) {
|
|
|
5262
5342
|
return;
|
|
5263
5343
|
}
|
|
5264
5344
|
try {
|
|
5265
|
-
|
|
5266
|
-
const revokeUrl = `${getGatewayUrl()}/api/gateway/revoke`;
|
|
5267
|
-
const revokeRes = await fetch(revokeUrl, {
|
|
5268
|
-
method: "POST",
|
|
5269
|
-
headers: { "X-Private-Token": auth.privateToken }
|
|
5270
|
-
});
|
|
5271
|
-
if (revokeRes.ok) console.log(`${GREEN$2}✓ 已撤销当前网关会话${RESET$3}`);
|
|
5272
|
-
else if (revokeRes.status === 404) console.log(`${DIM$3}服务端暂不支持撤销网关会话,继续本机登出${RESET$3}`);
|
|
5273
|
-
else console.log(`${YELLOW$3}⚠️ 撤销网关会话失败,继续本机登出${RESET$3}`);
|
|
5274
|
-
} catch {
|
|
5275
|
-
console.log(`${YELLOW$3}⚠️ 撤销网关会话失败,继续本机登出${RESET$3}`);
|
|
5276
|
-
}
|
|
5345
|
+
await revokeGatewaySessionIfPossible(auth);
|
|
5277
5346
|
removeAuth();
|
|
5278
5347
|
console.log(`${GREEN$2}✓ 已登出${RESET$3}`);
|
|
5279
5348
|
} catch (error) {
|
|
@@ -5433,6 +5502,11 @@ async function status(args = {}) {
|
|
|
5433
5502
|
console.log(` 工号: ${auth.empId}`);
|
|
5434
5503
|
console.log(` 网关: ${getGatewayUrl()}`);
|
|
5435
5504
|
console.log(` SSO_REFRESH_TOKEN: ${auth.ssoRefreshToken ? `${GREEN$2}已缓存${RESET$3}` : `${YELLOW$3}未缓存${RESET$3}`}`);
|
|
5505
|
+
const ssoRtExp = getEffectiveSsoRefreshCookieExpiresAtMs(auth);
|
|
5506
|
+
if (auth.ssoRefreshToken && ssoRtExp) {
|
|
5507
|
+
const rtDead = Date.now() >= ssoRtExp;
|
|
5508
|
+
console.log(` SSO_REFRESH 预估过期: ${new Date(ssoRtExp).toLocaleString()}${rtDead ? ` ${YELLOW$3}(已过期)${RESET$3}` : ""}`);
|
|
5509
|
+
} else if (auth.ssoRefreshToken) console.log(` SSO_REFRESH 预估过期: ${YELLOW$3}未知${RESET$3} ${DIM$3}(可 login --reauth 重新写入)${RESET$3}`);
|
|
5436
5510
|
if (expired) {
|
|
5437
5511
|
console.log(` Token: ${YELLOW$3}即将过期${RESET$3}`);
|
|
5438
5512
|
console.log(`${TEXT$3}建议重新登录: npx ali-skills login${RESET$3}`);
|
|
@@ -5461,13 +5535,14 @@ async function ensureSsoRefreshToken() {
|
|
|
5461
5535
|
});
|
|
5462
5536
|
if (response.status === 200) {
|
|
5463
5537
|
const data = await response.json();
|
|
5538
|
+
const mergedRtExp = typeof data.ssoRefreshTokenExpiresAt === "number" && data.ssoRefreshTokenExpiresAt > 0 ? data.ssoRefreshTokenExpiresAt : Date.now() + getSsoRefreshCookieTtlMs();
|
|
5464
5539
|
saveAuth({
|
|
5465
5540
|
...auth,
|
|
5466
5541
|
gatewayUrl: auth.gatewayUrl || getGatewayUrl(),
|
|
5467
5542
|
ssoRefreshToken: data.ssoRefreshToken,
|
|
5468
5543
|
ssoRefreshTokenFetchedAt: Date.now(),
|
|
5469
5544
|
ssoRefreshTokenLastCheckedAt: Date.now(),
|
|
5470
|
-
ssoRefreshTokenExpiresAt:
|
|
5545
|
+
ssoRefreshTokenExpiresAt: mergedRtExp
|
|
5471
5546
|
});
|
|
5472
5547
|
console.log(`${DIM$3}已从服务端获取 SSO_REFRESH_TOKEN${RESET$3}`);
|
|
5473
5548
|
return data.ssoRefreshToken;
|
|
@@ -5768,6 +5843,13 @@ async function sendDirectRequest(targetUrl, platform, token, options) {
|
|
|
5768
5843
|
if (!response.ok) process.exit(1);
|
|
5769
5844
|
}
|
|
5770
5845
|
async function sendSsoCookieDirectRequest(targetUrl, options) {
|
|
5846
|
+
const printReauthAndRetryHint = (location, forceStderr = false) => {
|
|
5847
|
+
const log = forceStderr ? console.error : console.log;
|
|
5848
|
+
log(`${YELLOW$2}检测到被重定向到登录页,当前 SSO_REFRESH_TOKEN 很可能已失效${RESET$2}`);
|
|
5849
|
+
if (location) log(`${DIM$2}Location: ${location}${RESET$2}`);
|
|
5850
|
+
log(`${TEXT$2}请先执行: npx ali-skills login --reauth(刷新 SSO_REFRESH_TOKEN)${RESET$2}`);
|
|
5851
|
+
log(`${TEXT$2}刷新后请重新发起当前请求${RESET$2}`);
|
|
5852
|
+
};
|
|
5771
5853
|
let ssoRefreshToken = null;
|
|
5772
5854
|
try {
|
|
5773
5855
|
await ensureLogin();
|
|
@@ -5785,6 +5867,8 @@ async function sendSsoCookieDirectRequest(targetUrl, options) {
|
|
|
5785
5867
|
console.log(`${TEXT$2}建议执行: npx ali-skills login${RESET$2}`);
|
|
5786
5868
|
process.exit(1);
|
|
5787
5869
|
}
|
|
5870
|
+
const authForRt = readAuth();
|
|
5871
|
+
if (authForRt) exitIfSsoRefreshCookieExpired(authForRt, { quiet: options.quiet });
|
|
5788
5872
|
const requestHeaders = {
|
|
5789
5873
|
"User-Agent": "ali-skills-cli/1.0",
|
|
5790
5874
|
Cookie: `SSO_REFRESH_TOKEN=${ssoRefreshToken}`
|
|
@@ -5804,7 +5888,7 @@ async function sendSsoCookieDirectRequest(targetUrl, options) {
|
|
|
5804
5888
|
const controller = new AbortController();
|
|
5805
5889
|
const timeout = options.timeout || 3e4;
|
|
5806
5890
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
5807
|
-
const { response, responseBody } = await fetchWithRedirects(targetUrl, options.method.toUpperCase(), requestHeaders, body, timeout, options.quiet);
|
|
5891
|
+
const { response, responseBody, loginRedirectUrl } = await fetchWithRedirects(targetUrl, options.method.toUpperCase(), requestHeaders, body, timeout, options.quiet, { stopOnAlibabaLoginRedirect: true });
|
|
5808
5892
|
clearTimeout(timeoutId);
|
|
5809
5893
|
if (!options.quiet) {
|
|
5810
5894
|
const statusColor = response.ok ? GREEN$1 : RED$2;
|
|
@@ -5816,7 +5900,15 @@ async function sendSsoCookieDirectRequest(targetUrl, options) {
|
|
|
5816
5900
|
console.log(`${DIM$2} 2. 目标服务未启用该认证链路${RESET$2}`);
|
|
5817
5901
|
console.log(`${DIM$2} 3. 当前账号在目标系统无访问权限${RESET$2}`);
|
|
5818
5902
|
console.log(`${TEXT$2}建议: 重新登录后重试,或联系目标系统确认登录态策略${RESET$2}`);
|
|
5819
|
-
}
|
|
5903
|
+
} else if (loginRedirectUrl) printReauthAndRetryHint(loginRedirectUrl);
|
|
5904
|
+
}
|
|
5905
|
+
if (options.includeHeaders) {
|
|
5906
|
+
console.log();
|
|
5907
|
+
console.log(`${TEXT$2}Response Headers:${RESET$2}`);
|
|
5908
|
+
response.headers.forEach((value, key) => {
|
|
5909
|
+
console.log(` ${key}: ${value}`);
|
|
5910
|
+
});
|
|
5911
|
+
console.log();
|
|
5820
5912
|
}
|
|
5821
5913
|
let outputBody = responseBody;
|
|
5822
5914
|
if (!options.raw && options.pretty !== false) try {
|
|
@@ -5827,7 +5919,14 @@ async function sendSsoCookieDirectRequest(targetUrl, options) {
|
|
|
5827
5919
|
const { writeFileSync } = __require("fs");
|
|
5828
5920
|
writeFileSync(options.output, outputBody);
|
|
5829
5921
|
console.log(`${GREEN$1}✓ 已保存到 ${options.output}${RESET$2}`);
|
|
5830
|
-
} else
|
|
5922
|
+
} else {
|
|
5923
|
+
if (options.quiet && !response.ok && outputBody.trim().length === 0 && (loginRedirectUrl || response.headers.get("location"))) {
|
|
5924
|
+
const location = loginRedirectUrl || response.headers.get("location") || "(empty)";
|
|
5925
|
+
console.error(`HTTP ${response.status} ${response.statusText} (Location: ${location})`);
|
|
5926
|
+
printReauthAndRetryHint(location, true);
|
|
5927
|
+
}
|
|
5928
|
+
console.log(outputBody);
|
|
5929
|
+
}
|
|
5831
5930
|
if (!response.ok) process.exit(1);
|
|
5832
5931
|
}
|
|
5833
5932
|
async function sendSsoTicketDirectRequest(targetUrl, options) {
|
|
@@ -5932,7 +6031,7 @@ async function sendPlainDirectRequest(targetUrl, options, allowSsoCookieFallback
|
|
|
5932
6031
|
} else console.log(outputBody);
|
|
5933
6032
|
if (!response.ok) process.exit(1);
|
|
5934
6033
|
}
|
|
5935
|
-
async function fetchWithRedirects(initialUrl, method, headers, body, timeout, quiet) {
|
|
6034
|
+
async function fetchWithRedirects(initialUrl, method, headers, body, timeout, quiet, opts) {
|
|
5936
6035
|
const controller = new AbortController();
|
|
5937
6036
|
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
|
5938
6037
|
let currentUrl = initialUrl;
|
|
@@ -5960,7 +6059,15 @@ async function fetchWithRedirects(initialUrl, method, headers, body, timeout, qu
|
|
|
5960
6059
|
};
|
|
5961
6060
|
if (redirects >= MAX_REDIRECTS) throw new Error(`重定向次数超过上限(${MAX_REDIRECTS})`);
|
|
5962
6061
|
const nextUrl = new URL(location, currentUrl).toString();
|
|
5963
|
-
if (new URL(nextUrl).hostname === "login.alibaba-inc.com")
|
|
6062
|
+
if (new URL(nextUrl).hostname === "login.alibaba-inc.com") {
|
|
6063
|
+
sawAlibabaLoginRedirect = true;
|
|
6064
|
+
if (opts?.stopOnAlibabaLoginRedirect) return {
|
|
6065
|
+
response,
|
|
6066
|
+
responseBody: await response.text(),
|
|
6067
|
+
sawAlibabaLoginRedirect,
|
|
6068
|
+
loginRedirectUrl: nextUrl
|
|
6069
|
+
};
|
|
6070
|
+
}
|
|
5964
6071
|
redirects += 1;
|
|
5965
6072
|
if (!quiet) console.log(`${DIM$2}↪ 重定向 ${redirects}: ${response.status} ${response.statusText} -> ${nextUrl}${RESET$2}`);
|
|
5966
6073
|
currentUrl = nextUrl;
|
|
@@ -6519,9 +6626,6 @@ ${BOLD}Manage Skills:${RESET}
|
|
|
6519
6626
|
list, ls List installed skills
|
|
6520
6627
|
find [query] Search for skills interactively
|
|
6521
6628
|
|
|
6522
|
-
${BOLD}Publish:${RESET}
|
|
6523
|
-
publish [options] Publish skills from current repo to OSS (alias: pub)
|
|
6524
|
-
|
|
6525
6629
|
${BOLD}Updates:${RESET}
|
|
6526
6630
|
check Check for available skill updates (project-level by default)
|
|
6527
6631
|
check -g Check global skill updates
|
|
@@ -6532,9 +6636,7 @@ ${BOLD}Updates:${RESET}
|
|
|
6532
6636
|
update <skill> Update specific skill(s)
|
|
6533
6637
|
|
|
6534
6638
|
${BOLD}Project:${RESET}
|
|
6535
|
-
experimental_install Restore skills from skills-lock.json
|
|
6536
6639
|
init [name] Initialize a skill (creates <name>/SKILL.md or ./SKILL.md)
|
|
6537
|
-
experimental_sync Sync skills from node_modules into agent directories
|
|
6538
6640
|
|
|
6539
6641
|
${BOLD}Gateway:${RESET}
|
|
6540
6642
|
gateway 鉴权请求能力入口(login/logout/status/req)
|
|
@@ -6548,8 +6650,10 @@ ${BOLD}Add Options:${RESET}
|
|
|
6548
6650
|
-s, --skill <skills> Specify skill names to install (use '*' for all skills)
|
|
6549
6651
|
-l, --list List available skills in the repository without installing
|
|
6550
6652
|
-y, --yes Skip confirmation prompts
|
|
6653
|
+
--ci Enable CI mode (auto non-interactive, implies --yes)
|
|
6551
6654
|
--github Force fetching from GitHub when using owner/repo shorthand
|
|
6552
|
-
--
|
|
6655
|
+
--install-mode <mode> Install mode: symlink|copy|symlink-isolated|copy-isolated (default: symlink)
|
|
6656
|
+
--copy Backward-compatible alias of --install-mode copy (recommended: use --install-mode)
|
|
6553
6657
|
--all Shorthand for --skill '*' --agent '*' -y
|
|
6554
6658
|
--full-depth Search all subdirectories even when a root SKILL.md exists
|
|
6555
6659
|
|
|
@@ -6560,10 +6664,6 @@ ${BOLD}Remove Options:${RESET}
|
|
|
6560
6664
|
-y, --yes Skip confirmation prompts
|
|
6561
6665
|
--all Shorthand for --skill '*' --agent '*' -y
|
|
6562
6666
|
|
|
6563
|
-
${BOLD}Experimental Sync Options:${RESET}
|
|
6564
|
-
-a, --agent <agents> Specify agents to install to (use '*' for all agents)
|
|
6565
|
-
-y, --yes Skip confirmation prompts
|
|
6566
|
-
|
|
6567
6667
|
${BOLD}List Options:${RESET}
|
|
6568
6668
|
-g, --global List global skills (default: project)
|
|
6569
6669
|
-a, --agent <agents> Filter by specific agents
|
|
@@ -6573,14 +6673,12 @@ ${BOLD}Options:${RESET}
|
|
|
6573
6673
|
--help, -h Show this help message
|
|
6574
6674
|
--version, -v Show version number
|
|
6575
6675
|
|
|
6576
|
-
${BOLD}Debug:${RESET}
|
|
6577
|
-
ALI_SKILLS_DEBUG_UPDATE=1 Print detailed logs for check/update diagnosis
|
|
6578
|
-
|
|
6579
6676
|
${BOLD}Examples:${RESET}
|
|
6580
6677
|
${DIM}$${RESET} ali-skills add group/project
|
|
6581
6678
|
${DIM}$${RESET} ali-skills add group/project -g
|
|
6582
6679
|
${DIM}$${RESET} ali-skills add group/project --agent claude-code cursor
|
|
6583
6680
|
${DIM}$${RESET} ali-skills add group/project --skill pr-review commit
|
|
6681
|
+
${DIM}$${RESET} ali-skills add group/project --install-mode symlink-isolated
|
|
6584
6682
|
${DIM}$${RESET} ali-skills remove ${DIM}# interactive remove${RESET}
|
|
6585
6683
|
${DIM}$${RESET} ali-skills remove web-design ${DIM}# remove by name${RESET}
|
|
6586
6684
|
${DIM}$${RESET} ali-skills rm --global frontend-design
|
|
@@ -6593,10 +6691,7 @@ ${BOLD}Examples:${RESET}
|
|
|
6593
6691
|
${DIM}$${RESET} ali-skills check
|
|
6594
6692
|
${DIM}$${RESET} ali-skills check web-design react-best-practices
|
|
6595
6693
|
${DIM}$${RESET} ali-skills update
|
|
6596
|
-
${DIM}$${RESET} ali-skills experimental_install ${DIM}# restore from skills-lock.json${RESET}
|
|
6597
6694
|
${DIM}$${RESET} ali-skills init my-skill
|
|
6598
|
-
${DIM}$${RESET} ali-skills experimental_sync ${DIM}# sync from node_modules${RESET}
|
|
6599
|
-
${DIM}$${RESET} ali-skills experimental_sync -y ${DIM}# sync without prompts${RESET}
|
|
6600
6695
|
|
|
6601
6696
|
Discover more skills at ${TEXT}https://ali-skills.alibaba-inc.com/${RESET}
|
|
6602
6697
|
`);
|
|
@@ -6636,7 +6731,7 @@ function showGatewayHelp() {
|
|
|
6636
6731
|
const platformKeysForHelp = listPlatforms().filter((p) => p.key !== "aone").map((p) => p.key).join(", ");
|
|
6637
6732
|
console.log(`
|
|
6638
6733
|
${BOLD}Gateway Commands:${RESET}
|
|
6639
|
-
login [platform]
|
|
6734
|
+
login [--reauth] [platform] Login to Gateway or configure platform token; --reauth 等价于先 logout 再登录
|
|
6640
6735
|
logout [platform] Logout BUC or clear platform token
|
|
6641
6736
|
status [platform] [--all] Show login status, single platform, or all platform statuses
|
|
6642
6737
|
request [platform] <url|path> Send HTTP request (supports platform + path shorthand)
|
|
@@ -6666,6 +6761,7 @@ ${BOLD}Request Options:${RESET}
|
|
|
6666
6761
|
|
|
6667
6762
|
${BOLD}Examples:${RESET}
|
|
6668
6763
|
${DIM}$${RESET} ali-skills login
|
|
6764
|
+
${DIM}$${RESET} ali-skills login --reauth
|
|
6669
6765
|
${DIM}$${RESET} ali-skills login code
|
|
6670
6766
|
${DIM}$${RESET} ali-skills login yuque
|
|
6671
6767
|
${DIM}$${RESET} ali-skills login yuque group
|
|
@@ -6929,6 +7025,16 @@ function parseLogoutArgs(args) {
|
|
|
6929
7025
|
clearAll
|
|
6930
7026
|
};
|
|
6931
7027
|
}
|
|
7028
|
+
function stripReauthFlag(args) {
|
|
7029
|
+
let reauth = false;
|
|
7030
|
+
const rest = [];
|
|
7031
|
+
for (const a of args) if (a === "--reauth") reauth = true;
|
|
7032
|
+
else rest.push(a);
|
|
7033
|
+
return {
|
|
7034
|
+
reauth,
|
|
7035
|
+
rest
|
|
7036
|
+
};
|
|
7037
|
+
}
|
|
6932
7038
|
async function runGatewayCommand(args) {
|
|
6933
7039
|
if (args.length === 0) {
|
|
6934
7040
|
showGatewayHelp();
|
|
@@ -6937,11 +7043,14 @@ async function runGatewayCommand(args) {
|
|
|
6937
7043
|
const command = args[0];
|
|
6938
7044
|
const rest = args.slice(1);
|
|
6939
7045
|
switch (command) {
|
|
6940
|
-
case "login":
|
|
7046
|
+
case "login": {
|
|
6941
7047
|
showLogo();
|
|
6942
7048
|
console.log();
|
|
6943
|
-
|
|
7049
|
+
const { reauth, rest: loginRest } = stripReauthFlag(rest);
|
|
7050
|
+
if (loginRest.length > 0) await runPlatformLogin(loginRest);
|
|
7051
|
+
else await login({ reauth });
|
|
6944
7052
|
break;
|
|
7053
|
+
}
|
|
6945
7054
|
case "logout": {
|
|
6946
7055
|
const lo = parseLogoutArgs(rest);
|
|
6947
7056
|
await logout(lo.platform, lo.yuqueGroup, lo.clearAll);
|
|
@@ -7593,7 +7702,14 @@ async function main() {
|
|
|
7593
7702
|
case "a":
|
|
7594
7703
|
case "add": {
|
|
7595
7704
|
showLogo();
|
|
7596
|
-
|
|
7705
|
+
let addParsed;
|
|
7706
|
+
try {
|
|
7707
|
+
addParsed = parseAddOptions(restArgs);
|
|
7708
|
+
} catch (error) {
|
|
7709
|
+
console.error(error instanceof Error ? error.message : "Invalid add options");
|
|
7710
|
+
process.exit(1);
|
|
7711
|
+
}
|
|
7712
|
+
const { source: addSource, options: addOpts } = addParsed;
|
|
7597
7713
|
await runAdd(addSource, addOpts);
|
|
7598
7714
|
break;
|
|
7599
7715
|
}
|
|
@@ -7628,10 +7744,12 @@ async function main() {
|
|
|
7628
7744
|
case "check":
|
|
7629
7745
|
await runCheck(restArgs);
|
|
7630
7746
|
break;
|
|
7631
|
-
case "login":
|
|
7632
|
-
|
|
7633
|
-
|
|
7747
|
+
case "login": {
|
|
7748
|
+
const { reauth, rest: loginRest } = stripReauthFlag(restArgs);
|
|
7749
|
+
if (loginRest.length > 0) await runPlatformLogin(loginRest);
|
|
7750
|
+
else await login({ reauth });
|
|
7634
7751
|
break;
|
|
7752
|
+
}
|
|
7635
7753
|
case "logout": {
|
|
7636
7754
|
const lo = parseLogoutArgs(restArgs);
|
|
7637
7755
|
await logout(lo.platform, lo.yuqueGroup, lo.clearAll);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ali-skills",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.26",
|
|
4
4
|
"description": "The open agent skills ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"author": "",
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ali/cli-skills": "^2.0.
|
|
34
|
+
"@ali/cli-skills": "^2.0.27"
|
|
35
35
|
},
|
|
36
36
|
"bundleDependencies": [
|
|
37
37
|
"@ali/cli-skills"
|