ali-skills 0.0.10 → 0.0.12

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.
@@ -166,6 +166,14 @@ function parseSource(input) {
166
166
  type: "internal",
167
167
  url: input.replace(/\bgitlab\.alibaba-inc\.com\b/g, "code.alibaba-inc.com")
168
168
  };
169
+ const internalSshMatch = input.match(/^git@(?:code|gitlab)\.alibaba-inc\.com:(.+?)(?:\.git)?$/);
170
+ if (internalSshMatch) {
171
+ const repoPath = internalSshMatch[1];
172
+ if (repoPath.includes("/")) return {
173
+ type: "internal",
174
+ url: `git@code.alibaba-inc.com:${repoPath}.git`
175
+ };
176
+ }
169
177
  if (isWellKnownUrl(input)) return {
170
178
  type: "well-known",
171
179
  url: input
@@ -365,6 +373,37 @@ async function searchMultiselect(options) {
365
373
  });
366
374
  }
367
375
  const CLONE_TIMEOUT_MS = 6e4;
376
+ function getGitUserConfig() {
377
+ try {
378
+ const name = execSync("git config user.name", {
379
+ encoding: "utf-8",
380
+ stdio: [
381
+ "pipe",
382
+ "pipe",
383
+ "ignore"
384
+ ]
385
+ }).trim();
386
+ const email = execSync("git config user.email", {
387
+ encoding: "utf-8",
388
+ stdio: [
389
+ "pipe",
390
+ "pipe",
391
+ "ignore"
392
+ ]
393
+ }).trim();
394
+ if (!name || !email) return null;
395
+ const emailMatch = email.match(/^([a-z0-9._-]+)@/i);
396
+ return {
397
+ username: (name || (emailMatch ? emailMatch[1] : "")) ?? "",
398
+ email
399
+ };
400
+ } catch {
401
+ return null;
402
+ }
403
+ }
404
+ function getCurrentUser() {
405
+ return getGitUserConfig();
406
+ }
368
407
  var GitCloneError = class extends Error {
369
408
  url;
370
409
  isTimeout;
@@ -677,12 +716,24 @@ async function parseSkillMd(skillMdPath, options) {
677
716
  });
678
717
  return null;
679
718
  }
719
+ const extractAuthorInfo = (data) => {
720
+ const authorObj = data.author && typeof data.author === "object" && !Array.isArray(data.author) ? data.author : {};
721
+ return {
722
+ authorName: typeof authorObj.nickname === "string" && authorObj.nickname || typeof authorObj.name === "string" && authorObj.name || void 0,
723
+ authorEmpId: typeof authorObj.empId === "string" && authorObj.empId || void 0,
724
+ authorAvatar: typeof authorObj.avatar === "string" && authorObj.avatar || void 0
725
+ };
726
+ };
727
+ const { authorName, authorEmpId, authorAvatar } = extractAuthorInfo(data);
680
728
  return {
681
729
  name: data.name,
682
730
  description: data.description,
683
731
  path: dirname(skillMdPath),
684
732
  rawContent: content,
685
- metadata: data.metadata
733
+ metadata: data.metadata,
734
+ authorName,
735
+ authorEmpId,
736
+ authorAvatar
686
737
  };
687
738
  }
688
739
  async function findSkillDirs(dir, depth = 0, maxDepth = 5) {
@@ -833,15 +884,6 @@ const agents = {
833
884
  return existsSync(join(home, ".cursor"));
834
885
  }
835
886
  },
836
- codex: {
837
- name: "codex",
838
- displayName: "Codex",
839
- skillsDir: ".agents/skills",
840
- globalSkillsDir: join(codexHome, "skills"),
841
- detectInstalled: async () => {
842
- return existsSync(codexHome) || existsSync("/etc/codex");
843
- }
844
- },
845
887
  "aone-copilot": {
846
888
  name: "aone-copilot",
847
889
  displayName: "Aone Copilot",
@@ -851,6 +893,24 @@ const agents = {
851
893
  return existsSync(join(home, ".aone-copilot"));
852
894
  }
853
895
  },
896
+ qoder: {
897
+ name: "qoder",
898
+ displayName: "Qoder",
899
+ skillsDir: ".qoder/skills",
900
+ globalSkillsDir: join(home, ".qoder/skills"),
901
+ detectInstalled: async () => {
902
+ return existsSync(join(home, ".qoder"));
903
+ }
904
+ },
905
+ qoderwork: {
906
+ name: "qoderwork",
907
+ displayName: "QoderWork",
908
+ skillsDir: ".qoderwork/skills",
909
+ globalSkillsDir: join(home, ".qoderwork/skills"),
910
+ detectInstalled: async () => {
911
+ return existsSync(join(home, ".qoderwork"));
912
+ }
913
+ },
854
914
  "qwen-code": {
855
915
  name: "qwen-code",
856
916
  displayName: "Qwen Code",
@@ -869,6 +929,24 @@ const agents = {
869
929
  return existsSync(join(home, ".iflow"));
870
930
  }
871
931
  },
932
+ "github-copilot": {
933
+ name: "github-copilot",
934
+ displayName: "GitHub Copilot",
935
+ skillsDir: ".agents/skills",
936
+ globalSkillsDir: join(home, ".copilot/skills"),
937
+ detectInstalled: async () => {
938
+ return existsSync(join(home, ".copilot"));
939
+ }
940
+ },
941
+ codex: {
942
+ name: "codex",
943
+ displayName: "Codex",
944
+ skillsDir: ".agents/skills",
945
+ globalSkillsDir: join(codexHome, "skills"),
946
+ detectInstalled: async () => {
947
+ return existsSync(codexHome) || existsSync("/etc/codex");
948
+ }
949
+ },
872
950
  opencode: {
873
951
  name: "opencode",
874
952
  displayName: "OpenCode",
@@ -887,24 +965,6 @@ const agents = {
887
965
  return existsSync(join(home, ".openclaw")) || existsSync(join(home, ".clawdbot")) || existsSync(join(home, ".moltbot"));
888
966
  }
889
967
  },
890
- "kimi-cli": {
891
- name: "kimi-cli",
892
- displayName: "Kimi Code CLI",
893
- skillsDir: ".agents/skills",
894
- globalSkillsDir: join(home, ".config/agents/skills"),
895
- detectInstalled: async () => {
896
- return existsSync(join(home, ".kimi"));
897
- }
898
- },
899
- "github-copilot": {
900
- name: "github-copilot",
901
- displayName: "GitHub Copilot",
902
- skillsDir: ".agents/skills",
903
- globalSkillsDir: join(home, ".copilot/skills"),
904
- detectInstalled: async () => {
905
- return existsSync(join(home, ".copilot"));
906
- }
907
- },
908
968
  "gemini-cli": {
909
969
  name: "gemini-cli",
910
970
  displayName: "Gemini CLI",
@@ -914,6 +974,15 @@ const agents = {
914
974
  return existsSync(join(home, ".gemini"));
915
975
  }
916
976
  },
977
+ antigravity: {
978
+ name: "antigravity",
979
+ displayName: "Antigravity",
980
+ skillsDir: ".agent/skills",
981
+ globalSkillsDir: join(home, ".gemini/antigravity/skills"),
982
+ detectInstalled: async () => {
983
+ return existsSync(join(home, ".gemini/antigravity"));
984
+ }
985
+ },
917
986
  cline: {
918
987
  name: "cline",
919
988
  displayName: "Cline",
@@ -932,15 +1001,6 @@ const agents = {
932
1001
  return existsSync(join(process.cwd(), ".continue")) || existsSync(join(home, ".continue"));
933
1002
  }
934
1003
  },
935
- antigravity: {
936
- name: "antigravity",
937
- displayName: "Antigravity",
938
- skillsDir: ".agent/skills",
939
- globalSkillsDir: join(home, ".gemini/antigravity/skills"),
940
- detectInstalled: async () => {
941
- return existsSync(join(home, ".gemini/antigravity"));
942
- }
943
- },
944
1004
  "kiro-cli": {
945
1005
  name: "kiro-cli",
946
1006
  displayName: "Kiro CLI",
@@ -959,6 +1019,15 @@ const agents = {
959
1019
  return existsSync(join(home, ".codeium/windsurf"));
960
1020
  }
961
1021
  },
1022
+ "kimi-cli": {
1023
+ name: "kimi-cli",
1024
+ displayName: "Kimi Code CLI",
1025
+ skillsDir: ".agents/skills",
1026
+ globalSkillsDir: join(home, ".config/agents/skills"),
1027
+ detectInstalled: async () => {
1028
+ return existsSync(join(home, ".kimi"));
1029
+ }
1030
+ },
962
1031
  trae: {
963
1032
  name: "trae",
964
1033
  displayName: "Trae",
@@ -1185,15 +1254,6 @@ const agents = {
1185
1254
  return existsSync(join(home, ".commandcode"));
1186
1255
  }
1187
1256
  },
1188
- qoder: {
1189
- name: "qoder",
1190
- displayName: "Qoder",
1191
- skillsDir: ".qoder/skills",
1192
- globalSkillsDir: join(home, ".qoder/skills"),
1193
- detectInstalled: async () => {
1194
- return existsSync(join(home, ".qoder"));
1195
- }
1196
- },
1197
1257
  universal: {
1198
1258
  name: "universal",
1199
1259
  displayName: "Universal",
@@ -2023,7 +2083,7 @@ function logSkillParseFailures(failures) {
2023
2083
  if (f.hint) M.message(import_picocolors.default.yellow(` 提示: ${f.hint}`));
2024
2084
  }
2025
2085
  }
2026
- var version$1 = "2.0.8";
2086
+ var version$1 = "2.0.11";
2027
2087
  const isCancelled$1 = (value) => typeof value === "symbol";
2028
2088
  async function isSourcePrivate(source) {
2029
2089
  const ownerRepo = parseOwnerRepo(source);
@@ -2396,16 +2456,20 @@ async function handleWellKnownSkills(source, url, options, spinner) {
2396
2456
  skillFiles[skill.installName] = skill.sourceUrl;
2397
2457
  if (skill.description) skillDescriptions[skill.installName] = skill.description;
2398
2458
  }
2399
- if (await isSourcePrivate(sourceIdentifier) !== true) track({
2400
- event: "install",
2401
- source: sourceIdentifier,
2402
- skills: selectedSkills.map((s) => s.installName).join(","),
2403
- agents: targetAgents.join(","),
2404
- ...installGlobally && { global: "1" },
2405
- skillFiles: JSON.stringify(skillFiles),
2406
- sourceType: "well-known",
2407
- descriptions: JSON.stringify(skillDescriptions)
2408
- });
2459
+ if (await isSourcePrivate(sourceIdentifier) !== true) {
2460
+ const currentUser = getCurrentUser();
2461
+ track({
2462
+ event: "install",
2463
+ source: sourceIdentifier,
2464
+ skills: selectedSkills.map((s) => s.installName).join(","),
2465
+ agents: targetAgents.join(","),
2466
+ ...installGlobally && { global: "1" },
2467
+ skillFiles: JSON.stringify(skillFiles),
2468
+ sourceType: "well-known",
2469
+ descriptions: JSON.stringify(skillDescriptions),
2470
+ ...currentUser && { user: JSON.stringify(currentUser) }
2471
+ });
2472
+ }
2409
2473
  if (successful.length > 0 && installGlobally) {
2410
2474
  const successfulSkillNames = new Set(successful.map((r) => r.skill));
2411
2475
  for (const skill of selectedSkills) if (successfulSkillNames.has(skill.installName)) try {
@@ -2514,6 +2578,13 @@ async function runAdd(args, options = {}) {
2514
2578
  const spinner = Y();
2515
2579
  spinner.start("Parsing source...");
2516
2580
  const parsed = parseSource(resolvedSource);
2581
+ if (parsed.type === "internal" && parsed.url.startsWith("git@")) {
2582
+ const sshMatch = parsed.url.match(/^git@code\.alibaba-inc\.com:(.+)$/);
2583
+ if (sshMatch) {
2584
+ const repoPath = sshMatch[1].replace(/\.git$/, "");
2585
+ parsed.url = `https://${GITLAB_ACCOUNT.user}:${GITLAB_ACCOUNT.token}@code.alibaba-inc.com/${repoPath}.git`;
2586
+ }
2587
+ }
2517
2588
  if (options.branch) {
2518
2589
  parsed.ref = options.branch;
2519
2590
  parsed.subpath = void 0;
@@ -2918,6 +2989,7 @@ async function runAdd(args, options = {}) {
2918
2989
  const failed = results.filter((r) => !r.success);
2919
2990
  const skillFiles = {};
2920
2991
  const skillDescriptions = {};
2992
+ const skillMdAuthors = {};
2921
2993
  for (const skill of selectedSkills) {
2922
2994
  let relativePath;
2923
2995
  if (tempDir && skill.path === tempDir) relativePath = "SKILL.md";
@@ -2925,29 +2997,59 @@ async function runAdd(args, options = {}) {
2925
2997
  else continue;
2926
2998
  skillFiles[skill.name] = relativePath;
2927
2999
  if (skill.description) skillDescriptions[skill.name] = skill.description;
3000
+ if (skill.authorName || skill.authorEmpId || skill.authorAvatar) skillMdAuthors[skill.name] = {
3001
+ name: skill.authorName,
3002
+ empId: skill.authorEmpId,
3003
+ avatar: skill.authorAvatar
3004
+ };
2928
3005
  }
2929
3006
  const normalizedSource = getOwnerRepo(parsed);
2930
3007
  const effectiveSourceType = parsed.type;
2931
3008
  const lockSource = parsed.url.startsWith("git@") ? parsed.url : normalizedSource;
2932
- let skillAuthor;
3009
+ const trackableSkillNames = selectedSkills.filter((s) => isValidSkillName(s.name)).map((s) => s.name);
3010
+ const skillMdLastCommitAuthors = {};
2933
3011
  if (parsed.type === "internal" && normalizedSource) {
2934
3012
  const gitlabToken = GITLAB_ACCOUNT.token;
2935
3013
  if (gitlabToken) {
2936
3014
  const project = await getGitLabProject(normalizedSource, gitlabToken);
2937
- if (project) {
2938
- const firstSkillPath = Object.values(skillFiles)[0];
2939
- if (firstSkillPath) {
2940
- const author = await getSkillLastCommitAuthor(project.id, firstSkillPath, gitlabToken);
2941
- if (author) skillAuthor = author;
3015
+ if (project) for (const skillName of trackableSkillNames) {
3016
+ const skillFilePath = skillFiles[skillName];
3017
+ if (skillFilePath) {
3018
+ const author = await getSkillLastCommitAuthor(project.id, skillFilePath, gitlabToken);
3019
+ if (author) {
3020
+ const formattedName = author.username ? `${author.name}/${author.username}` : author.name;
3021
+ skillMdLastCommitAuthors[skillName] = {
3022
+ employeeId: author.employeeId,
3023
+ email: author.email,
3024
+ name: formattedName
3025
+ };
3026
+ }
2942
3027
  }
2943
3028
  }
2944
3029
  }
2945
3030
  }
2946
- const trackableSkillNames = selectedSkills.filter((s) => isValidSkillName(s.name)).map((s) => s.name);
2947
3031
  if (normalizedSource && trackableSkillNames.length > 0) {
2948
3032
  const ownerRepo = parseOwnerRepo(normalizedSource);
2949
3033
  if (ownerRepo) {
2950
- if (await isRepoPrivate(ownerRepo.owner, ownerRepo.repo) === false) track({
3034
+ if (await isRepoPrivate(ownerRepo.owner, ownerRepo.repo) === false) {
3035
+ const currentUser = getCurrentUser();
3036
+ track({
3037
+ event: "install",
3038
+ source: normalizedSource,
3039
+ skills: trackableSkillNames.join(","),
3040
+ agents: targetAgents.join(","),
3041
+ ...installGlobally && { global: "1" },
3042
+ skillFiles: JSON.stringify(skillFiles),
3043
+ sourceType: effectiveSourceType,
3044
+ skillMdLastCommitAuthors: JSON.stringify(skillMdLastCommitAuthors),
3045
+ skillMdConfigAuthors: JSON.stringify(skillMdAuthors),
3046
+ descriptions: JSON.stringify(skillDescriptions),
3047
+ ...currentUser && { user: JSON.stringify(currentUser) }
3048
+ });
3049
+ }
3050
+ } else {
3051
+ const currentUser = getCurrentUser();
3052
+ track({
2951
3053
  event: "install",
2952
3054
  source: normalizedSource,
2953
3055
  skills: trackableSkillNames.join(","),
@@ -2955,20 +3057,12 @@ async function runAdd(args, options = {}) {
2955
3057
  ...installGlobally && { global: "1" },
2956
3058
  skillFiles: JSON.stringify(skillFiles),
2957
3059
  sourceType: effectiveSourceType,
2958
- author: JSON.stringify(skillAuthor),
2959
- descriptions: JSON.stringify(skillDescriptions)
3060
+ skillMdLastCommitAuthors: JSON.stringify(skillMdLastCommitAuthors),
3061
+ skillMdConfigAuthors: JSON.stringify(skillMdAuthors),
3062
+ descriptions: JSON.stringify(skillDescriptions),
3063
+ ...currentUser && { user: JSON.stringify(currentUser) }
2960
3064
  });
2961
- } else track({
2962
- event: "install",
2963
- source: normalizedSource,
2964
- skills: trackableSkillNames.join(","),
2965
- agents: targetAgents.join(","),
2966
- ...installGlobally && { global: "1" },
2967
- skillFiles: JSON.stringify(skillFiles),
2968
- sourceType: effectiveSourceType,
2969
- author: JSON.stringify(skillAuthor),
2970
- descriptions: JSON.stringify(skillDescriptions)
2971
- });
3065
+ }
2972
3066
  }
2973
3067
  if (successful.length > 0 && installGlobally && normalizedSource) {
2974
3068
  const successfulSkillNames = new Set(successful.map((r) => r.skill));
@@ -4017,13 +4111,19 @@ function detectRepoInfo() {
4017
4111
  }).trim();
4018
4112
  if (!remoteUrl) return null;
4019
4113
  if (remoteUrl.includes("code.alibaba-inc.com") || remoteUrl.includes("gitlab.alibaba-inc.com")) {
4020
- const match = remoteUrl.match(/(?:code|gitlab)\.alibaba-inc\.com[/:]([^/]+)\/([^/.]+)/);
4021
- if (match) return {
4022
- sourceType: "internal",
4023
- owner: match[1],
4024
- repo: match[2],
4025
- remoteUrl
4026
- };
4114
+ const match = remoteUrl.match(/(?:code|gitlab)\.alibaba-inc\.com[\/:](.+?)(?:\.git)?$/);
4115
+ if (match) {
4116
+ const pathParts = match[1].split("/");
4117
+ if (pathParts.length >= 2) {
4118
+ const repo = pathParts.pop();
4119
+ return {
4120
+ sourceType: "internal",
4121
+ owner: pathParts.join("/"),
4122
+ repo,
4123
+ remoteUrl
4124
+ };
4125
+ }
4126
+ }
4027
4127
  }
4028
4128
  if (remoteUrl.includes("github.com")) {
4029
4129
  const match = remoteUrl.match(/github\.com[/:]([^/]+)\/([^/.]+)/);
@@ -4224,12 +4324,18 @@ async function runPublish(args, options = {}) {
4224
4324
  const registerResult = await registerSkill({
4225
4325
  source,
4226
4326
  sourceType: repoInfo.sourceType,
4227
- skills: successful.map((r) => ({
4228
- name: r.skill,
4229
- zipUrl: r.zipUrl,
4230
- zipHash: r.hash,
4231
- description: selectedSkills.find((s) => getSkillDisplayName(s) === r.skill)?.description ?? ""
4232
- }))
4327
+ skills: successful.map((r) => {
4328
+ const skill = selectedSkills.find((s) => getSkillDisplayName(s) === r.skill);
4329
+ return {
4330
+ name: r.skill,
4331
+ zipUrl: r.zipUrl,
4332
+ zipHash: r.hash,
4333
+ description: skill?.description ?? "",
4334
+ authorName: skill?.authorName,
4335
+ authorEmpId: skill?.authorEmpId,
4336
+ authorAvatar: skill?.authorAvatar
4337
+ };
4338
+ })
4233
4339
  });
4234
4340
  if (registerResult.success) spinner.stop("Skills registered");
4235
4341
  else spinner.stop(import_picocolors.default.yellow(`Registration warning: ${registerResult.error}`));
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ali/cli-skills",
3
- "version": "2.0.8",
3
+ "version": "2.0.11",
4
4
  "description": "The open agent skills ecosystem",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,7 +25,7 @@
25
25
  "test": "vitest",
26
26
  "type-check": "tsc --noEmit",
27
27
  "publish:snapshot": "tnpm version prerelease --preid=snapshot --no-git-tag-version && tnpm publish --tag snapshot",
28
- "publish:latest:patch": "tnpm version patch && tnpm publish && git push --follow-tags"
28
+ "publish:latest:patch": "tnpm version patch && tnpm publish && git push --follow-tags --no-verify"
29
29
  },
30
30
  "lint-staged": {
31
31
  "src/**/*.ts": "prettier --write",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ali-skills",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
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.8"
34
+ "@ali/cli-skills": "^2.0.11"
35
35
  },
36
36
  "bundleDependencies": [
37
37
  "@ali/cli-skills"