eskill 1.0.15 → 1.0.17

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/cli.js CHANGED
@@ -25,13 +25,18 @@ program
25
25
  .option('-l, --link', '使用符号链接而非复制', false)
26
26
  .option('-f, --force', '强制覆盖已存在的技能', false)
27
27
  .action(async (url, options) => {
28
- const spinner = ora('正在安装技能...').start();
29
-
30
28
  try {
31
- await installFromGitUrl(url, options);
32
- spinner.succeed('技能安装成功');
29
+ const result = await installFromGitUrl(url, options);
30
+
31
+ // 如果用户取消安装,正常退出
32
+ if (result && result.cancelled) {
33
+ process.exit(0);
34
+ }
35
+
36
+ // 其他情况显示成功消息
37
+ console.log('\n✓ 技能安装成功');
33
38
  } catch (error) {
34
- spinner.fail(`安装失败: ${error.message}`);
39
+ console.error(`\n❌ 安装失败: ${error.message}`);
35
40
  process.exit(1);
36
41
  }
37
42
  });
package/lib/installer.js CHANGED
@@ -5,6 +5,8 @@ import { tmpdir } from 'os';
5
5
  import { fileURLToPath } from 'url';
6
6
  import { parseGitUrl } from './git-url-parser.js';
7
7
  import { AGENTS, expandHomePath } from './agent-config.js';
8
+ import { searchSkills, formatSkillList } from './search.js';
9
+ import readline from 'readline';
8
10
 
9
11
  /**
10
12
  * 获取 eskill 包的安装目录
@@ -48,14 +50,106 @@ function getSkillMeta(skillPath) {
48
50
  }
49
51
  }
50
52
 
53
+ /**
54
+ * 检测并处理 name@author 格式
55
+ * 返回解析后的 GitHub URL,如果不是该格式则返回原 URL
56
+ */
57
+ async function handleSkillAtAuthorFormat(input) {
58
+ // 检测是否为 name@author 格式
59
+ const match = input.match(/^([^@]+)@([^@]+)$/);
60
+
61
+ if (!match) {
62
+ // 不是该格式,直接返回原 URL
63
+ return input;
64
+ }
65
+
66
+ const [, skillName, author] = match;
67
+ console.log(`\n检测到技能名称格式: ${skillName}@${author}`);
68
+ console.log(`正在搜索 "${skillName}"...\n`);
69
+
70
+ try {
71
+ // 搜索技能
72
+ const result = await searchSkills(skillName, { limit: 100, sortBy: 'stars' });
73
+
74
+ if (result.success === false) {
75
+ throw new Error(result.error?.message || '搜索失败');
76
+ }
77
+
78
+ const skills = result.data?.skills || result.data || result.skills || result.results || [];
79
+
80
+ // 筛选出匹配作者的技能
81
+ const matchedSkills = skills.filter(skill => {
82
+ const skillAuthor = skill.author || skill.owner || '';
83
+ return skillAuthor.toLowerCase() === author.toLowerCase();
84
+ });
85
+
86
+ if (matchedSkills.length === 0) {
87
+ // 没有找到匹配的作者
88
+ console.log(`❌ 未找到作者 "${author}" 的技能 "${skillName}"\n`);
89
+ console.log('搜索结果如下:\n');
90
+ console.log(formatSkillList(skills));
91
+ throw new Error(`未找到匹配的技能`);
92
+ }
93
+
94
+ // 找到匹配的技能
95
+ const matchedSkill = matchedSkills[0];
96
+ const githubUrl = matchedSkill.githubUrl || matchedSkill.github_url || matchedSkill.url;
97
+
98
+ if (!githubUrl) {
99
+ throw new Error('技能信息中没有 GitHub URL');
100
+ }
101
+
102
+ console.log(`\n✓ 找到匹配的技能:`);
103
+ console.log(` 名称: ${skillName}@${author}`);
104
+ console.log(` Stars: ⭐ ${matchedSkill.stars || 'N/A'}`);
105
+ console.log(` GitHub: ${githubUrl}\n`);
106
+
107
+ return githubUrl;
108
+ } catch (error) {
109
+ if (error.message === '未找到匹配的技能') {
110
+ throw error;
111
+ }
112
+ throw new Error(`搜索失败: ${error.message}`);
113
+ }
114
+ }
115
+
116
+ /**
117
+ * 等待用户确认
118
+ */
119
+ function confirmAction(message) {
120
+ return new Promise((resolve) => {
121
+ const rl = readline.createInterface({
122
+ input: process.stdin,
123
+ output: process.stdout
124
+ });
125
+
126
+ rl.question(`${message} (y/N): `, (answer) => {
127
+ rl.close();
128
+ resolve(answer.toLowerCase() === 'y' || answer.toLowerCase() === 'yes');
129
+ });
130
+ });
131
+ }
132
+
51
133
  /**
52
134
  * 从 Git URL 安装技能
53
135
  */
54
136
  export async function installFromGitUrl(gitUrl, options = {}) {
55
137
  const { agent = 'claude', link = false, force = false } = options;
56
138
 
139
+ // 检测并处理 name@author 格式
140
+ let actualUrl = await handleSkillAtAuthorFormat(gitUrl);
141
+
142
+ // 如果 URL 被转换了(即原来是 name@author 格式),需要确认
143
+ if (actualUrl !== gitUrl) {
144
+ const confirmed = await confirmAction('是否安装此技能?');
145
+ if (!confirmed) {
146
+ console.log('\n已取消安装');
147
+ return { success: false, cancelled: true };
148
+ }
149
+ }
150
+
57
151
  // 解析 Git URL
58
- const parsed = parseGitUrl(gitUrl);
152
+ const parsed = parseGitUrl(actualUrl);
59
153
  console.log(`平台: ${parsed.platform}`);
60
154
  console.log(`仓库: ${parsed.owner}/${parsed.repo}`);
61
155
  console.log(`分支: ${parsed.branch}`);
package/lib/search.js CHANGED
@@ -96,8 +96,10 @@ export function formatSkillList(skills, showIndex = true) {
96
96
  output += ` Stars: ⭐ ${skill.stars}\n`;
97
97
  }
98
98
 
99
- if (skill.url || skill.github_url) {
100
- output += ` ${skill.url || skill.github_url}\n`;
99
+ // 显示 GitHub URL(支持多种字段名)
100
+ const githubUrl = skill.githubUrl || skill.github_url || skill.url;
101
+ if (githubUrl) {
102
+ output += ` ${githubUrl}\n`;
101
103
  }
102
104
 
103
105
  output += '\n';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "eskill",
3
- "version": "1.0.15",
3
+ "version": "1.0.17",
4
4
  "description": "Unified AI Agent Skills Management - Install skills from Git URLs",
5
5
  "main": "index.js",
6
6
  "type": "module",