antikit 1.12.7 → 1.12.8

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "antikit",
3
- "version": "1.12.7",
3
+ "version": "1.12.8",
4
4
  "description": "CLI tool to manage AI agent skills from Anti Gravity skills repository",
5
5
  "type": "module",
6
6
  "main": "src/index.js",
@@ -1,9 +1,14 @@
1
1
  import chalk from 'chalk';
2
+ import ora from 'ora';
2
3
  import { readdirSync, existsSync, readFileSync } from 'fs';
3
4
  import { join } from 'path';
5
+ import { checkbox, confirm, Separator } from '@inquirer/prompts';
6
+ import Table from 'cli-table3';
4
7
  import { getOrCreateSkillsDir } from '../utils/local.js';
5
8
  import { installSkill } from './install.js';
6
- import { confirm } from '@inquirer/prompts';
9
+ import { fetchSkillInfo } from '../utils/github.js';
10
+ import { compareVersions, DEFAULT_VERSION } from '../utils/version.js';
11
+ import { METADATA_FILE } from '../utils/constants.js';
7
12
 
8
13
  export async function upgradeSkills(skillName, options = {}) {
9
14
  const skillsDir = getOrCreateSkillsDir();
@@ -18,31 +23,230 @@ export async function upgradeSkills(skillName, options = {}) {
18
23
  return;
19
24
  }
20
25
 
21
- // 2. Upgrade all skills
22
- const skills = readdirSync(skillsDir).filter(
26
+ // 2. Get all installed skills
27
+ const skillNames = readdirSync(skillsDir).filter(
23
28
  f => existsSync(join(skillsDir, f)) && !f.startsWith('.')
24
29
  );
25
30
 
26
- if (skills.length === 0) {
31
+ if (skillNames.length === 0) {
27
32
  console.log(chalk.yellow('No skills installed.'));
28
33
  return;
29
34
  }
30
35
 
31
- console.log(chalk.blue(`Found ${skills.length} installed skills.`));
36
+ // 3. Fetch skill metadata and check for updates
37
+ const spinner = ora('Checking for updates...').start();
38
+ const skillsWithInfo = [];
32
39
 
33
- let shouldProceed = options.yes;
40
+ for (const skillName of skillNames) {
41
+ const metaPath = join(skillsDir, skillName, METADATA_FILE);
42
+
43
+ if (!existsSync(metaPath)) {
44
+ skillsWithInfo.push({
45
+ name: skillName,
46
+ localVersion: DEFAULT_VERSION,
47
+ remoteVersion: null,
48
+ updateAvailable: false,
49
+ error: 'Missing metadata'
50
+ });
51
+ continue;
52
+ }
53
+
54
+ try {
55
+ const meta = JSON.parse(readFileSync(metaPath, 'utf-8'));
56
+ const localVersion = meta.version || DEFAULT_VERSION;
57
+
58
+ if (!meta.source || !meta.source.owner || !meta.source.repo) {
59
+ skillsWithInfo.push({
60
+ name: skillName,
61
+ localVersion,
62
+ remoteVersion: null,
63
+ updateAvailable: false,
64
+ error: 'Invalid metadata',
65
+ meta
66
+ });
67
+ continue;
68
+ }
69
+
70
+ // Fetch remote version
71
+ const info = await fetchSkillInfo(
72
+ skillName,
73
+ meta.source.owner,
74
+ meta.source.repo,
75
+ meta.source.path || '',
76
+ meta.source.branch || 'main'
77
+ );
78
+
79
+ const remoteVersion = info ? info.version : DEFAULT_VERSION;
80
+ const updateAvailable = compareVersions(remoteVersion, localVersion) > 0;
81
+
82
+ skillsWithInfo.push({
83
+ name: skillName,
84
+ localVersion,
85
+ remoteVersion,
86
+ updateAvailable,
87
+ description: info ? info.description : meta.description,
88
+ meta
89
+ });
90
+ } catch (error) {
91
+ skillsWithInfo.push({
92
+ name: skillName,
93
+ localVersion: DEFAULT_VERSION,
94
+ remoteVersion: null,
95
+ updateAvailable: false,
96
+ error: error.message
97
+ });
98
+ }
99
+ }
100
+
101
+ spinner.succeed(`Found ${skillsWithInfo.length} installed skills`);
102
+ console.log();
103
+
104
+ // 4. Check if interactive mode or auto-upgrade mode
105
+ if (options.interactive || (!options.yes && process.stdout.isTTY)) {
106
+ await interactiveUpgrade(skillsDir, skillsWithInfo);
107
+ } else {
108
+ await autoUpgradeAll(skillsDir, skillsWithInfo, options.yes);
109
+ }
110
+ }
111
+
112
+
113
+ async function interactiveUpgrade(skillsDir, skills) {
114
+ // Sort skills: updateAvailable first, then by name
115
+ skills.sort((a, b) => {
116
+ if (a.updateAvailable && !b.updateAvailable) return -1;
117
+ if (!a.updateAvailable && b.updateAvailable) return 1;
118
+ return a.name.localeCompare(b.name);
119
+ });
120
+
121
+ const hasUpdates = skills.some(s => s.updateAvailable);
122
+
123
+ if (!hasUpdates) {
124
+ console.log(chalk.green('✓ All skills are up to date!'));
125
+ console.log();
126
+ displaySkillsTable(skills);
127
+ return;
128
+ }
129
+
130
+ console.log(chalk.bold('Select skills to upgrade:\n'));
131
+
132
+ const choices = skills.map(skill => {
133
+ let label = '';
134
+ let disabled = false;
135
+
136
+ if (skill.error) {
137
+ label = `${chalk.red('✗')} ${chalk.cyan(skill.name)} ${chalk.dim(`(${skill.error})`)}`;
138
+ disabled = `Cannot upgrade: ${skill.error}`;
139
+ } else if (skill.updateAvailable) {
140
+ label = `${chalk.yellow('↑')} ${chalk.cyan(skill.name)} ${chalk.yellow(`v${skill.localVersion} → v${skill.remoteVersion}`)}`;
141
+ } else {
142
+ label = `${chalk.green('✓')} ${chalk.cyan(skill.name)} ${chalk.dim(`v${skill.localVersion} (Up to date)`)}`;
143
+ disabled = true;
144
+ }
145
+
146
+ if (skill.description && !skill.error) {
147
+ label += ` ${chalk.dim('- ' + skill.description.slice(0, 80) + (skill.description.length > 80 ? '...' : ''))}`;
148
+ }
149
+
150
+ return {
151
+ name: label,
152
+ value: skill,
153
+ disabled
154
+ };
155
+ });
156
+
157
+ // Show checkbox selection
158
+ const selected = await checkbox({
159
+ message: 'Select skills to upgrade:',
160
+ choices,
161
+ pageSize: 20,
162
+ loop: false
163
+ });
164
+
165
+ if (selected.length === 0) {
166
+ console.log(chalk.yellow('\nNo skills selected.'));
167
+ return;
168
+ }
169
+
170
+ // Confirm upgrade
171
+ const shouldUpgrade = await confirm({
172
+ message: `Upgrade ${selected.length} skill(s)?`,
173
+ default: true
174
+ });
175
+
176
+ if (!shouldUpgrade) {
177
+ console.log(chalk.yellow('Operation cancelled.'));
178
+ return;
179
+ }
180
+
181
+ // Upgrade selected skills
182
+ console.log();
183
+ let successCount = 0;
184
+ let failCount = 0;
185
+
186
+ for (const skill of selected) {
187
+ try {
188
+ await upgradeSingleSkill(skillsDir, skill.name);
189
+ successCount++;
190
+ } catch {
191
+ failCount++;
192
+ }
193
+ }
194
+
195
+ console.log('\n────────────────────────────────────────');
196
+ if (failCount === 0) {
197
+ console.log(chalk.green(`✓ All ${successCount} skills upgraded successfully`));
198
+ } else {
199
+ console.log(chalk.yellow(`⚠ Upgraded ${successCount} skills, ${failCount} failed`));
200
+ }
201
+ }
202
+
203
+ async function autoUpgradeAll(skillsDir, skills, autoYes) {
204
+ const upgradableSkills = skills.filter(s => s.updateAvailable && !s.error);
205
+
206
+ if (upgradableSkills.length === 0) {
207
+ console.log(chalk.green('✓ All skills are up to date!'));
208
+ console.log();
209
+ displaySkillsTable(skills);
210
+ return;
211
+ }
212
+
213
+ console.log(chalk.blue(`Found ${upgradableSkills.length} skill(s) with available updates:`));
214
+ console.log();
215
+
216
+ // Display table of upgradable skills
217
+ const table = new Table({
218
+ head: [chalk.cyan('Skill Name'), chalk.cyan('Current'), chalk.cyan('Latest')],
219
+ colWidths: [30, 15, 15],
220
+ style: { head: [], border: [] }
221
+ });
222
+
223
+ upgradableSkills.forEach(skill => {
224
+ table.push([
225
+ chalk.bold.cyan(skill.name),
226
+ chalk.dim(skill.localVersion),
227
+ chalk.yellow(skill.remoteVersion)
228
+ ]);
229
+ });
230
+
231
+ console.log(table.toString());
232
+ console.log();
233
+
234
+ let shouldProceed = autoYes;
34
235
  if (!shouldProceed) {
35
236
  shouldProceed = await confirm({ message: 'Upgrade all skills?', default: true });
36
237
  }
37
238
 
38
- if (!shouldProceed) return;
239
+ if (!shouldProceed) {
240
+ console.log(chalk.yellow('Operation cancelled.'));
241
+ return;
242
+ }
39
243
 
40
244
  let successCount = 0;
41
245
  let failCount = 0;
42
246
 
43
- for (const skill of skills) {
247
+ for (const skill of upgradableSkills) {
44
248
  try {
45
- await upgradeSingleSkill(skillsDir, skill);
249
+ await upgradeSingleSkill(skillsDir, skill.name);
46
250
  successCount++;
47
251
  } catch {
48
252
  failCount++;
@@ -57,6 +261,34 @@ export async function upgradeSkills(skillName, options = {}) {
57
261
  }
58
262
  }
59
263
 
264
+ function displaySkillsTable(skills) {
265
+ const table = new Table({
266
+ head: [chalk.cyan('Skill Name'), chalk.cyan('Version'), chalk.cyan('Status')],
267
+ colWidths: [30, 15, 20],
268
+ style: { head: [], border: [] }
269
+ });
270
+
271
+ skills.forEach(skill => {
272
+ let status = '';
273
+ if (skill.error) {
274
+ status = chalk.red('Error');
275
+ } else if (skill.updateAvailable) {
276
+ status = chalk.yellow('Update available');
277
+ } else {
278
+ status = chalk.green('Up to date');
279
+ }
280
+
281
+ table.push([
282
+ chalk.bold.cyan(skill.name),
283
+ skill.error ? chalk.dim(skill.localVersion) : skill.localVersion,
284
+ status
285
+ ]);
286
+ });
287
+
288
+ console.log(table.toString());
289
+ console.log();
290
+ }
291
+
60
292
  async function upgradeSingleSkill(skillsDir, skillName) {
61
293
  const skillPath = join(skillsDir, skillName);
62
294
  const metaPath = join(skillPath, '.antikit-skill.json');
@@ -79,6 +311,7 @@ async function upgradeSingleSkill(skillsDir, skillName) {
79
311
  force: true,
80
312
  owner: meta.source.owner,
81
313
  repo: meta.source.repo,
314
+ path: meta.source.path, // Pass path from metadata
82
315
  noExit: true // Don't kill process on error
83
316
  });
84
317
  } catch (error) {
@@ -86,3 +319,4 @@ async function upgradeSingleSkill(skillsDir, skillName) {
86
319
  throw error;
87
320
  }
88
321
  }
322
+
package/src/index.js CHANGED
@@ -82,6 +82,7 @@ program
82
82
  .command('upgrade [skill]')
83
83
  .alias('ug')
84
84
  .description('Upgrade installed skills')
85
+ .option('-i, --interactive', 'Interactive mode to select skills (default in TTY)')
85
86
  .option('-y, --yes', 'Skip confirmation')
86
87
  .action(upgradeSkills);
87
88
 
@@ -54,7 +54,26 @@ export function loadConfig() {
54
54
 
55
55
  try {
56
56
  const content = readFileSync(CONFIG_FILE, 'utf-8');
57
- return JSON.parse(content);
57
+ const config = JSON.parse(content);
58
+
59
+ // Migration: Rename legacy "official" source to "antiskills"
60
+ let needsSave = false;
61
+ if (config.sources) {
62
+ config.sources = config.sources.map(source => {
63
+ if (source.name === 'official') {
64
+ needsSave = true;
65
+ return { ...source, name: OFFICIAL_SOURCE };
66
+ }
67
+ return source;
68
+ });
69
+ }
70
+
71
+ // Save migrated config
72
+ if (needsSave) {
73
+ saveConfig(config);
74
+ }
75
+
76
+ return config;
58
77
  } catch {
59
78
  return DEFAULT_CONFIG;
60
79
  }
@@ -4,7 +4,7 @@
4
4
  */
5
5
 
6
6
  // Source names
7
- export const OFFICIAL_SOURCE = 'official';
7
+ export const OFFICIAL_SOURCE = 'antiskills';
8
8
 
9
9
  // File names
10
10
  export const SKILL_MD = 'SKILL.md';