agentinit 1.18.0 → 1.18.2
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/CHANGELOG.md +21 -0
- package/README.md +2 -0
- package/dist/cli.js +248 -34
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +143 -34
- package/dist/commands/skills.js.map +1 -1
- package/dist/core/skillsManager.d.ts +11 -0
- package/dist/core/skillsManager.d.ts.map +1 -1
- package/dist/core/skillsManager.js +135 -2
- package/dist/core/skillsManager.js.map +1 -1
- package/dist/types/skills.d.ts +10 -0
- package/dist/types/skills.d.ts.map +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## [1.18.2](https://github.com/agentinit/agentinit/compare/v1.18.1...v1.18.2) (2026-04-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **skills:** preview install status during target selection ([97d93ec](https://github.com/agentinit/agentinit/commit/97d93ecb73d6522d2e10b6133eb8b050826c3849))
|
|
7
|
+
|
|
8
|
+
## [1.18.1](https://github.com/agentinit/agentinit/compare/v1.18.0...v1.18.1) (2026-04-05)
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **skills:** compare full skill payloads before updates ([4b1e27c](https://github.com/agentinit/agentinit/commit/4b1e27cc69264d46edb38c2f6435b7f2659cfdb3))
|
|
14
|
+
|
|
15
|
+
## [Unreleased]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Bug Fixes
|
|
19
|
+
|
|
20
|
+
* **skills:** compare installed skill payloads before prompting for updates
|
|
21
|
+
|
|
1
22
|
# [1.18.0](https://github.com/agentinit/agentinit/compare/v1.17.2...v1.18.0) (2026-04-04)
|
|
2
23
|
|
|
3
24
|
|
package/README.md
CHANGED
|
@@ -221,6 +221,8 @@ If a GitHub or local Claude bundle contains multiple plugins, `agentinit skills
|
|
|
221
221
|
|
|
222
222
|
Skills are installed into a canonical store by default (`.agents/skills/` for project, `~/.agents/skills/` for global), with agent-specific paths symlinked automatically. Bare skill names resolve from your configured default marketplace, falling back to the public catalog at `vercel-labs/agent-skills`. Use `./name` for local paths, `owner/repo` for GitHub repos, or `--from <marketplace>` for explicit marketplace sources.
|
|
223
223
|
|
|
224
|
+
When you re-run `agentinit skills add`, AgentInit now compares the installed skill payload with the source before overwriting anything. Unchanged skills are reported as already up to date. If an installed skill has changed, interactive runs ask for confirmation before replacing it, while `--yes` applies the update automatically.
|
|
225
|
+
|
|
224
226
|
### `agentinit plugins`
|
|
225
227
|
|
|
226
228
|
Install, inspect, search, and remove portable plugins from explicit marketplace sources, GitHub repositories, or local paths.
|
package/dist/cli.js
CHANGED
|
@@ -18554,6 +18554,7 @@ import {resolve as resolve8, join as join5, relative as relative3, basename as b
|
|
|
18554
18554
|
import {promises as fs24} from "fs";
|
|
18555
18555
|
import {homedir as homedir5, tmpdir} from "os";
|
|
18556
18556
|
import {execFile} from "child_process";
|
|
18557
|
+
import {createHash} from "crypto";
|
|
18557
18558
|
import {promisify} from "util";
|
|
18558
18559
|
|
|
18559
18560
|
class SkillsManager {
|
|
@@ -19006,6 +19007,22 @@ class SkillsManager {
|
|
|
19006
19007
|
mode: "symlink"
|
|
19007
19008
|
};
|
|
19008
19009
|
}
|
|
19010
|
+
async previewInstallStatus(skill, projectPath, options2 = {}) {
|
|
19011
|
+
if (options2.sharedStore) {
|
|
19012
|
+
const plan2 = this.getCanonicalInstallPlan(skill.name, projectPath, {
|
|
19013
|
+
...options2.global !== undefined ? { global: options2.global } : {}
|
|
19014
|
+
});
|
|
19015
|
+
return this.compareSkillSnapshot(skill, plan2.path);
|
|
19016
|
+
}
|
|
19017
|
+
if (!options2.agent) {
|
|
19018
|
+
throw new Error("Agent is required to preview install status");
|
|
19019
|
+
}
|
|
19020
|
+
const plan = await this.getInstallPlan(skill.name, options2.agent, projectPath, {
|
|
19021
|
+
...options2.global !== undefined ? { global: options2.global } : {},
|
|
19022
|
+
...options2.copy !== undefined ? { copy: options2.copy } : {}
|
|
19023
|
+
});
|
|
19024
|
+
return this.compareSkillSnapshot(skill, plan.canonicalPath || plan.path);
|
|
19025
|
+
}
|
|
19009
19026
|
async installSkillForAgent(skillPath, skillName, agent, projectPath, options2 = {}) {
|
|
19010
19027
|
const plan = await this.getInstallPlan(skillName, agent, projectPath, options2);
|
|
19011
19028
|
const skillsDir = agent.getSkillsDir(projectPath, options2.global);
|
|
@@ -19108,6 +19125,52 @@ class SkillsManager {
|
|
|
19108
19125
|
getInstallPath(skillName, targetDir) {
|
|
19109
19126
|
return this.resolveInstallPath(targetDir, this.normalizeSkillName(skillName));
|
|
19110
19127
|
}
|
|
19128
|
+
updateSnapshotWithFile(hash, relativePath, content) {
|
|
19129
|
+
hash.update(`file:${relativePath}\n`);
|
|
19130
|
+
hash.update(content);
|
|
19131
|
+
hash.update("\n");
|
|
19132
|
+
}
|
|
19133
|
+
async createDirectorySnapshot(rootPath) {
|
|
19134
|
+
if (!await fileExists(rootPath))
|
|
19135
|
+
return null;
|
|
19136
|
+
const hash = createHash("sha256");
|
|
19137
|
+
const walk = async (currentPath, relativePath) => {
|
|
19138
|
+
const stat = await fs24.stat(currentPath);
|
|
19139
|
+
if (!stat.isDirectory()) {
|
|
19140
|
+
const content = await fs24.readFile(currentPath);
|
|
19141
|
+
this.updateSnapshotWithFile(hash, relativePath, content);
|
|
19142
|
+
return;
|
|
19143
|
+
}
|
|
19144
|
+
hash.update(`dir:${relativePath || "."}\n`);
|
|
19145
|
+
const entries = (await fs24.readdir(currentPath)).sort((left, right) => left.localeCompare(right));
|
|
19146
|
+
for (const entry of entries) {
|
|
19147
|
+
await walk(join5(currentPath, entry), relativePath ? join5(relativePath, entry) : entry);
|
|
19148
|
+
}
|
|
19149
|
+
};
|
|
19150
|
+
await walk(rootPath, "");
|
|
19151
|
+
return hash.digest("hex");
|
|
19152
|
+
}
|
|
19153
|
+
async readExistingSkillSnapshot(installPath) {
|
|
19154
|
+
return this.createDirectorySnapshot(installPath);
|
|
19155
|
+
}
|
|
19156
|
+
async getNewSkillSnapshot(skill) {
|
|
19157
|
+
if (skill.generatedContent) {
|
|
19158
|
+
const hash = createHash("sha256");
|
|
19159
|
+
hash.update("dir:.\n");
|
|
19160
|
+
this.updateSnapshotWithFile(hash, "SKILL.md", skill.generatedContent.trim());
|
|
19161
|
+
return hash.digest("hex");
|
|
19162
|
+
}
|
|
19163
|
+
return this.createDirectorySnapshot(skill.path);
|
|
19164
|
+
}
|
|
19165
|
+
async compareSkillSnapshot(skill, installPath) {
|
|
19166
|
+
const existing = await this.readExistingSkillSnapshot(installPath);
|
|
19167
|
+
if (existing === null)
|
|
19168
|
+
return "new";
|
|
19169
|
+
const incoming = await this.getNewSkillSnapshot(skill);
|
|
19170
|
+
if (incoming === null)
|
|
19171
|
+
return "new";
|
|
19172
|
+
return existing === incoming ? "unchanged" : "changed";
|
|
19173
|
+
}
|
|
19111
19174
|
async cleanAndCreateDirectory(path) {
|
|
19112
19175
|
await fs24.rm(path, { recursive: true, force: true }).catch(() => {
|
|
19113
19176
|
});
|
|
@@ -19128,7 +19191,7 @@ class SkillsManager {
|
|
|
19128
19191
|
try {
|
|
19129
19192
|
let skills2 = context.skills;
|
|
19130
19193
|
if (skills2.length === 0) {
|
|
19131
|
-
return { installed: [], skipped: [], warnings: context.warnings };
|
|
19194
|
+
return { installed: [], updated: [], unchanged: [], skipped: [], warnings: context.warnings };
|
|
19132
19195
|
}
|
|
19133
19196
|
if (options2.skills && options2.skills.length > 0) {
|
|
19134
19197
|
const names = new Set(options2.skills.map((skill) => skill.toLowerCase()));
|
|
@@ -19139,18 +19202,33 @@ class SkillsManager {
|
|
|
19139
19202
|
if (agents.length === 0 && !installToSharedStore) {
|
|
19140
19203
|
return {
|
|
19141
19204
|
installed: [],
|
|
19205
|
+
updated: [],
|
|
19206
|
+
unchanged: [],
|
|
19142
19207
|
skipped: skills2.map((skill) => ({ skill, reason: "No target agents found" })),
|
|
19143
19208
|
warnings: context.warnings
|
|
19144
19209
|
};
|
|
19145
19210
|
}
|
|
19146
|
-
const result = { installed: [], skipped: [], warnings: context.warnings };
|
|
19211
|
+
const result = { installed: [], updated: [], unchanged: [], skipped: [], warnings: context.warnings };
|
|
19147
19212
|
const installableAgents = [];
|
|
19213
|
+
const comparisonCache = new Map;
|
|
19214
|
+
const pendingUpdates = [];
|
|
19148
19215
|
if (installToSharedStore) {
|
|
19149
19216
|
for (const skill of skills2) {
|
|
19150
19217
|
try {
|
|
19151
19218
|
const installOptions = {
|
|
19152
19219
|
...options2.global !== undefined ? { global: options2.global } : {}
|
|
19153
19220
|
};
|
|
19221
|
+
const plan = this.getCanonicalInstallPlan(skill.name, projectPath, installOptions);
|
|
19222
|
+
const comparison = await this.compareSkillSnapshot(skill, plan.path);
|
|
19223
|
+
comparisonCache.set(plan.path, comparison);
|
|
19224
|
+
if (comparison === "unchanged") {
|
|
19225
|
+
result.unchanged.push({ skill, agent: SHARED_SKILLS_TARGET_ID, path: plan.path });
|
|
19226
|
+
continue;
|
|
19227
|
+
}
|
|
19228
|
+
if (comparison === "changed") {
|
|
19229
|
+
pendingUpdates.push({ skill, agent: SHARED_SKILLS_TARGET_ID, installOptions });
|
|
19230
|
+
continue;
|
|
19231
|
+
}
|
|
19154
19232
|
const installed = skill.generatedContent ? await this.installSkillFromContentToCanonicalStore(skill.name, skill.generatedContent, projectPath, installOptions) : await this.installSkillToCanonicalStore(skill.path, skill.name, projectPath, installOptions);
|
|
19155
19233
|
result.installed.push({ skill, agent: SHARED_SKILLS_TARGET_ID, ...installed });
|
|
19156
19234
|
} catch (error) {
|
|
@@ -19181,6 +19259,21 @@ class SkillsManager {
|
|
|
19181
19259
|
...options2.global !== undefined ? { global: options2.global } : {},
|
|
19182
19260
|
...options2.copy !== undefined ? { copy: options2.copy } : {}
|
|
19183
19261
|
};
|
|
19262
|
+
const plan = await this.getInstallPlan(skill.name, agent, projectPath, installOptions);
|
|
19263
|
+
const comparisonPath = plan.canonicalPath || plan.path;
|
|
19264
|
+
let comparison = comparisonCache.get(comparisonPath);
|
|
19265
|
+
if (comparison === undefined) {
|
|
19266
|
+
comparison = await this.compareSkillSnapshot(skill, comparisonPath);
|
|
19267
|
+
comparisonCache.set(comparisonPath, comparison);
|
|
19268
|
+
}
|
|
19269
|
+
if (comparison === "unchanged") {
|
|
19270
|
+
result.unchanged.push({ skill, agent: agent.id, path: comparisonPath });
|
|
19271
|
+
continue;
|
|
19272
|
+
}
|
|
19273
|
+
if (comparison === "changed") {
|
|
19274
|
+
pendingUpdates.push({ skill, agent: agent.id, agentObj: agent, installOptions });
|
|
19275
|
+
continue;
|
|
19276
|
+
}
|
|
19184
19277
|
const installed = skill.generatedContent ? await this.installSkillFromContentForAgent(skill.name, skill.generatedContent, agent, projectPath, installOptions) : await this.installSkillForAgent(skill.path, skill.name, agent, projectPath, installOptions);
|
|
19185
19278
|
result.installed.push({ skill, agent: agent.id, ...installed });
|
|
19186
19279
|
} catch (error) {
|
|
@@ -19188,6 +19281,35 @@ class SkillsManager {
|
|
|
19188
19281
|
}
|
|
19189
19282
|
}
|
|
19190
19283
|
}
|
|
19284
|
+
if (pendingUpdates.length > 0) {
|
|
19285
|
+
let approvedNames;
|
|
19286
|
+
if (options2.yes) {
|
|
19287
|
+
approvedNames = new Set(pendingUpdates.map((p) => p.skill.name));
|
|
19288
|
+
} else if (options2.confirmUpdate) {
|
|
19289
|
+
const uniqueSkills = [...new Map(pendingUpdates.map((p) => [p.skill.name, p.skill])).values()];
|
|
19290
|
+
const approved = await options2.confirmUpdate(uniqueSkills);
|
|
19291
|
+
approvedNames = new Set(approved.map((s) => s.name));
|
|
19292
|
+
} else {
|
|
19293
|
+
approvedNames = new Set;
|
|
19294
|
+
}
|
|
19295
|
+
for (const pending of pendingUpdates) {
|
|
19296
|
+
if (!approvedNames.has(pending.skill.name)) {
|
|
19297
|
+
result.skipped.push({ skill: pending.skill, reason: "Update available; re-run with -y to update" });
|
|
19298
|
+
continue;
|
|
19299
|
+
}
|
|
19300
|
+
try {
|
|
19301
|
+
if (pending.agent === SHARED_SKILLS_TARGET_ID) {
|
|
19302
|
+
const installed = pending.skill.generatedContent ? await this.installSkillFromContentToCanonicalStore(pending.skill.name, pending.skill.generatedContent, projectPath, pending.installOptions) : await this.installSkillToCanonicalStore(pending.skill.path, pending.skill.name, projectPath, pending.installOptions);
|
|
19303
|
+
result.updated.push({ skill: pending.skill, agent: pending.agent, ...installed });
|
|
19304
|
+
} else if (pending.agentObj) {
|
|
19305
|
+
const installed = pending.skill.generatedContent ? await this.installSkillFromContentForAgent(pending.skill.name, pending.skill.generatedContent, pending.agentObj, projectPath, pending.installOptions) : await this.installSkillForAgent(pending.skill.path, pending.skill.name, pending.agentObj, projectPath, pending.installOptions);
|
|
19306
|
+
result.updated.push({ skill: pending.skill, agent: pending.agent, ...installed });
|
|
19307
|
+
}
|
|
19308
|
+
} catch (error) {
|
|
19309
|
+
result.skipped.push({ skill: pending.skill, reason: error.message });
|
|
19310
|
+
}
|
|
19311
|
+
}
|
|
19312
|
+
}
|
|
19191
19313
|
return result;
|
|
19192
19314
|
} finally {
|
|
19193
19315
|
await context.cleanup();
|
|
@@ -41300,7 +41422,7 @@ init_skills();
|
|
|
41300
41422
|
function registerSkillsCommand(program2) {
|
|
41301
41423
|
const marketplaceHelp = getMarketplaceIds().join(", ");
|
|
41302
41424
|
const skills3 = program2.command("skills").description("Manage agent skills");
|
|
41303
|
-
skills3.command("add <source>").description("Add skills from a marketplace, GitHub repo, or local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-g, --global", "Install skills globally").option("-a, --agent <agents...>", "Target specific agent(s)").option("-s, --skill <names...>", "Install only specific skills by name").option("-l, --list", "List available skills from the source without installing").option("--all", "Select all bundled plugins when the source contains multiple plugins").option("--copy", "Copy skill files instead of symlinking").option("-y, --yes", "Skip prompts
|
|
41425
|
+
skills3.command("add <source>").description("Add skills from a marketplace, GitHub repo, or local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-g, --global", "Install skills globally").option("-a, --agent <agents...>", "Target specific agent(s)").option("-s, --skill <names...>", "Install only specific skills by name").option("-l, --list", "List available skills from the source without installing").option("--all", "Select all bundled plugins when the source contains multiple plugins").option("--copy", "Copy skill files instead of symlinking").option("-y, --yes", "Skip prompts, auto-detect project-configured agents, and apply available skill updates").action(async (source, options2) => {
|
|
41304
41426
|
logger.titleBox("AgentInit Skills");
|
|
41305
41427
|
const agentManager9 = new AgentManager;
|
|
41306
41428
|
const skillsManager5 = new SkillsManager(agentManager9);
|
|
@@ -41342,10 +41464,12 @@ function registerSkillsCommand(program2) {
|
|
|
41342
41464
|
}
|
|
41343
41465
|
const verifySpinner = ora("Verifying skill source...").start();
|
|
41344
41466
|
let selectedPluginNames;
|
|
41467
|
+
let preparedSkills = [];
|
|
41345
41468
|
try {
|
|
41346
|
-
await skillsManager5.prepareSource(source, process.cwd(), {
|
|
41469
|
+
const prepared = await skillsManager5.prepareSource(source, process.cwd(), {
|
|
41347
41470
|
from: options2.from
|
|
41348
41471
|
});
|
|
41472
|
+
preparedSkills = prepared.skills;
|
|
41349
41473
|
verifySpinner.stop();
|
|
41350
41474
|
} catch (error) {
|
|
41351
41475
|
if (error instanceof MultipleBundlePluginsError && (options2.all || !options2.yes)) {
|
|
@@ -41357,10 +41481,11 @@ function registerSkillsCommand(program2) {
|
|
|
41357
41481
|
selectedPluginNames = selected;
|
|
41358
41482
|
const retrySpinner = ora("Verifying skill source...").start();
|
|
41359
41483
|
try {
|
|
41360
|
-
await skillsManager5.prepareSource(source, process.cwd(), {
|
|
41484
|
+
const prepared = await skillsManager5.prepareSource(source, process.cwd(), {
|
|
41361
41485
|
from: options2.from,
|
|
41362
41486
|
...selectedPluginNames[0] ? { pluginName: selectedPluginNames[0] } : {}
|
|
41363
41487
|
});
|
|
41488
|
+
preparedSkills = prepared.skills;
|
|
41364
41489
|
retrySpinner.stop();
|
|
41365
41490
|
} catch (retryError) {
|
|
41366
41491
|
retrySpinner.fail("Failed to verify skill source");
|
|
@@ -41376,9 +41501,13 @@ function registerSkillsCommand(program2) {
|
|
|
41376
41501
|
let targetAgents = options2.agent;
|
|
41377
41502
|
let targetGlobal = options2.global;
|
|
41378
41503
|
if (!targetAgents && !options2.yes) {
|
|
41504
|
+
const selectedSkillNames = options2.skill && options2.skill.length > 0 ? new Set(options2.skill.map((name) => name.toLowerCase())) : undefined;
|
|
41505
|
+
const filteredPreviewSkills = selectedSkillNames ? preparedSkills.filter((skill) => selectedSkillNames.has(skill.name.toLowerCase())) : preparedSkills;
|
|
41379
41506
|
const selection = await resolveInteractiveSkillTargets(skillsManager5, agentManager9, source, process.cwd(), {
|
|
41380
41507
|
from: options2.from,
|
|
41381
|
-
global: options2.global
|
|
41508
|
+
global: options2.global,
|
|
41509
|
+
copy: options2.copy,
|
|
41510
|
+
skills: filteredPreviewSkills
|
|
41382
41511
|
});
|
|
41383
41512
|
if (selection?.aborted) {
|
|
41384
41513
|
await skillsManager5.discardPreparedSource(source, process.cwd(), {
|
|
@@ -41391,6 +41520,16 @@ function registerSkillsCommand(program2) {
|
|
|
41391
41520
|
targetGlobal = selection.global;
|
|
41392
41521
|
}
|
|
41393
41522
|
}
|
|
41523
|
+
const confirmUpdate = options2.yes ? undefined : async (skills4) => {
|
|
41524
|
+
const names = skills4.map((s) => s.name).join(", ");
|
|
41525
|
+
const response = await import_prompts3.default({
|
|
41526
|
+
type: "confirm",
|
|
41527
|
+
name: "update",
|
|
41528
|
+
message: skills4.length === 1 ? `Skill "${skills4[0].name}" has been updated. Update it?` : `${skills4.length} skill(s) have updates (${names}). Update them?`,
|
|
41529
|
+
initial: true
|
|
41530
|
+
});
|
|
41531
|
+
return response.update ? skills4 : [];
|
|
41532
|
+
};
|
|
41394
41533
|
const buildInstallOptions = (pluginName) => ({
|
|
41395
41534
|
...options2.from !== undefined ? { from: options2.from } : {},
|
|
41396
41535
|
...targetGlobal !== undefined ? { global: targetGlobal } : {},
|
|
@@ -41398,7 +41537,8 @@ function registerSkillsCommand(program2) {
|
|
|
41398
41537
|
...options2.skill !== undefined ? { skills: options2.skill } : {},
|
|
41399
41538
|
...options2.copy !== undefined ? { copy: options2.copy } : {},
|
|
41400
41539
|
...pluginName !== undefined ? { pluginName } : {},
|
|
41401
|
-
...options2.yes !== undefined ? { yes: options2.yes } : {}
|
|
41540
|
+
...options2.yes !== undefined ? { yes: options2.yes } : {},
|
|
41541
|
+
...confirmUpdate !== undefined ? { confirmUpdate } : {}
|
|
41402
41542
|
});
|
|
41403
41543
|
const pluginsToInstall = selectedPluginNames || [undefined];
|
|
41404
41544
|
for (const pluginName of pluginsToInstall) {
|
|
@@ -41539,11 +41679,18 @@ async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, sou
|
|
|
41539
41679
|
name: "groups",
|
|
41540
41680
|
message: installGlobal ? "Select which global agent skills directories to install into:" : detectedGroups.length > 0 ? "Select which project agent skills directories to install into:" : "Select which project agent skills directories to install into manually:",
|
|
41541
41681
|
min: 1,
|
|
41542
|
-
choices: availableGroups.map((group) =>
|
|
41543
|
-
|
|
41544
|
-
|
|
41545
|
-
|
|
41546
|
-
|
|
41682
|
+
choices: await Promise.all(availableGroups.map(async (group) => {
|
|
41683
|
+
const description = await buildSkillGroupPreviewDescription(skillsManager5, group, projectPath, {
|
|
41684
|
+
global: installGlobal,
|
|
41685
|
+
...options2.copy !== undefined ? { copy: options2.copy } : {},
|
|
41686
|
+
...options2.skills !== undefined ? { skills: options2.skills } : {}
|
|
41687
|
+
});
|
|
41688
|
+
return {
|
|
41689
|
+
title: formatSkillGroupTitle(group),
|
|
41690
|
+
...description ? { description } : {},
|
|
41691
|
+
value: group.kind === "canonical-shared" ? [SHARED_SKILLS_TARGET_ID] : group.agents.map((agent) => agent.id),
|
|
41692
|
+
selected: shouldPreselectSkillGroup(group, installGlobal, detectedGroups.length > 0, recommendedAgentId)
|
|
41693
|
+
};
|
|
41547
41694
|
}))
|
|
41548
41695
|
});
|
|
41549
41696
|
const selected = flattenAgentIds(response.groups);
|
|
@@ -41692,6 +41839,33 @@ var describeGlobalSkillGroup = function(group) {
|
|
|
41692
41839
|
}
|
|
41693
41840
|
return;
|
|
41694
41841
|
};
|
|
41842
|
+
async function buildSkillGroupPreviewDescription(skillsManager5, group, projectPath, options2) {
|
|
41843
|
+
const skills3 = options2.skills || [];
|
|
41844
|
+
if (skills3.length === 0) {
|
|
41845
|
+
return group.description || describeGlobalSkillGroup(group);
|
|
41846
|
+
}
|
|
41847
|
+
const statuses = await Promise.all(skills3.map(async (skill) => ({
|
|
41848
|
+
skill,
|
|
41849
|
+
status: await skillsManager5.previewInstallStatus(skill, projectPath, group.kind === "canonical-shared" ? { global: options2.global, sharedStore: true } : {
|
|
41850
|
+
global: options2.global,
|
|
41851
|
+
...options2.copy !== undefined ? { copy: options2.copy } : {},
|
|
41852
|
+
...group.agents[0] ? { agent: group.agents[0] } : {}
|
|
41853
|
+
})
|
|
41854
|
+
})));
|
|
41855
|
+
const unchanged = statuses.filter((entry) => entry.status === "unchanged").map((entry) => entry.skill.name);
|
|
41856
|
+
const changed = statuses.filter((entry) => entry.status === "changed").map((entry) => entry.skill.name);
|
|
41857
|
+
const parts = [];
|
|
41858
|
+
if (unchanged.length > 0) {
|
|
41859
|
+
parts.push(`Already up to date: ${unchanged.join(", ")}`);
|
|
41860
|
+
}
|
|
41861
|
+
if (changed.length > 0) {
|
|
41862
|
+
parts.push(`${changed.length === 1 ? "Update available" : "Updates available"}: ${changed.join(", ")}`);
|
|
41863
|
+
}
|
|
41864
|
+
if (parts.length === 0) {
|
|
41865
|
+
return;
|
|
41866
|
+
}
|
|
41867
|
+
return parts.join(". ");
|
|
41868
|
+
}
|
|
41695
41869
|
var formatSkillGroupTitle = function(group) {
|
|
41696
41870
|
if (group.kind === "canonical-shared") {
|
|
41697
41871
|
return `${group.displayDir} -> ${SHARED_SKILLS_TARGET_NAME}`;
|
|
@@ -41779,14 +41953,18 @@ var displayDiscoveredSkills = function(skills3, warnings) {
|
|
|
41779
41953
|
}
|
|
41780
41954
|
};
|
|
41781
41955
|
var displayInstallResult = function(result, spinner, agentManager9, skillsManager5, source, options2) {
|
|
41782
|
-
|
|
41956
|
+
const hasInstalled = result.installed.length > 0;
|
|
41957
|
+
const hasUpdated = result.updated.length > 0;
|
|
41958
|
+
const hasUnchanged = result.unchanged.length > 0;
|
|
41959
|
+
const hasSkipped = result.skipped.length > 0;
|
|
41960
|
+
if (!hasInstalled && !hasUpdated && !hasUnchanged && !hasSkipped) {
|
|
41783
41961
|
spinner.warn("No skills found in the source.");
|
|
41784
41962
|
for (const warning of result.warnings) {
|
|
41785
41963
|
logger.warn(warning);
|
|
41786
41964
|
}
|
|
41787
41965
|
return;
|
|
41788
41966
|
}
|
|
41789
|
-
if (
|
|
41967
|
+
if (!hasInstalled && !hasUpdated && !hasUnchanged && hasSkipped && result.skipped.every((skip) => skip.reason === "No target agents found")) {
|
|
41790
41968
|
spinner.warn("No target agents found.");
|
|
41791
41969
|
logNoTargetAgentsGuidance(skillsManager5, agentManager9, source, {
|
|
41792
41970
|
...options2.from !== undefined ? { from: options2.from } : {}
|
|
@@ -41799,29 +41977,63 @@ var displayInstallResult = function(result, spinner, agentManager9, skillsManage
|
|
|
41799
41977
|
}
|
|
41800
41978
|
return;
|
|
41801
41979
|
}
|
|
41802
|
-
|
|
41803
|
-
|
|
41804
|
-
|
|
41805
|
-
|
|
41806
|
-
|
|
41807
|
-
const
|
|
41808
|
-
|
|
41809
|
-
|
|
41810
|
-
|
|
41811
|
-
|
|
41812
|
-
|
|
41813
|
-
|
|
41814
|
-
|
|
41815
|
-
|
|
41816
|
-
|
|
41817
|
-
|
|
41818
|
-
|
|
41980
|
+
if (!hasInstalled && !hasUpdated && hasUnchanged) {
|
|
41981
|
+
const uniqueUnchanged = new Set(result.unchanged.map((item) => item.skill.name));
|
|
41982
|
+
spinner.info(`${uniqueUnchanged.size} skill(s) already up to date`);
|
|
41983
|
+
logger.info(dim(` Already installed: ${[...uniqueUnchanged].join(", ")}`));
|
|
41984
|
+
} else {
|
|
41985
|
+
const parts = [];
|
|
41986
|
+
if (hasInstalled) {
|
|
41987
|
+
const uniqueInstallCount = new Set(result.installed.map((item) => `${item.path}:${item.skill.name}`)).size;
|
|
41988
|
+
parts.push(`Installed ${green(String(uniqueInstallCount))}`);
|
|
41989
|
+
}
|
|
41990
|
+
if (hasUpdated) {
|
|
41991
|
+
const uniqueUpdateCount = new Set(result.updated.map((item) => `${item.path}:${item.skill.name}`)).size;
|
|
41992
|
+
parts.push(`Updated ${yellow(String(uniqueUpdateCount))}`);
|
|
41993
|
+
}
|
|
41994
|
+
if (hasUnchanged) {
|
|
41995
|
+
const uniqueUnchanged = new Set(result.unchanged.map((item) => item.skill.name)).size;
|
|
41996
|
+
parts.push(`${uniqueUnchanged} already up to date`);
|
|
41997
|
+
}
|
|
41998
|
+
spinner.succeed(`${parts.join(", ")} skill(s)`);
|
|
41999
|
+
const byPath = new Map;
|
|
42000
|
+
for (const item of result.installed) {
|
|
42001
|
+
const path = item.path;
|
|
42002
|
+
const existing = byPath.get(path) || {
|
|
42003
|
+
agents: new Set,
|
|
42004
|
+
skills: new Set
|
|
42005
|
+
};
|
|
42006
|
+
existing.agents.add(formatSkillTargetName(agentManager9, item.agent));
|
|
42007
|
+
existing.skills.add(item.skill.name);
|
|
42008
|
+
byPath.set(path, existing);
|
|
42009
|
+
}
|
|
42010
|
+
for (const [path, details] of byPath) {
|
|
42011
|
+
logger.info(` ${relative7(process.cwd(), path) || path}`);
|
|
42012
|
+
logger.info(` Agents: ${[...details.agents].join(", ")}`);
|
|
42013
|
+
logger.info(` Skills: ${green(String(details.skills.size))} installed (${[...details.skills].join(", ")})`);
|
|
42014
|
+
}
|
|
42015
|
+
const byPathUpdated = new Map;
|
|
42016
|
+
for (const item of result.updated) {
|
|
42017
|
+
const path = item.path;
|
|
42018
|
+
const existing = byPathUpdated.get(path) || {
|
|
42019
|
+
agents: new Set,
|
|
42020
|
+
skills: new Set
|
|
42021
|
+
};
|
|
42022
|
+
existing.agents.add(formatSkillTargetName(agentManager9, item.agent));
|
|
42023
|
+
existing.skills.add(item.skill.name);
|
|
42024
|
+
byPathUpdated.set(path, existing);
|
|
42025
|
+
}
|
|
42026
|
+
for (const [path, details] of byPathUpdated) {
|
|
42027
|
+
logger.info(` ${relative7(process.cwd(), path) || path}`);
|
|
42028
|
+
logger.info(` Agents: ${[...details.agents].join(", ")}`);
|
|
42029
|
+
logger.info(` Skills: ${yellow(String(details.skills.size))} updated (${[...details.skills].join(", ")})`);
|
|
42030
|
+
}
|
|
41819
42031
|
}
|
|
41820
|
-
const copiedFallbacks = result.installed.filter((item) => item.symlinkFailed);
|
|
42032
|
+
const copiedFallbacks = [...result.installed, ...result.updated].filter((item) => item.symlinkFailed);
|
|
41821
42033
|
if (copiedFallbacks.length > 0) {
|
|
41822
42034
|
logger.warn(`Symlink creation failed for ${copiedFallbacks.length} install(s); copied the skill files instead.`);
|
|
41823
42035
|
}
|
|
41824
|
-
if (
|
|
42036
|
+
if (hasSkipped) {
|
|
41825
42037
|
logger.info("");
|
|
41826
42038
|
logger.warn(`Skipped ${result.skipped.length} skill(s):`);
|
|
41827
42039
|
for (const skip of result.skipped) {
|
|
@@ -41834,7 +42046,9 @@ var displayInstallResult = function(result, spinner, agentManager9, skillsManage
|
|
|
41834
42046
|
logger.warn(warning);
|
|
41835
42047
|
}
|
|
41836
42048
|
}
|
|
41837
|
-
|
|
42049
|
+
if (hasInstalled || hasUpdated) {
|
|
42050
|
+
logger.success("Skills installation complete.");
|
|
42051
|
+
}
|
|
41838
42052
|
};
|
|
41839
42053
|
|
|
41840
42054
|
// dist/commands/mcp.js
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqCpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"skills.d.ts","sourceRoot":"","sources":["../../src/commands/skills.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqCpC,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAqS5D"}
|