agentinit 1.17.2 → 1.18.1
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 +22 -0
- package/README.md +10 -2
- package/dist/cli.js +261 -84
- package/dist/commands/plugins.d.ts.map +1 -1
- package/dist/commands/plugins.js +7 -27
- package/dist/commands/plugins.js.map +1 -1
- package/dist/commands/skills.d.ts.map +1 -1
- package/dist/commands/skills.js +89 -51
- package/dist/commands/skills.js.map +1 -1
- package/dist/core/skillsManager.d.ts +5 -0
- package/dist/core/skillsManager.d.ts.map +1 -1
- package/dist/core/skillsManager.js +119 -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/dist/utils/promptUtils.d.ts +26 -0
- package/dist/utils/promptUtils.d.ts.map +1 -0
- package/dist/utils/promptUtils.js +65 -0
- package/dist/utils/promptUtils.js.map +1 -0
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,24 @@
|
|
|
1
|
+
## [1.18.1](https://github.com/agentinit/agentinit/compare/v1.18.0...v1.18.1) (2026-04-05)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* **skills:** compare full skill payloads before updates ([4b1e27c](https://github.com/agentinit/agentinit/commit/4b1e27cc69264d46edb38c2f6435b7f2659cfdb3))
|
|
7
|
+
|
|
8
|
+
## [Unreleased]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
### Bug Fixes
|
|
12
|
+
|
|
13
|
+
* **skills:** compare installed skill payloads before prompting for updates
|
|
14
|
+
|
|
15
|
+
# [1.18.0](https://github.com/agentinit/agentinit/compare/v1.17.2...v1.18.0) (2026-04-04)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* **cli:** support selecting all bundled plugins ([2e533d7](https://github.com/agentinit/agentinit/commit/2e533d7bea4d6fd4c0c2a74982b169e80d9192bd))
|
|
21
|
+
|
|
1
22
|
## [1.17.2](https://github.com/agentinit/agentinit/compare/v1.17.1...v1.17.2) (2026-04-02)
|
|
2
23
|
|
|
3
24
|
|
|
@@ -184,6 +205,7 @@
|
|
|
184
205
|
* fix plugin scope handling for global MCP installs/removals and targeted removals
|
|
185
206
|
* preserve revert semantics for canonical project skills and keep `skills remove` project-scoped by default
|
|
186
207
|
* prevent `skills remove` from deleting shared native skill paths that are still used by another agent
|
|
208
|
+
* support `--all` when listing or installing from multi-plugin Claude bundles and document the updated multiselect shortcut
|
|
187
209
|
* update docs and onboarding to the `mcp add|verify`, `rules add`, and `skills add` command model
|
|
188
210
|
* parse Claude Code marketplace bundle repos like `openai/codex-plugin-cc` when installing portable skills or plugins
|
|
189
211
|
* keep interactive plugin target defaults on all detected agents, warn clearly when Claude-native payloads are skipped, and reuse the previewed remote source during install
|
package/README.md
CHANGED
|
@@ -208,16 +208,21 @@ agentinit skills add owner/repo --global --agent agents
|
|
|
208
208
|
# Force copied installs instead of canonical symlink installs
|
|
209
209
|
agentinit skills add ./skills --copy
|
|
210
210
|
|
|
211
|
+
# Install every bundled plugin from a multi-plugin Claude bundle
|
|
212
|
+
agentinit skills add owner/repo --all
|
|
213
|
+
|
|
211
214
|
# Review and clean up installed skills
|
|
212
215
|
agentinit skills list
|
|
213
216
|
agentinit skills list --agent agents
|
|
214
217
|
agentinit skills remove openai-docs
|
|
215
218
|
```
|
|
216
219
|
|
|
217
|
-
If a GitHub or local Claude bundle contains multiple plugins, `agentinit skills add` prompts you to choose one or more bundled plugins to inspect or install. Press `Space` to select and `Enter` to confirm. In non-interactive `--yes` mode, ambiguous multi-plugin bundles fail
|
|
220
|
+
If a GitHub or local Claude bundle contains multiple plugins, `agentinit skills add` prompts you to choose one or more bundled plugins to inspect or install. Press `Space` to select, `A` to select or deselect all, and `Enter` to confirm. Use `--all` to skip the prompt and install or inspect every bundled plugin. In non-interactive `--yes` mode, ambiguous multi-plugin bundles still fail unless `--all` is provided.
|
|
218
221
|
|
|
219
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.
|
|
220
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
|
+
|
|
221
226
|
### `agentinit plugins`
|
|
222
227
|
|
|
223
228
|
Install, inspect, search, and remove portable plugins from explicit marketplace sources, GitHub repositories, or local paths.
|
|
@@ -245,6 +250,9 @@ agentinit plugins install owner/repo
|
|
|
245
250
|
agentinit plugins install ./plugins/code-review
|
|
246
251
|
agentinit plugins install ./plugins/code-review --copy-skills
|
|
247
252
|
|
|
253
|
+
# Install every bundled plugin from a multi-plugin Claude bundle
|
|
254
|
+
agentinit plugins install owner/repo --all
|
|
255
|
+
|
|
248
256
|
# Inspect and remove installed plugins
|
|
249
257
|
agentinit plugins list
|
|
250
258
|
agentinit plugins remove code-review
|
|
@@ -252,7 +260,7 @@ agentinit plugins remove code-review
|
|
|
252
260
|
|
|
253
261
|
Bare plugin names resolve through your configured default marketplace. Built-in marketplaces include `claude` and `openai`; add custom ones with `agentinit config marketplaces add`. For Claude-format plugins, native bundles are installed into `~/.claude/plugins` alongside portable skill and MCP installs.
|
|
254
262
|
|
|
255
|
-
If a GitHub or local Claude bundle contains multiple plugins, `agentinit plugins install` prompts you to choose one or more bundled plugins to inspect or install. Press `Space` to select and `Enter` to confirm. In non-interactive `--yes` mode, ambiguous multi-plugin bundles fail
|
|
263
|
+
If a GitHub or local Claude bundle contains multiple plugins, `agentinit plugins install` prompts you to choose one or more bundled plugins to inspect or install. Press `Space` to select, `A` to select or deselect all, and `Enter` to confirm. Use `--all` to skip the prompt and install or inspect every bundled plugin. In non-interactive `--yes` mode, ambiguous multi-plugin bundles still fail unless `--all` is provided.
|
|
256
264
|
|
|
257
265
|
### `agentinit config`
|
|
258
266
|
|
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 {
|
|
@@ -19108,6 +19109,52 @@ class SkillsManager {
|
|
|
19108
19109
|
getInstallPath(skillName, targetDir) {
|
|
19109
19110
|
return this.resolveInstallPath(targetDir, this.normalizeSkillName(skillName));
|
|
19110
19111
|
}
|
|
19112
|
+
updateSnapshotWithFile(hash, relativePath, content) {
|
|
19113
|
+
hash.update(`file:${relativePath}\n`);
|
|
19114
|
+
hash.update(content);
|
|
19115
|
+
hash.update("\n");
|
|
19116
|
+
}
|
|
19117
|
+
async createDirectorySnapshot(rootPath) {
|
|
19118
|
+
if (!await fileExists(rootPath))
|
|
19119
|
+
return null;
|
|
19120
|
+
const hash = createHash("sha256");
|
|
19121
|
+
const walk = async (currentPath, relativePath) => {
|
|
19122
|
+
const stat = await fs24.stat(currentPath);
|
|
19123
|
+
if (!stat.isDirectory()) {
|
|
19124
|
+
const content = await fs24.readFile(currentPath);
|
|
19125
|
+
this.updateSnapshotWithFile(hash, relativePath, content);
|
|
19126
|
+
return;
|
|
19127
|
+
}
|
|
19128
|
+
hash.update(`dir:${relativePath || "."}\n`);
|
|
19129
|
+
const entries = (await fs24.readdir(currentPath)).sort((left, right) => left.localeCompare(right));
|
|
19130
|
+
for (const entry of entries) {
|
|
19131
|
+
await walk(join5(currentPath, entry), relativePath ? join5(relativePath, entry) : entry);
|
|
19132
|
+
}
|
|
19133
|
+
};
|
|
19134
|
+
await walk(rootPath, "");
|
|
19135
|
+
return hash.digest("hex");
|
|
19136
|
+
}
|
|
19137
|
+
async readExistingSkillSnapshot(installPath) {
|
|
19138
|
+
return this.createDirectorySnapshot(installPath);
|
|
19139
|
+
}
|
|
19140
|
+
async getNewSkillSnapshot(skill) {
|
|
19141
|
+
if (skill.generatedContent) {
|
|
19142
|
+
const hash = createHash("sha256");
|
|
19143
|
+
hash.update("dir:.\n");
|
|
19144
|
+
this.updateSnapshotWithFile(hash, "SKILL.md", skill.generatedContent.trim());
|
|
19145
|
+
return hash.digest("hex");
|
|
19146
|
+
}
|
|
19147
|
+
return this.createDirectorySnapshot(skill.path);
|
|
19148
|
+
}
|
|
19149
|
+
async compareSkillSnapshot(skill, installPath) {
|
|
19150
|
+
const existing = await this.readExistingSkillSnapshot(installPath);
|
|
19151
|
+
if (existing === null)
|
|
19152
|
+
return "new";
|
|
19153
|
+
const incoming = await this.getNewSkillSnapshot(skill);
|
|
19154
|
+
if (incoming === null)
|
|
19155
|
+
return "new";
|
|
19156
|
+
return existing === incoming ? "unchanged" : "changed";
|
|
19157
|
+
}
|
|
19111
19158
|
async cleanAndCreateDirectory(path) {
|
|
19112
19159
|
await fs24.rm(path, { recursive: true, force: true }).catch(() => {
|
|
19113
19160
|
});
|
|
@@ -19128,7 +19175,7 @@ class SkillsManager {
|
|
|
19128
19175
|
try {
|
|
19129
19176
|
let skills2 = context.skills;
|
|
19130
19177
|
if (skills2.length === 0) {
|
|
19131
|
-
return { installed: [], skipped: [], warnings: context.warnings };
|
|
19178
|
+
return { installed: [], updated: [], unchanged: [], skipped: [], warnings: context.warnings };
|
|
19132
19179
|
}
|
|
19133
19180
|
if (options2.skills && options2.skills.length > 0) {
|
|
19134
19181
|
const names = new Set(options2.skills.map((skill) => skill.toLowerCase()));
|
|
@@ -19139,18 +19186,33 @@ class SkillsManager {
|
|
|
19139
19186
|
if (agents.length === 0 && !installToSharedStore) {
|
|
19140
19187
|
return {
|
|
19141
19188
|
installed: [],
|
|
19189
|
+
updated: [],
|
|
19190
|
+
unchanged: [],
|
|
19142
19191
|
skipped: skills2.map((skill) => ({ skill, reason: "No target agents found" })),
|
|
19143
19192
|
warnings: context.warnings
|
|
19144
19193
|
};
|
|
19145
19194
|
}
|
|
19146
|
-
const result = { installed: [], skipped: [], warnings: context.warnings };
|
|
19195
|
+
const result = { installed: [], updated: [], unchanged: [], skipped: [], warnings: context.warnings };
|
|
19147
19196
|
const installableAgents = [];
|
|
19197
|
+
const comparisonCache = new Map;
|
|
19198
|
+
const pendingUpdates = [];
|
|
19148
19199
|
if (installToSharedStore) {
|
|
19149
19200
|
for (const skill of skills2) {
|
|
19150
19201
|
try {
|
|
19151
19202
|
const installOptions = {
|
|
19152
19203
|
...options2.global !== undefined ? { global: options2.global } : {}
|
|
19153
19204
|
};
|
|
19205
|
+
const plan = this.getCanonicalInstallPlan(skill.name, projectPath, installOptions);
|
|
19206
|
+
const comparison = await this.compareSkillSnapshot(skill, plan.path);
|
|
19207
|
+
comparisonCache.set(plan.path, comparison);
|
|
19208
|
+
if (comparison === "unchanged") {
|
|
19209
|
+
result.unchanged.push({ skill, agent: SHARED_SKILLS_TARGET_ID, path: plan.path });
|
|
19210
|
+
continue;
|
|
19211
|
+
}
|
|
19212
|
+
if (comparison === "changed") {
|
|
19213
|
+
pendingUpdates.push({ skill, agent: SHARED_SKILLS_TARGET_ID, installOptions });
|
|
19214
|
+
continue;
|
|
19215
|
+
}
|
|
19154
19216
|
const installed = skill.generatedContent ? await this.installSkillFromContentToCanonicalStore(skill.name, skill.generatedContent, projectPath, installOptions) : await this.installSkillToCanonicalStore(skill.path, skill.name, projectPath, installOptions);
|
|
19155
19217
|
result.installed.push({ skill, agent: SHARED_SKILLS_TARGET_ID, ...installed });
|
|
19156
19218
|
} catch (error) {
|
|
@@ -19181,6 +19243,21 @@ class SkillsManager {
|
|
|
19181
19243
|
...options2.global !== undefined ? { global: options2.global } : {},
|
|
19182
19244
|
...options2.copy !== undefined ? { copy: options2.copy } : {}
|
|
19183
19245
|
};
|
|
19246
|
+
const plan = await this.getInstallPlan(skill.name, agent, projectPath, installOptions);
|
|
19247
|
+
const comparisonPath = plan.canonicalPath || plan.path;
|
|
19248
|
+
let comparison = comparisonCache.get(comparisonPath);
|
|
19249
|
+
if (comparison === undefined) {
|
|
19250
|
+
comparison = await this.compareSkillSnapshot(skill, comparisonPath);
|
|
19251
|
+
comparisonCache.set(comparisonPath, comparison);
|
|
19252
|
+
}
|
|
19253
|
+
if (comparison === "unchanged") {
|
|
19254
|
+
result.unchanged.push({ skill, agent: agent.id, path: comparisonPath });
|
|
19255
|
+
continue;
|
|
19256
|
+
}
|
|
19257
|
+
if (comparison === "changed") {
|
|
19258
|
+
pendingUpdates.push({ skill, agent: agent.id, agentObj: agent, installOptions });
|
|
19259
|
+
continue;
|
|
19260
|
+
}
|
|
19184
19261
|
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
19262
|
result.installed.push({ skill, agent: agent.id, ...installed });
|
|
19186
19263
|
} catch (error) {
|
|
@@ -19188,6 +19265,35 @@ class SkillsManager {
|
|
|
19188
19265
|
}
|
|
19189
19266
|
}
|
|
19190
19267
|
}
|
|
19268
|
+
if (pendingUpdates.length > 0) {
|
|
19269
|
+
let approvedNames;
|
|
19270
|
+
if (options2.yes) {
|
|
19271
|
+
approvedNames = new Set(pendingUpdates.map((p) => p.skill.name));
|
|
19272
|
+
} else if (options2.confirmUpdate) {
|
|
19273
|
+
const uniqueSkills = [...new Map(pendingUpdates.map((p) => [p.skill.name, p.skill])).values()];
|
|
19274
|
+
const approved = await options2.confirmUpdate(uniqueSkills);
|
|
19275
|
+
approvedNames = new Set(approved.map((s) => s.name));
|
|
19276
|
+
} else {
|
|
19277
|
+
approvedNames = new Set;
|
|
19278
|
+
}
|
|
19279
|
+
for (const pending of pendingUpdates) {
|
|
19280
|
+
if (!approvedNames.has(pending.skill.name)) {
|
|
19281
|
+
result.skipped.push({ skill: pending.skill, reason: "Update available; re-run with -y to update" });
|
|
19282
|
+
continue;
|
|
19283
|
+
}
|
|
19284
|
+
try {
|
|
19285
|
+
if (pending.agent === SHARED_SKILLS_TARGET_ID) {
|
|
19286
|
+
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);
|
|
19287
|
+
result.updated.push({ skill: pending.skill, agent: pending.agent, ...installed });
|
|
19288
|
+
} else if (pending.agentObj) {
|
|
19289
|
+
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);
|
|
19290
|
+
result.updated.push({ skill: pending.skill, agent: pending.agent, ...installed });
|
|
19291
|
+
}
|
|
19292
|
+
} catch (error) {
|
|
19293
|
+
result.skipped.push({ skill: pending.skill, reason: error.message });
|
|
19294
|
+
}
|
|
19295
|
+
}
|
|
19296
|
+
}
|
|
19191
19297
|
return result;
|
|
19192
19298
|
} finally {
|
|
19193
19299
|
await context.cleanup();
|
|
@@ -41225,9 +41331,73 @@ var BUILT_IN_MARKETPLACE_IDS = new Set(MARKETPLACES.map((marketplace) => marketp
|
|
|
41225
41331
|
var BUILT_IN_VERIFIED_REPOS = new Set(getBuiltInVerifiedGithubRepos());
|
|
41226
41332
|
|
|
41227
41333
|
// dist/commands/skills.js
|
|
41228
|
-
var
|
|
41334
|
+
var import_prompts3 = __toESM(require_prompts3(), 1);
|
|
41229
41335
|
import {homedir as homedir6} from "os";
|
|
41230
41336
|
import {relative as relative7, resolve as resolve12} from "path";
|
|
41337
|
+
|
|
41338
|
+
// dist/utils/promptUtils.js
|
|
41339
|
+
var import_prompts2 = __toESM(require_prompts3(), 1);
|
|
41340
|
+
import {createRequire as createRequire2} from "module";
|
|
41341
|
+
function enableUppercaseToggleAllForMultiselectPrompt() {
|
|
41342
|
+
if (uppercaseToggleAllPatched) {
|
|
41343
|
+
return;
|
|
41344
|
+
}
|
|
41345
|
+
uppercaseToggleAllPatched = true;
|
|
41346
|
+
try {
|
|
41347
|
+
const MultiselectPrompt = require2("prompts/lib/elements/multiselect");
|
|
41348
|
+
const prototype = MultiselectPrompt?.prototype;
|
|
41349
|
+
if (!prototype || typeof prototype._ !== "function" || prototype.__agentinitUppercaseToggleAllPatched) {
|
|
41350
|
+
return;
|
|
41351
|
+
}
|
|
41352
|
+
const originalHandler = prototype._;
|
|
41353
|
+
prototype._ = function agentinitMultiselectHandler(input, key) {
|
|
41354
|
+
return originalHandler.call(this, input === "A" ? "a" : input, key);
|
|
41355
|
+
};
|
|
41356
|
+
Object.defineProperty(prototype, "__agentinitUppercaseToggleAllPatched", {
|
|
41357
|
+
value: true,
|
|
41358
|
+
configurable: false,
|
|
41359
|
+
enumerable: false,
|
|
41360
|
+
writable: false
|
|
41361
|
+
});
|
|
41362
|
+
} catch {
|
|
41363
|
+
}
|
|
41364
|
+
}
|
|
41365
|
+
async function promptMultiselect(options2) {
|
|
41366
|
+
enableUppercaseToggleAllForMultiselectPrompt();
|
|
41367
|
+
return import_prompts2.default({
|
|
41368
|
+
...options2,
|
|
41369
|
+
type: "multiselect",
|
|
41370
|
+
instructions: options2.instructions ?? false,
|
|
41371
|
+
hint: options2.hint ?? MULTISELECT_TOGGLE_ALL_HINT
|
|
41372
|
+
});
|
|
41373
|
+
}
|
|
41374
|
+
async function selectBundlePlugins(entries, actionLabel, options2 = {}) {
|
|
41375
|
+
if (options2.selectAll) {
|
|
41376
|
+
logger.info("Selecting all bundled plugins (--all).");
|
|
41377
|
+
return entries.map((entry) => entry.name);
|
|
41378
|
+
}
|
|
41379
|
+
logger.info(dim(MULTISELECT_TOGGLE_ALL_HINT));
|
|
41380
|
+
const response = await promptMultiselect({
|
|
41381
|
+
name: "plugins",
|
|
41382
|
+
message: `This repository contains multiple plugins. Select which to ${actionLabel}:`,
|
|
41383
|
+
min: 1,
|
|
41384
|
+
choices: entries.map((entry) => ({
|
|
41385
|
+
title: entry.name,
|
|
41386
|
+
value: entry.name,
|
|
41387
|
+
...entry.description ? { description: entry.description } : {}
|
|
41388
|
+
}))
|
|
41389
|
+
});
|
|
41390
|
+
if (!response.plugins || response.plugins.length === 0) {
|
|
41391
|
+
logger.info("Cancelled.");
|
|
41392
|
+
return null;
|
|
41393
|
+
}
|
|
41394
|
+
return response.plugins;
|
|
41395
|
+
}
|
|
41396
|
+
var require2 = createRequire2(import.meta.url);
|
|
41397
|
+
var MULTISELECT_TOGGLE_ALL_HINT = "Press Space to select, A to select or deselect all, then Enter to confirm.";
|
|
41398
|
+
var uppercaseToggleAllPatched = false;
|
|
41399
|
+
|
|
41400
|
+
// dist/commands/skills.js
|
|
41231
41401
|
init_skillsManager();
|
|
41232
41402
|
init_pluginManager();
|
|
41233
41403
|
init_marketplaceRegistry();
|
|
@@ -41236,7 +41406,7 @@ init_skills();
|
|
|
41236
41406
|
function registerSkillsCommand(program2) {
|
|
41237
41407
|
const marketplaceHelp = getMarketplaceIds().join(", ");
|
|
41238
41408
|
const skills3 = program2.command("skills").description("Manage agent skills");
|
|
41239
|
-
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("--copy", "Copy skill files instead of symlinking").option("-y, --yes", "Skip prompts
|
|
41409
|
+
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) => {
|
|
41240
41410
|
logger.titleBox("AgentInit Skills");
|
|
41241
41411
|
const agentManager9 = new AgentManager;
|
|
41242
41412
|
const skillsManager5 = new SkillsManager(agentManager9);
|
|
@@ -41251,7 +41421,7 @@ function registerSkillsCommand(program2) {
|
|
|
41251
41421
|
} catch (error) {
|
|
41252
41422
|
if (error instanceof MultipleBundlePluginsError) {
|
|
41253
41423
|
spinner.stop();
|
|
41254
|
-
const selected = await selectBundlePlugins(error, "list");
|
|
41424
|
+
const selected = await selectBundlePlugins(error.entries, "list", { selectAll: options2.all });
|
|
41255
41425
|
if (!selected) {
|
|
41256
41426
|
return;
|
|
41257
41427
|
}
|
|
@@ -41284,9 +41454,9 @@ function registerSkillsCommand(program2) {
|
|
|
41284
41454
|
});
|
|
41285
41455
|
verifySpinner.stop();
|
|
41286
41456
|
} catch (error) {
|
|
41287
|
-
if (error instanceof MultipleBundlePluginsError && !options2.yes) {
|
|
41457
|
+
if (error instanceof MultipleBundlePluginsError && (options2.all || !options2.yes)) {
|
|
41288
41458
|
verifySpinner.stop();
|
|
41289
|
-
const selected = await selectBundlePlugins(error, "install");
|
|
41459
|
+
const selected = await selectBundlePlugins(error.entries, "install", { selectAll: options2.all });
|
|
41290
41460
|
if (!selected) {
|
|
41291
41461
|
return;
|
|
41292
41462
|
}
|
|
@@ -41327,6 +41497,16 @@ function registerSkillsCommand(program2) {
|
|
|
41327
41497
|
targetGlobal = selection.global;
|
|
41328
41498
|
}
|
|
41329
41499
|
}
|
|
41500
|
+
const confirmUpdate = options2.yes ? undefined : async (skills4) => {
|
|
41501
|
+
const names = skills4.map((s) => s.name).join(", ");
|
|
41502
|
+
const response = await import_prompts3.default({
|
|
41503
|
+
type: "confirm",
|
|
41504
|
+
name: "update",
|
|
41505
|
+
message: skills4.length === 1 ? `Skill "${skills4[0].name}" has been updated. Update it?` : `${skills4.length} skill(s) have updates (${names}). Update them?`,
|
|
41506
|
+
initial: true
|
|
41507
|
+
});
|
|
41508
|
+
return response.update ? skills4 : [];
|
|
41509
|
+
};
|
|
41330
41510
|
const buildInstallOptions = (pluginName) => ({
|
|
41331
41511
|
...options2.from !== undefined ? { from: options2.from } : {},
|
|
41332
41512
|
...targetGlobal !== undefined ? { global: targetGlobal } : {},
|
|
@@ -41334,7 +41514,8 @@ function registerSkillsCommand(program2) {
|
|
|
41334
41514
|
...options2.skill !== undefined ? { skills: options2.skill } : {},
|
|
41335
41515
|
...options2.copy !== undefined ? { copy: options2.copy } : {},
|
|
41336
41516
|
...pluginName !== undefined ? { pluginName } : {},
|
|
41337
|
-
...options2.yes !== undefined ? { yes: options2.yes } : {}
|
|
41517
|
+
...options2.yes !== undefined ? { yes: options2.yes } : {},
|
|
41518
|
+
...confirmUpdate !== undefined ? { confirmUpdate } : {}
|
|
41338
41519
|
});
|
|
41339
41520
|
const pluginsToInstall = selectedPluginNames || [undefined];
|
|
41340
41521
|
for (const pluginName of pluginsToInstall) {
|
|
@@ -41430,30 +41611,10 @@ function registerSkillsCommand(program2) {
|
|
|
41430
41611
|
}
|
|
41431
41612
|
});
|
|
41432
41613
|
}
|
|
41433
|
-
async function selectBundlePlugins(error, actionLabel) {
|
|
41434
|
-
logger.info(dim("Press Space to select, then Enter to confirm."));
|
|
41435
|
-
const response = await import_prompts2.default({
|
|
41436
|
-
type: "multiselect",
|
|
41437
|
-
name: "plugins",
|
|
41438
|
-
message: `This repository contains multiple plugins. Select which to ${actionLabel}:`,
|
|
41439
|
-
instructions: false,
|
|
41440
|
-
min: 1,
|
|
41441
|
-
choices: error.entries.map((entry) => ({
|
|
41442
|
-
title: entry.name,
|
|
41443
|
-
value: entry.name,
|
|
41444
|
-
...entry.description ? { description: entry.description } : {}
|
|
41445
|
-
}))
|
|
41446
|
-
});
|
|
41447
|
-
if (!response.plugins || response.plugins.length === 0) {
|
|
41448
|
-
logger.info("Cancelled.");
|
|
41449
|
-
return null;
|
|
41450
|
-
}
|
|
41451
|
-
return response.plugins;
|
|
41452
|
-
}
|
|
41453
41614
|
async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, source, projectPath, options2) {
|
|
41454
41615
|
let installGlobal = !!options2.global;
|
|
41455
41616
|
if (!options2.global) {
|
|
41456
|
-
const response2 = await
|
|
41617
|
+
const response2 = await import_prompts3.default({
|
|
41457
41618
|
type: "select",
|
|
41458
41619
|
name: "scope",
|
|
41459
41620
|
message: "Where should the skill be installed?",
|
|
@@ -41491,11 +41652,9 @@ async function resolveInteractiveSkillTargets(skillsManager5, agentManager9, sou
|
|
|
41491
41652
|
logger.warn("No project agent files with skills support were detected in this project.");
|
|
41492
41653
|
logger.info("Select project agent directories manually. Run `agentinit init` if you want future installs to auto-detect.");
|
|
41493
41654
|
}
|
|
41494
|
-
const response = await
|
|
41495
|
-
type: "multiselect",
|
|
41655
|
+
const response = await promptMultiselect({
|
|
41496
41656
|
name: "groups",
|
|
41497
41657
|
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:",
|
|
41498
|
-
instructions: false,
|
|
41499
41658
|
min: 1,
|
|
41500
41659
|
choices: availableGroups.map((group) => ({
|
|
41501
41660
|
title: formatSkillGroupTitle(group),
|
|
@@ -41737,14 +41896,18 @@ var displayDiscoveredSkills = function(skills3, warnings) {
|
|
|
41737
41896
|
}
|
|
41738
41897
|
};
|
|
41739
41898
|
var displayInstallResult = function(result, spinner, agentManager9, skillsManager5, source, options2) {
|
|
41740
|
-
|
|
41899
|
+
const hasInstalled = result.installed.length > 0;
|
|
41900
|
+
const hasUpdated = result.updated.length > 0;
|
|
41901
|
+
const hasUnchanged = result.unchanged.length > 0;
|
|
41902
|
+
const hasSkipped = result.skipped.length > 0;
|
|
41903
|
+
if (!hasInstalled && !hasUpdated && !hasUnchanged && !hasSkipped) {
|
|
41741
41904
|
spinner.warn("No skills found in the source.");
|
|
41742
41905
|
for (const warning of result.warnings) {
|
|
41743
41906
|
logger.warn(warning);
|
|
41744
41907
|
}
|
|
41745
41908
|
return;
|
|
41746
41909
|
}
|
|
41747
|
-
if (
|
|
41910
|
+
if (!hasInstalled && !hasUpdated && !hasUnchanged && hasSkipped && result.skipped.every((skip) => skip.reason === "No target agents found")) {
|
|
41748
41911
|
spinner.warn("No target agents found.");
|
|
41749
41912
|
logNoTargetAgentsGuidance(skillsManager5, agentManager9, source, {
|
|
41750
41913
|
...options2.from !== undefined ? { from: options2.from } : {}
|
|
@@ -41757,29 +41920,63 @@ var displayInstallResult = function(result, spinner, agentManager9, skillsManage
|
|
|
41757
41920
|
}
|
|
41758
41921
|
return;
|
|
41759
41922
|
}
|
|
41760
|
-
|
|
41761
|
-
|
|
41762
|
-
|
|
41763
|
-
|
|
41764
|
-
|
|
41765
|
-
const
|
|
41766
|
-
|
|
41767
|
-
|
|
41768
|
-
|
|
41769
|
-
|
|
41770
|
-
|
|
41771
|
-
|
|
41772
|
-
|
|
41773
|
-
|
|
41774
|
-
|
|
41775
|
-
|
|
41776
|
-
|
|
41923
|
+
if (!hasInstalled && !hasUpdated && hasUnchanged) {
|
|
41924
|
+
const uniqueUnchanged = new Set(result.unchanged.map((item) => item.skill.name));
|
|
41925
|
+
spinner.info(`${uniqueUnchanged.size} skill(s) already up to date`);
|
|
41926
|
+
logger.info(dim(` Already installed: ${[...uniqueUnchanged].join(", ")}`));
|
|
41927
|
+
} else {
|
|
41928
|
+
const parts = [];
|
|
41929
|
+
if (hasInstalled) {
|
|
41930
|
+
const uniqueInstallCount = new Set(result.installed.map((item) => `${item.path}:${item.skill.name}`)).size;
|
|
41931
|
+
parts.push(`Installed ${green(String(uniqueInstallCount))}`);
|
|
41932
|
+
}
|
|
41933
|
+
if (hasUpdated) {
|
|
41934
|
+
const uniqueUpdateCount = new Set(result.updated.map((item) => `${item.path}:${item.skill.name}`)).size;
|
|
41935
|
+
parts.push(`Updated ${yellow(String(uniqueUpdateCount))}`);
|
|
41936
|
+
}
|
|
41937
|
+
if (hasUnchanged) {
|
|
41938
|
+
const uniqueUnchanged = new Set(result.unchanged.map((item) => item.skill.name)).size;
|
|
41939
|
+
parts.push(`${uniqueUnchanged} already up to date`);
|
|
41940
|
+
}
|
|
41941
|
+
spinner.succeed(`${parts.join(", ")} skill(s)`);
|
|
41942
|
+
const byPath = new Map;
|
|
41943
|
+
for (const item of result.installed) {
|
|
41944
|
+
const path = item.path;
|
|
41945
|
+
const existing = byPath.get(path) || {
|
|
41946
|
+
agents: new Set,
|
|
41947
|
+
skills: new Set
|
|
41948
|
+
};
|
|
41949
|
+
existing.agents.add(formatSkillTargetName(agentManager9, item.agent));
|
|
41950
|
+
existing.skills.add(item.skill.name);
|
|
41951
|
+
byPath.set(path, existing);
|
|
41952
|
+
}
|
|
41953
|
+
for (const [path, details] of byPath) {
|
|
41954
|
+
logger.info(` ${relative7(process.cwd(), path) || path}`);
|
|
41955
|
+
logger.info(` Agents: ${[...details.agents].join(", ")}`);
|
|
41956
|
+
logger.info(` Skills: ${green(String(details.skills.size))} installed (${[...details.skills].join(", ")})`);
|
|
41957
|
+
}
|
|
41958
|
+
const byPathUpdated = new Map;
|
|
41959
|
+
for (const item of result.updated) {
|
|
41960
|
+
const path = item.path;
|
|
41961
|
+
const existing = byPathUpdated.get(path) || {
|
|
41962
|
+
agents: new Set,
|
|
41963
|
+
skills: new Set
|
|
41964
|
+
};
|
|
41965
|
+
existing.agents.add(formatSkillTargetName(agentManager9, item.agent));
|
|
41966
|
+
existing.skills.add(item.skill.name);
|
|
41967
|
+
byPathUpdated.set(path, existing);
|
|
41968
|
+
}
|
|
41969
|
+
for (const [path, details] of byPathUpdated) {
|
|
41970
|
+
logger.info(` ${relative7(process.cwd(), path) || path}`);
|
|
41971
|
+
logger.info(` Agents: ${[...details.agents].join(", ")}`);
|
|
41972
|
+
logger.info(` Skills: ${yellow(String(details.skills.size))} updated (${[...details.skills].join(", ")})`);
|
|
41973
|
+
}
|
|
41777
41974
|
}
|
|
41778
|
-
const copiedFallbacks = result.installed.filter((item) => item.symlinkFailed);
|
|
41975
|
+
const copiedFallbacks = [...result.installed, ...result.updated].filter((item) => item.symlinkFailed);
|
|
41779
41976
|
if (copiedFallbacks.length > 0) {
|
|
41780
41977
|
logger.warn(`Symlink creation failed for ${copiedFallbacks.length} install(s); copied the skill files instead.`);
|
|
41781
41978
|
}
|
|
41782
|
-
if (
|
|
41979
|
+
if (hasSkipped) {
|
|
41783
41980
|
logger.info("");
|
|
41784
41981
|
logger.warn(`Skipped ${result.skipped.length} skill(s):`);
|
|
41785
41982
|
for (const skip of result.skipped) {
|
|
@@ -41792,7 +41989,9 @@ var displayInstallResult = function(result, spinner, agentManager9, skillsManage
|
|
|
41792
41989
|
logger.warn(warning);
|
|
41793
41990
|
}
|
|
41794
41991
|
}
|
|
41795
|
-
|
|
41992
|
+
if (hasInstalled || hasUpdated) {
|
|
41993
|
+
logger.success("Skills installation complete.");
|
|
41994
|
+
}
|
|
41796
41995
|
};
|
|
41797
41996
|
|
|
41798
41997
|
// dist/commands/mcp.js
|
|
@@ -42585,7 +42784,7 @@ function registerRulesCommand(program2) {
|
|
|
42585
42784
|
}
|
|
42586
42785
|
|
|
42587
42786
|
// dist/commands/plugins.js
|
|
42588
|
-
var
|
|
42787
|
+
var import_prompts4 = __toESM(require_prompts3(), 1);
|
|
42589
42788
|
import {homedir as homedir7} from "os";
|
|
42590
42789
|
import {dirname as dirname9, relative as relative8, resolve as resolve13} from "path";
|
|
42591
42790
|
init_pluginManager();
|
|
@@ -42595,7 +42794,7 @@ function registerPluginsCommand(program2) {
|
|
|
42595
42794
|
const marketplaceHelp = new PluginManager().getMarketplaceIds().join(", ");
|
|
42596
42795
|
const marketplaceCategoryHelp = getMarketplaceCategories().join(", ");
|
|
42597
42796
|
const plugins = program2.command("plugins").description("Install agent-agnostic plugins from any marketplace or source");
|
|
42598
|
-
plugins.command("install <source>").description("Install a plugin from <marketplace>/<name>, a GitHub repo, or a local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-a, --agent <agents...>", "Target specific agent(s)").option("-g, --global", "Install globally").option("--copy-skills", "Copy plugin skills instead of using canonical symlink installs").option("-l, --list", "Preview plugin contents without installing").option("-y, --yes", "Skip confirmation prompts, auto-detect project-configured agents").action(async (source, options2) => {
|
|
42797
|
+
plugins.command("install <source>").description("Install a plugin from <marketplace>/<name>, a GitHub repo, or a local path").option("--from <marketplace>", `Marketplace source override (available: ${marketplaceHelp})`).option("-a, --agent <agents...>", "Target specific agent(s)").option("-g, --global", "Install globally").option("--copy-skills", "Copy plugin skills instead of using canonical symlink installs").option("--all", "Select all bundled plugins when the source contains multiple plugins").option("-l, --list", "Preview plugin contents without installing").option("-y, --yes", "Skip confirmation prompts, auto-detect project-configured agents").action(async (source, options2) => {
|
|
42599
42798
|
logger.titleBox("AgentInit Plugins");
|
|
42600
42799
|
const agentManager12 = new AgentManager;
|
|
42601
42800
|
const pluginManager3 = new PluginManager(agentManager12);
|
|
@@ -42631,7 +42830,7 @@ function registerPluginsCommand(program2) {
|
|
|
42631
42830
|
} catch (error) {
|
|
42632
42831
|
if (error instanceof MultipleBundlePluginsError) {
|
|
42633
42832
|
spinner.stop();
|
|
42634
|
-
const selected = await
|
|
42833
|
+
const selected = await selectBundlePlugins(error.entries, "preview", { selectAll: options2.all });
|
|
42635
42834
|
if (!selected) {
|
|
42636
42835
|
return;
|
|
42637
42836
|
}
|
|
@@ -42695,7 +42894,7 @@ function registerPluginsCommand(program2) {
|
|
|
42695
42894
|
} catch (error) {
|
|
42696
42895
|
if (error instanceof MultipleBundlePluginsError) {
|
|
42697
42896
|
previewSpinner.stop();
|
|
42698
|
-
const selected = await
|
|
42897
|
+
const selected = await selectBundlePlugins(error.entries, "install", { selectAll: options2.all });
|
|
42699
42898
|
if (!selected) {
|
|
42700
42899
|
return;
|
|
42701
42900
|
}
|
|
@@ -42791,9 +42990,9 @@ function registerPluginsCommand(program2) {
|
|
|
42791
42990
|
}
|
|
42792
42991
|
logger.success("Plugin installation complete.");
|
|
42793
42992
|
} catch (error) {
|
|
42794
|
-
if (error instanceof MultipleBundlePluginsError && !options2.yes) {
|
|
42993
|
+
if (error instanceof MultipleBundlePluginsError && (options2.all || !options2.yes)) {
|
|
42795
42994
|
spinner.stop();
|
|
42796
|
-
const selected = await
|
|
42995
|
+
const selected = await selectBundlePlugins(error.entries, "install", { selectAll: options2.all });
|
|
42797
42996
|
if (!selected) {
|
|
42798
42997
|
return;
|
|
42799
42998
|
}
|
|
@@ -42937,26 +43136,6 @@ function registerPluginsCommand(program2) {
|
|
|
42937
43136
|
}
|
|
42938
43137
|
});
|
|
42939
43138
|
}
|
|
42940
|
-
async function selectBundlePlugins2(error, actionLabel) {
|
|
42941
|
-
logger.info(dim("Press Space to select, then Enter to confirm."));
|
|
42942
|
-
const response = await import_prompts3.default({
|
|
42943
|
-
type: "multiselect",
|
|
42944
|
-
name: "plugins",
|
|
42945
|
-
message: `This repository contains multiple plugins. Select which to ${actionLabel}:`,
|
|
42946
|
-
instructions: false,
|
|
42947
|
-
min: 1,
|
|
42948
|
-
choices: error.entries.map((entry) => ({
|
|
42949
|
-
title: entry.name,
|
|
42950
|
-
value: entry.name,
|
|
42951
|
-
...entry.description ? { description: entry.description } : {}
|
|
42952
|
-
}))
|
|
42953
|
-
});
|
|
42954
|
-
if (!response.plugins || response.plugins.length === 0) {
|
|
42955
|
-
logger.info("Cancelled.");
|
|
42956
|
-
return null;
|
|
42957
|
-
}
|
|
42958
|
-
return response.plugins;
|
|
42959
|
-
}
|
|
42960
43139
|
var formatPathForDisplay = function(pathValue, projectPath) {
|
|
42961
43140
|
if (pathValue.startsWith(`${projectPath}/`)) {
|
|
42962
43141
|
return relative8(projectPath, pathValue) || ".";
|
|
@@ -43290,7 +43469,7 @@ async function interactiveAgentSelect(pluginManager3, agentManager12, projectPat
|
|
|
43290
43469
|
}));
|
|
43291
43470
|
if (groups.length === 0 && !installGlobal) {
|
|
43292
43471
|
logger.warn("No agents with skills support detected in this project.");
|
|
43293
|
-
const scopeResponse = await
|
|
43472
|
+
const scopeResponse = await import_prompts4.default({
|
|
43294
43473
|
type: "select",
|
|
43295
43474
|
name: "scope",
|
|
43296
43475
|
message: "Install this plugin globally instead?",
|
|
@@ -43316,11 +43495,9 @@ async function interactiveAgentSelect(pluginManager3, agentManager12, projectPat
|
|
|
43316
43495
|
logger.warn("No supported agents expose a skills directory.");
|
|
43317
43496
|
return { aborted: true };
|
|
43318
43497
|
}
|
|
43319
|
-
const response = await
|
|
43320
|
-
type: "multiselect",
|
|
43498
|
+
const response = await promptMultiselect({
|
|
43321
43499
|
name: "groups",
|
|
43322
43500
|
message: installGlobal ? "Select which global agents should receive this plugin:" : "Select which agents should receive this plugin:",
|
|
43323
|
-
instructions: false,
|
|
43324
43501
|
min: 1,
|
|
43325
43502
|
choices: groups.map((group) => {
|
|
43326
43503
|
const compatible = group.compatibleAgentNames.length > 0 ? dim(` (also compatible: ${group.compatibleAgentNames.join(", ")})`) : "";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../src/commands/plugins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"plugins.d.ts","sourceRoot":"","sources":["../../src/commands/plugins.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAsCpC,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CA2b7D"}
|