@maccesar/titools 2.2.9 → 2.2.10
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/lib/commands/update.js +84 -48
- package/package.json +1 -1
package/lib/commands/update.js
CHANGED
|
@@ -42,6 +42,49 @@ function hasAnySkillSymlink(platformSkillsDir) {
|
|
|
42
42
|
return skillList.some((skill) => existsSync(join(platformSkillsDir, skill)));
|
|
43
43
|
}
|
|
44
44
|
|
|
45
|
+
/**
|
|
46
|
+
* Perform the actual update for a specific scope
|
|
47
|
+
* @param {string|undefined} baseDir - Base directory (undefined = global, path = local)
|
|
48
|
+
* @param {string} repoDir - Repository directory
|
|
49
|
+
* @param {Object} spinner - Ora spinner instance
|
|
50
|
+
* @returns {Promise<void>}
|
|
51
|
+
*/
|
|
52
|
+
async function performUpdate(baseDir, repoDir, spinner) {
|
|
53
|
+
// Detect platforms with existing symlinks (only update those)
|
|
54
|
+
const detectedPlatforms = detectPlatforms(baseDir);
|
|
55
|
+
const platformsWithSymlinks = detectedPlatforms.filter((p) =>
|
|
56
|
+
hasAnySkillSymlink(p.skillsDir)
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
// Install skills
|
|
60
|
+
spinner.start('Syncing skills...');
|
|
61
|
+
const skillsResult = await installSkills(repoDir, baseDir);
|
|
62
|
+
spinner.succeed(`${skillsResult.installed.length} skills updated`);
|
|
63
|
+
|
|
64
|
+
// Install agents (only if Claude Code has symlinks)
|
|
65
|
+
const claudePlatform = platformsWithSymlinks.find((p) => p.name === 'claude');
|
|
66
|
+
if (claudePlatform) {
|
|
67
|
+
spinner.start('Syncing agents...');
|
|
68
|
+
const agentsResult = await installAgents(repoDir, baseDir);
|
|
69
|
+
if (agentsResult.installed.length > 0) {
|
|
70
|
+
spinner.succeed('Platform agents updated');
|
|
71
|
+
} else {
|
|
72
|
+
spinner.info('No agents to sync');
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
cleanupLegacyArtifacts(baseDir);
|
|
77
|
+
|
|
78
|
+
// Update symlinks silently for platforms that already had them
|
|
79
|
+
for (const platform of platformsWithSymlinks) {
|
|
80
|
+
await createSkillSymlinks(
|
|
81
|
+
platform.skillsDir,
|
|
82
|
+
SKILLS,
|
|
83
|
+
baseDir
|
|
84
|
+
);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
|
|
45
88
|
/**
|
|
46
89
|
* Update command handler
|
|
47
90
|
* @param {Object} options - Command options
|
|
@@ -65,15 +108,16 @@ export async function updateCommand(options) {
|
|
|
65
108
|
const localPlatforms = detectPlatforms(projectDir);
|
|
66
109
|
const hasLocalSkills = isProject && hasSkillsAt(projectDir);
|
|
67
110
|
const hasGlobalSkills = hasSkillsAt(undefined);
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
111
|
+
|
|
112
|
+
// Only show prompt if BOTH local and global skills exist
|
|
113
|
+
if (hasLocalSkills && hasGlobalSkills) {
|
|
71
114
|
try {
|
|
72
115
|
const scope = await select({
|
|
73
|
-
message: '
|
|
116
|
+
message: 'Both local and global skills detected. What do you want to update:',
|
|
74
117
|
choices: [
|
|
75
118
|
{ name: 'Global skills (user home)', value: 'global' },
|
|
76
119
|
{ name: 'Local skills (current project)', value: 'local' },
|
|
120
|
+
{ name: 'Both locations', value: 'both' },
|
|
77
121
|
],
|
|
78
122
|
theme: {
|
|
79
123
|
style: {
|
|
@@ -87,32 +131,44 @@ export async function updateCommand(options) {
|
|
|
87
131
|
process.exit(0);
|
|
88
132
|
}
|
|
89
133
|
if (scope === 'local') {
|
|
90
|
-
baseDir =
|
|
134
|
+
baseDir = projectDir;
|
|
135
|
+
} else if (scope === 'both') {
|
|
136
|
+
baseDir = 'both';
|
|
91
137
|
}
|
|
92
138
|
} catch (error) {
|
|
93
139
|
console.log('\nCancelled.');
|
|
94
140
|
process.exit(0);
|
|
95
141
|
}
|
|
142
|
+
} else if (hasLocalSkills && !hasGlobalSkills) {
|
|
143
|
+
// Only local skills exist, update local
|
|
144
|
+
baseDir = projectDir;
|
|
96
145
|
}
|
|
146
|
+
// If only global skills exist, baseDir remains undefined (global)
|
|
97
147
|
}
|
|
98
148
|
|
|
99
|
-
|
|
149
|
+
// Display mode
|
|
150
|
+
if (baseDir === 'both') {
|
|
151
|
+
console.log(chalk.cyan('Mode: Updating both global and local skills'));
|
|
152
|
+
} else if (baseDir) {
|
|
100
153
|
console.log(chalk.cyan('Mode: Local update (current project)'));
|
|
101
154
|
} else {
|
|
102
155
|
console.log(chalk.cyan('Mode: Global update (user home)'));
|
|
103
156
|
}
|
|
104
157
|
console.log('');
|
|
105
158
|
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
159
|
+
// Verify skills are installed
|
|
160
|
+
if (baseDir !== 'both') {
|
|
161
|
+
const skillsDir = getAgentsSkillsDir(baseDir);
|
|
162
|
+
const hasSkillsInstalled = skillsDir && SKILLS.some((skill) => existsSync(join(skillsDir, skill)));
|
|
163
|
+
if (!hasSkillsInstalled) {
|
|
164
|
+
console.log(chalk.yellow('No skills installed at this location.'));
|
|
165
|
+
console.log('Install them first with:');
|
|
166
|
+
console.log(' titools install');
|
|
167
|
+
console.log('');
|
|
168
|
+
console.log('Looked for skills in:');
|
|
169
|
+
console.log(` ${baseDir ? 'Local' : 'Global'}: ${skillsDir}`);
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
116
172
|
}
|
|
117
173
|
|
|
118
174
|
// Check for updates
|
|
@@ -121,7 +177,7 @@ export async function updateCommand(options) {
|
|
|
121
177
|
try {
|
|
122
178
|
const hasUpdate = await checkForUpdate(PACKAGE_VERSION);
|
|
123
179
|
|
|
124
|
-
// If there's a newer version on
|
|
180
|
+
// If there's a newer version on npm, prompt user to update CLI first
|
|
125
181
|
if (hasUpdate) {
|
|
126
182
|
let latestVersion = '(newer)';
|
|
127
183
|
try {
|
|
@@ -158,38 +214,18 @@ export async function updateCommand(options) {
|
|
|
158
214
|
return;
|
|
159
215
|
}
|
|
160
216
|
|
|
161
|
-
//
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
// Install skills
|
|
168
|
-
spinner.start('Syncing skills...');
|
|
169
|
-
const skillsResult = await installSkills(repoDir, baseDir);
|
|
170
|
-
spinner.succeed(`${skillsResult.installed.length} skills updated`);
|
|
171
|
-
|
|
172
|
-
// Install agents (only if Claude Code has symlinks)
|
|
173
|
-
const claudePlatform = platformsWithSymlinks.find((p) => p.name === 'claude');
|
|
174
|
-
if (claudePlatform) {
|
|
175
|
-
spinner.start('Syncing agents...');
|
|
176
|
-
const agentsResult = await installAgents(repoDir, baseDir);
|
|
177
|
-
if (agentsResult.installed.length > 0) {
|
|
178
|
-
spinner.succeed('Platform agents updated');
|
|
179
|
-
} else {
|
|
180
|
-
spinner.info('No agents to sync');
|
|
181
|
-
}
|
|
182
|
-
}
|
|
183
|
-
|
|
184
|
-
cleanupLegacyArtifacts(baseDir);
|
|
217
|
+
// Perform update(s)
|
|
218
|
+
if (baseDir === 'both') {
|
|
219
|
+
// Update both global and local
|
|
220
|
+
console.log(chalk.bold('Updating global skills...'));
|
|
221
|
+
await performUpdate(undefined, repoDir, spinner);
|
|
222
|
+
console.log('');
|
|
185
223
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
baseDir
|
|
192
|
-
);
|
|
224
|
+
console.log(chalk.bold('Updating local skills...'));
|
|
225
|
+
await performUpdate(process.cwd(), repoDir, spinner);
|
|
226
|
+
} else {
|
|
227
|
+
// Update single scope
|
|
228
|
+
await performUpdate(baseDir, repoDir, spinner);
|
|
193
229
|
}
|
|
194
230
|
|
|
195
231
|
// Summary
|