ali-skills 0.0.16 → 0.0.18

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.
@@ -224,20 +224,21 @@ function isWellKnownUrl(input) {
224
224
  return false;
225
225
  }
226
226
  }
227
- function getDisplaySource(sourceUrl) {
227
+ function getDisplaySource(sourceUrl, options = {}) {
228
+ const format = options.format ?? "compact";
228
229
  if (sourceUrl.startsWith("/") || sourceUrl.startsWith(".") || sourceUrl.startsWith("~")) return sourceUrl;
229
230
  const sshMatch = sourceUrl.match(/^git@([^:]+):(.+)$/);
230
231
  if (sshMatch) {
231
232
  const [, host, path] = sshMatch;
232
233
  if (!host || !path) return sourceUrl;
233
234
  const cleanPath = path.replace(/\.git$/, "");
234
- if (host === "code.alibaba-inc.com" || host === "gitlab.alibaba-inc.com") return cleanPath;
235
+ if (format === "compact" && (host === "code.alibaba-inc.com" || host === "gitlab.alibaba-inc.com")) return cleanPath;
235
236
  return `https://${host}/${cleanPath}`;
236
237
  }
237
238
  if (sourceUrl.startsWith("http://") || sourceUrl.startsWith("https://")) try {
238
239
  const url = new URL(sourceUrl);
239
240
  const cleanPath = url.pathname.replace(/\.git$/, "").replace(/^\//, "");
240
- if (url.hostname === "code.alibaba-inc.com" || url.hostname === "gitlab.alibaba-inc.com") return cleanPath;
241
+ if (format === "compact" && (url.hostname === "code.alibaba-inc.com" || url.hostname === "gitlab.alibaba-inc.com")) return cleanPath;
241
242
  return `https://${url.hostname}/${cleanPath}`;
242
243
  } catch {
243
244
  return sourceUrl.replace(/^https?:\/\/[^@]+@/, "https://");
@@ -408,6 +409,9 @@ async function searchMultiselect(options) {
408
409
  });
409
410
  }
410
411
  const CLONE_TIMEOUT_MS = 6e4;
412
+ function redactSensitiveText$1(text) {
413
+ return text.replace(/(https?:\/\/)([^/\s:@]+)(?::([^@/\s]*))?@/gi, "$1").replace(/([?&](?:private_token|access_token|token|api_key|access_key|secret|password)=)[^&\s]+/gi, "$1***");
414
+ }
411
415
  function getGitUserConfig() {
412
416
  try {
413
417
  const name = execSync("git config user.name", {
@@ -475,11 +479,13 @@ async function cloneRepo(url, ref) {
475
479
  force: true
476
480
  }).catch(() => {});
477
481
  const errorMessage = error instanceof Error ? error.message : String(error);
482
+ const safeUrl = getDisplaySource(url);
483
+ const safeErrorMessage = redactSensitiveText$1(errorMessage);
478
484
  const isTimeout = errorMessage.includes("block timeout") || errorMessage.includes("timed out");
479
485
  const isAuthError = errorMessage.includes("Authentication failed") || errorMessage.includes("could not read Username") || errorMessage.includes("Permission denied") || errorMessage.includes("Repository not found") || errorMessage.includes("HTTP Basic: Access denied") || errorMessage.includes("could not be found or you don") || errorMessage.toLowerCase().includes("you don't have permission") || /repository .+ not found/i.test(errorMessage);
480
- if (isTimeout) throw new GitCloneError("Clone timed out after 60s. This often happens with private repos that require authentication.\n Ensure you have access and your SSH keys or credentials are configured:\n - For SSH: ssh-add -l (to check loaded keys)\n - For HTTPS: gh auth status (if using GitHub CLI)", url, true, false);
481
- if (isAuthError) throw new GitCloneError(`Authentication failed for ${url}.\n - For private repos, ensure you have access\n - For SSH: Check your keys with 'ssh -T git@github.com'\n - For HTTPS: Run 'gh auth login' or configure git credentials`, url, false, true);
482
- throw new GitCloneError(`Failed to clone ${url}: ${errorMessage}`, url, false, false);
486
+ if (isTimeout) throw new GitCloneError("Clone timed out after 60s. This often happens with private repos that require authentication.\n Ensure you have access and your SSH keys or credentials are configured:\n - For SSH: ssh-add -l (to check loaded keys)\n - For HTTPS: gh auth status (if using GitHub CLI)", safeUrl, true, false);
487
+ if (isAuthError) throw new GitCloneError(`Authentication failed for ${safeUrl}.\n - For private repos, ensure you have access\n - For SSH: Check your keys with 'ssh -T git@github.com'\n - For HTTPS: Run 'gh auth login' or configure git credentials`, safeUrl, false, true);
488
+ throw new GitCloneError(`Failed to clone ${safeUrl}: ${safeErrorMessage}`, safeUrl, false, false);
483
489
  }
484
490
  }
485
491
  async function listRemoteBranches(url) {
@@ -1994,8 +2000,12 @@ async function fetchSkillFolderHash(ownerRepo, skillPath, token) {
1994
2000
  if (folderPath.endsWith("/SKILL.md")) folderPath = folderPath.slice(0, -9);
1995
2001
  else if (folderPath.endsWith("SKILL.md")) folderPath = folderPath.slice(0, -8);
1996
2002
  if (folderPath.endsWith("/")) folderPath = folderPath.slice(0, -1);
1997
- for (const branch of ["main", "master"]) try {
1998
- const url = `https://api.github.com/repos/${ownerRepo}/git/trees/${branch}?recursive=1`;
2003
+ for (const ref of [
2004
+ "HEAD",
2005
+ "master",
2006
+ "main"
2007
+ ]) try {
2008
+ const url = `https://api.github.com/repos/${ownerRepo}/git/trees/${ref}?recursive=1`;
1999
2009
  const headers = {
2000
2010
  Accept: "application/vnd.github.v3+json",
2001
2011
  "User-Agent": "skills-cli"
@@ -2013,10 +2023,14 @@ async function fetchSkillFolderHash(ownerRepo, skillPath, token) {
2013
2023
  return null;
2014
2024
  }
2015
2025
  async function fetchAliInternalCommitHash(source, skillPath = "", token) {
2016
- const branches = ["main", "master"];
2026
+ const refs = [
2027
+ "HEAD",
2028
+ "master",
2029
+ "main"
2030
+ ];
2017
2031
  const privateToken = token || process.env.GITLAB_PRIVATE_TOKEN || process.env.CODE_ALIBABA_TOKEN || GITLAB_ACCOUNT.token;
2018
- for (const branch of branches) try {
2019
- let url = `https://code.alibaba-inc.com/api/v4/projects/${encodeURIComponent(source)}/repository/commits?ref_name=${branch}&per_page=1`;
2032
+ for (const ref of refs) try {
2033
+ let url = `https://code.alibaba-inc.com/api/v4/projects/${encodeURIComponent(source)}/repository/commits?ref_name=${ref}&per_page=1`;
2020
2034
  if (skillPath) url += `&path=${encodeURIComponent(skillPath)}`;
2021
2035
  const headers = {
2022
2036
  Accept: "application/json",
@@ -2025,8 +2039,8 @@ async function fetchAliInternalCommitHash(source, skillPath = "", token) {
2025
2039
  };
2026
2040
  const response = await fetch(url, { headers });
2027
2041
  if (!response.ok) continue;
2028
- const data = await response.json();
2029
- if (data && data.length > 0) return data[0].id;
2042
+ const latestCommit = (await response.json())[0];
2043
+ if (latestCommit?.id) return latestCommit.id;
2030
2044
  } catch {
2031
2045
  continue;
2032
2046
  }
@@ -2191,8 +2205,11 @@ function logSkillParseFailures(failures) {
2191
2205
  if (f.hint) M.message(import_picocolors.default.yellow(` 提示: ${f.hint}`));
2192
2206
  }
2193
2207
  }
2194
- var version$1 = "2.0.16";
2208
+ var version$1 = "2.0.18";
2195
2209
  const isCancelled$1 = (value) => typeof value === "symbol";
2210
+ function redactSensitiveText(text) {
2211
+ return text.replace(/(https?:\/\/)([^/\s:@]+)(?::([^@/\s]*))?@/gi, "$1").replace(/([?&](?:private_token|access_token|token|api_key|access_key|secret|password)=)[^&\s]+/gi, "$1***");
2212
+ }
2196
2213
  async function isSourcePrivate(source) {
2197
2214
  const ownerRepo = parseOwnerRepo(source);
2198
2215
  if (!ownerRepo) return false;
@@ -2711,7 +2728,8 @@ async function runAdd(args, options = {}) {
2711
2728
  }
2712
2729
  } catch {}
2713
2730
  }
2714
- spinner.stop(`Source: ${parsed.type === "local" ? parsed.localPath : parsed.url}${parsed.ref ? ` @ ${import_picocolors.default.yellow(parsed.ref)}` : ""}${parsed.subpath ? ` (${parsed.subpath})` : ""}${parsed.skillFilter ? ` ${import_picocolors.default.dim("@")}${import_picocolors.default.cyan(parsed.skillFilter)}` : ""}`);
2731
+ const displaySource = parsed.type === "local" ? parsed.localPath : getDisplaySource(parsed.url, { format: "absolute" });
2732
+ spinner.stop(`Source: ${displaySource}${parsed.ref ? ` @ ${import_picocolors.default.yellow(parsed.ref)}` : ""}${parsed.subpath ? ` (${parsed.subpath})` : ""}${parsed.skillFilter ? ` ${import_picocolors.default.dim("@")}${import_picocolors.default.cyan(parsed.skillFilter)}` : ""}`);
2715
2733
  if (parsed.type === "well-known") {
2716
2734
  await handleWellKnownSkills(source, parsed.url, options, spinner);
2717
2735
  return;
@@ -3300,8 +3318,8 @@ async function runAdd(args, options = {}) {
3300
3318
  } catch (error) {
3301
3319
  if (error instanceof GitCloneError) {
3302
3320
  M.error(import_picocolors.default.red("Failed to clone repository"));
3303
- for (const line of error.message.split("\n")) M.message(import_picocolors.default.dim(line));
3304
- } else M.error(error instanceof Error ? error.message : "Unknown error occurred");
3321
+ for (const line of error.message.split("\n")) M.message(import_picocolors.default.dim(redactSensitiveText(line)));
3322
+ } else M.error(redactSensitiveText(error instanceof Error ? error.message : "Unknown error occurred"));
3305
3323
  showInstallTip();
3306
3324
  Se(import_picocolors.default.red("Installation failed"));
3307
3325
  process.exit(1);
@@ -6214,10 +6232,20 @@ async function main() {
6214
6232
  }
6215
6233
  main().then(async () => {
6216
6234
  if (getPendingTelemetryCount() > 0) {
6235
+ const syncStartAt = Date.now();
6236
+ const longSyncThresholdMs = 800;
6237
+ let didShowStartMessage = false;
6238
+ const startMessageTimer = setTimeout(() => {
6239
+ didShowStartMessage = true;
6240
+ console.log();
6241
+ console.log(`${DIM}Syncing telemetry data...${RESET}`);
6242
+ }, longSyncThresholdMs);
6243
+ await flushTelemetry();
6244
+ clearTimeout(startMessageTimer);
6217
6245
  console.log();
6218
- console.log(`${DIM}Syncing installation data...${RESET}`);
6219
- }
6220
- await flushTelemetry();
6246
+ if (didShowStartMessage || Date.now() - syncStartAt >= longSyncThresholdMs) console.log(`${DIM}Telemetry data sync complete${RESET}`);
6247
+ else console.log(`${DIM}Telemetry data synced${RESET}`);
6248
+ } else await flushTelemetry();
6221
6249
  process.exit(0);
6222
6250
  }).catch(async (error) => {
6223
6251
  console.error(error);
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ali/cli-skills",
3
- "version": "2.0.16",
3
+ "version": "2.0.18",
4
4
  "description": "The open agent skills ecosystem",
5
5
  "type": "module",
6
6
  "bin": {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ali-skills",
3
- "version": "0.0.16",
3
+ "version": "0.0.18",
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.16"
34
+ "@ali/cli-skills": "^2.0.18"
35
35
  },
36
36
  "bundleDependencies": [
37
37
  "@ali/cli-skills"