agentinit 1.14.0 → 1.15.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 +14 -0
- package/README.md +44 -7
- package/dist/cli.js +620 -200
- package/dist/cli.js.map +1 -1
- package/dist/commands/config.d.ts +2 -7
- package/dist/commands/config.d.ts.map +1 -1
- package/dist/commands/config.js +212 -3
- package/dist/commands/config.js.map +1 -1
- package/dist/commands/plugins.d.ts.map +1 -1
- package/dist/commands/plugins.js +5 -3
- package/dist/commands/plugins.js.map +1 -1
- package/dist/core/marketplaceRegistry.d.ts +3 -0
- package/dist/core/marketplaceRegistry.d.ts.map +1 -1
- package/dist/core/marketplaceRegistry.js +45 -2
- package/dist/core/marketplaceRegistry.js.map +1 -1
- package/dist/core/pluginManager.d.ts +2 -0
- package/dist/core/pluginManager.d.ts.map +1 -1
- package/dist/core/pluginManager.js +66 -32
- package/dist/core/pluginManager.js.map +1 -1
- package/dist/core/skillsManager.d.ts.map +1 -1
- package/dist/core/skillsManager.js +12 -1
- package/dist/core/skillsManager.js.map +1 -1
- package/dist/core/userConfig.d.ts +25 -0
- package/dist/core/userConfig.d.ts.map +1 -0
- package/dist/core/userConfig.js +156 -0
- package/dist/core/userConfig.js.map +1 -0
- package/package.json +1 -1
package/dist/cli.js
CHANGED
|
@@ -16717,15 +16717,207 @@ var init_agentManager = __esm(() => {
|
|
|
16717
16717
|
init_ZedAgent();
|
|
16718
16718
|
});
|
|
16719
16719
|
|
|
16720
|
+
// dist/core/userConfig.js
|
|
16721
|
+
import {existsSync, readFileSync} from "fs";
|
|
16722
|
+
import {promises as fs20} from "fs";
|
|
16723
|
+
import {homedir as homedir3} from "os";
|
|
16724
|
+
import {join as join3} from "path";
|
|
16725
|
+
function getUserConfigPath() {
|
|
16726
|
+
return join3(homedir3(), ".agentinit", "config.json");
|
|
16727
|
+
}
|
|
16728
|
+
function createDefaultUserConfig() {
|
|
16729
|
+
return {
|
|
16730
|
+
customMarketplaces: [],
|
|
16731
|
+
verifiedGithubRepos: []
|
|
16732
|
+
};
|
|
16733
|
+
}
|
|
16734
|
+
function normalizeMarketplaceIdentifier(identifier) {
|
|
16735
|
+
const normalized = identifier.trim().toLowerCase();
|
|
16736
|
+
if (!MARKETPLACE_IDENTIFIER_PATTERN.test(normalized)) {
|
|
16737
|
+
throw new Error('Invalid marketplace identifier. Use lowercase letters, numbers, ".", "_" or "-".');
|
|
16738
|
+
}
|
|
16739
|
+
return normalized;
|
|
16740
|
+
}
|
|
16741
|
+
function normalizeMarketplaceName(name, identifier) {
|
|
16742
|
+
const normalized = name?.trim();
|
|
16743
|
+
return normalized ? normalized : identifier;
|
|
16744
|
+
}
|
|
16745
|
+
function normalizeMarketplaceRepoUrl(repoUrl) {
|
|
16746
|
+
const normalized = repoUrl.trim().replace(/\/+$/, "");
|
|
16747
|
+
if (!normalized || !GIT_REPO_URL_PATTERN.test(normalized)) {
|
|
16748
|
+
throw new Error("Invalid marketplace repo URL. Use https://..., ssh://..., or git@...");
|
|
16749
|
+
}
|
|
16750
|
+
return normalized;
|
|
16751
|
+
}
|
|
16752
|
+
function normalizeGitHubRepoRef(repo) {
|
|
16753
|
+
const normalized = repo.trim();
|
|
16754
|
+
const match = normalized.match(GITHUB_REPO_PATTERN);
|
|
16755
|
+
if (!match) {
|
|
16756
|
+
throw new Error("Invalid GitHub repo. Use exact owner/repo.");
|
|
16757
|
+
}
|
|
16758
|
+
return `${match[1].toLowerCase()}/${match[2].toLowerCase()}`;
|
|
16759
|
+
}
|
|
16760
|
+
function sanitizeUserConfig(raw) {
|
|
16761
|
+
const defaults = createDefaultUserConfig();
|
|
16762
|
+
if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
|
|
16763
|
+
return defaults;
|
|
16764
|
+
}
|
|
16765
|
+
const parsed = raw;
|
|
16766
|
+
const seenMarketplaces = new Set;
|
|
16767
|
+
const customMarketplaces = [];
|
|
16768
|
+
if (Array.isArray(parsed.customMarketplaces)) {
|
|
16769
|
+
for (const entry of parsed.customMarketplaces) {
|
|
16770
|
+
const sanitized = sanitizeCustomMarketplaceConfig(entry);
|
|
16771
|
+
if (!sanitized || seenMarketplaces.has(sanitized.identifier)) {
|
|
16772
|
+
continue;
|
|
16773
|
+
}
|
|
16774
|
+
seenMarketplaces.add(sanitized.identifier);
|
|
16775
|
+
customMarketplaces.push(sanitized);
|
|
16776
|
+
}
|
|
16777
|
+
}
|
|
16778
|
+
const seenRepos = new Set;
|
|
16779
|
+
const verifiedGithubRepos = [];
|
|
16780
|
+
if (Array.isArray(parsed.verifiedGithubRepos)) {
|
|
16781
|
+
for (const entry of parsed.verifiedGithubRepos) {
|
|
16782
|
+
if (typeof entry !== "string") {
|
|
16783
|
+
continue;
|
|
16784
|
+
}
|
|
16785
|
+
try {
|
|
16786
|
+
const normalized = normalizeGitHubRepoRef(entry);
|
|
16787
|
+
if (seenRepos.has(normalized)) {
|
|
16788
|
+
continue;
|
|
16789
|
+
}
|
|
16790
|
+
seenRepos.add(normalized);
|
|
16791
|
+
verifiedGithubRepos.push(normalized);
|
|
16792
|
+
} catch {
|
|
16793
|
+
continue;
|
|
16794
|
+
}
|
|
16795
|
+
}
|
|
16796
|
+
}
|
|
16797
|
+
let defaultMarketplace;
|
|
16798
|
+
if (typeof parsed.defaultMarketplace === "string") {
|
|
16799
|
+
try {
|
|
16800
|
+
defaultMarketplace = normalizeMarketplaceIdentifier(parsed.defaultMarketplace);
|
|
16801
|
+
} catch {
|
|
16802
|
+
defaultMarketplace = undefined;
|
|
16803
|
+
}
|
|
16804
|
+
}
|
|
16805
|
+
return {
|
|
16806
|
+
...defaultMarketplace ? { defaultMarketplace } : {},
|
|
16807
|
+
customMarketplaces,
|
|
16808
|
+
verifiedGithubRepos
|
|
16809
|
+
};
|
|
16810
|
+
}
|
|
16811
|
+
function readUserConfigSync() {
|
|
16812
|
+
const configPath = getUserConfigPath();
|
|
16813
|
+
if (!existsSync(configPath)) {
|
|
16814
|
+
return createDefaultUserConfig();
|
|
16815
|
+
}
|
|
16816
|
+
try {
|
|
16817
|
+
const content = readFileSync(configPath, "utf8");
|
|
16818
|
+
return sanitizeUserConfig(JSON.parse(content));
|
|
16819
|
+
} catch {
|
|
16820
|
+
return createDefaultUserConfig();
|
|
16821
|
+
}
|
|
16822
|
+
}
|
|
16823
|
+
async function readUserConfig() {
|
|
16824
|
+
const configPath = getUserConfigPath();
|
|
16825
|
+
try {
|
|
16826
|
+
const content = await fs20.readFile(configPath, "utf8");
|
|
16827
|
+
return sanitizeUserConfig(JSON.parse(content));
|
|
16828
|
+
} catch {
|
|
16829
|
+
return createDefaultUserConfig();
|
|
16830
|
+
}
|
|
16831
|
+
}
|
|
16832
|
+
async function writeUserConfig(config) {
|
|
16833
|
+
const sanitized = sanitizeUserConfig(config);
|
|
16834
|
+
await writeFile(getUserConfigPath(), `${JSON.stringify(sanitized, null, 2)}\n`);
|
|
16835
|
+
}
|
|
16836
|
+
function getBuiltInVerifiedGithubRepos() {
|
|
16837
|
+
return [...BUILTIN_VERIFIED_GITHUB_REPOS];
|
|
16838
|
+
}
|
|
16839
|
+
function getEffectiveVerifiedGithubReposSync() {
|
|
16840
|
+
const repos = new Set(BUILTIN_VERIFIED_GITHUB_REPOS);
|
|
16841
|
+
for (const repo of readUserConfigSync().verifiedGithubRepos) {
|
|
16842
|
+
repos.add(repo);
|
|
16843
|
+
}
|
|
16844
|
+
return [...repos];
|
|
16845
|
+
}
|
|
16846
|
+
function isVerifiedGitHubRepoSync(owner, repo) {
|
|
16847
|
+
const normalized = normalizeGitHubRepoRef(`${owner}/${repo}`);
|
|
16848
|
+
return getEffectiveVerifiedGithubReposSync().includes(normalized);
|
|
16849
|
+
}
|
|
16850
|
+
var sanitizeCustomMarketplaceConfig, MARKETPLACE_IDENTIFIER_PATTERN, GITHUB_REPO_PATTERN, GIT_REPO_URL_PATTERN, BUILTIN_VERIFIED_GITHUB_REPOS;
|
|
16851
|
+
var init_userConfig = __esm(() => {
|
|
16852
|
+
init_fs();
|
|
16853
|
+
sanitizeCustomMarketplaceConfig = function(entry) {
|
|
16854
|
+
if (!entry || typeof entry !== "object" || Array.isArray(entry)) {
|
|
16855
|
+
return null;
|
|
16856
|
+
}
|
|
16857
|
+
const candidate = entry;
|
|
16858
|
+
try {
|
|
16859
|
+
const identifier = normalizeMarketplaceIdentifier(String(candidate.identifier || ""));
|
|
16860
|
+
return {
|
|
16861
|
+
identifier,
|
|
16862
|
+
name: normalizeMarketplaceName(typeof candidate.name === "string" ? candidate.name : undefined, identifier),
|
|
16863
|
+
repoUrl: normalizeMarketplaceRepoUrl(String(candidate.repoUrl || ""))
|
|
16864
|
+
};
|
|
16865
|
+
} catch {
|
|
16866
|
+
return null;
|
|
16867
|
+
}
|
|
16868
|
+
};
|
|
16869
|
+
MARKETPLACE_IDENTIFIER_PATTERN = /^[a-z0-9][a-z0-9._-]*$/;
|
|
16870
|
+
GITHUB_REPO_PATTERN = /^([A-Za-z0-9._-]+)\/([A-Za-z0-9._-]+)$/;
|
|
16871
|
+
GIT_REPO_URL_PATTERN = /^(https?:\/\/|ssh:\/\/|git@).+/;
|
|
16872
|
+
BUILTIN_VERIFIED_GITHUB_REPOS = ["openai/codex-plugin-cc"];
|
|
16873
|
+
});
|
|
16874
|
+
|
|
16720
16875
|
// dist/core/marketplaceRegistry.js
|
|
16876
|
+
function getMarketplaceCategoryForDir(dir) {
|
|
16877
|
+
if (dir === "plugins") {
|
|
16878
|
+
return "official";
|
|
16879
|
+
}
|
|
16880
|
+
if (dir === "external_plugins") {
|
|
16881
|
+
return "community";
|
|
16882
|
+
}
|
|
16883
|
+
if (dir.startsWith("skills/.")) {
|
|
16884
|
+
return dir.slice("skills/.".length);
|
|
16885
|
+
}
|
|
16886
|
+
return dir;
|
|
16887
|
+
}
|
|
16721
16888
|
function getMarketplace(id) {
|
|
16722
|
-
return
|
|
16889
|
+
return getAllMarketplaces().find((marketplace) => marketplace.id === id);
|
|
16723
16890
|
}
|
|
16724
16891
|
function getMarketplaceIds() {
|
|
16725
|
-
return
|
|
16892
|
+
return getAllMarketplaces().map((marketplace) => marketplace.id);
|
|
16893
|
+
}
|
|
16894
|
+
function getMarketplaceCategories(id) {
|
|
16895
|
+
const marketplaces = id ? [getMarketplace(id)].filter((marketplace) => !!marketplace) : getAllMarketplaces();
|
|
16896
|
+
return [...new Set(marketplaces.flatMap((marketplace) => marketplace.pluginDirs.map(getMarketplaceCategoryForDir)))];
|
|
16897
|
+
}
|
|
16898
|
+
function getConfiguredDefaultMarketplaceId() {
|
|
16899
|
+
const defaultMarketplace = readUserConfigSync().defaultMarketplace;
|
|
16900
|
+
if (!defaultMarketplace) {
|
|
16901
|
+
return;
|
|
16902
|
+
}
|
|
16903
|
+
return getMarketplace(defaultMarketplace)?.id;
|
|
16726
16904
|
}
|
|
16727
|
-
var MARKETPLACES;
|
|
16905
|
+
var getCustomMarketplaces, getAllMarketplaces, MARKETPLACES, CUSTOM_MARKETPLACE_PLUGIN_DIRS, CUSTOM_MARKETPLACE_CACHE_TTL_MS;
|
|
16728
16906
|
var init_marketplaceRegistry = __esm(() => {
|
|
16907
|
+
init_userConfig();
|
|
16908
|
+
getCustomMarketplaces = function() {
|
|
16909
|
+
const builtInIds = new Set(MARKETPLACES.map((marketplace) => marketplace.id));
|
|
16910
|
+
return readUserConfigSync().customMarketplaces.filter((marketplace) => !builtInIds.has(marketplace.identifier)).map((marketplace) => ({
|
|
16911
|
+
id: marketplace.identifier,
|
|
16912
|
+
name: marketplace.name,
|
|
16913
|
+
repoUrl: marketplace.repoUrl,
|
|
16914
|
+
pluginDirs: [...CUSTOM_MARKETPLACE_PLUGIN_DIRS],
|
|
16915
|
+
cacheTtlMs: CUSTOM_MARKETPLACE_CACHE_TTL_MS
|
|
16916
|
+
}));
|
|
16917
|
+
};
|
|
16918
|
+
getAllMarketplaces = function() {
|
|
16919
|
+
return [...MARKETPLACES, ...getCustomMarketplaces()];
|
|
16920
|
+
};
|
|
16729
16921
|
MARKETPLACES = [
|
|
16730
16922
|
{
|
|
16731
16923
|
id: "agentinit",
|
|
@@ -16749,6 +16941,8 @@ var init_marketplaceRegistry = __esm(() => {
|
|
|
16749
16941
|
cacheTtlMs: 3600000
|
|
16750
16942
|
}
|
|
16751
16943
|
];
|
|
16944
|
+
CUSTOM_MARKETPLACE_PLUGIN_DIRS = ["skills", "mcps", "rules"];
|
|
16945
|
+
CUSTOM_MARKETPLACE_CACHE_TTL_MS = 3600000;
|
|
16752
16946
|
});
|
|
16753
16947
|
|
|
16754
16948
|
// dist/core/mcpFilter.js
|
|
@@ -16860,9 +17054,9 @@ __export(exports_pluginManager, {
|
|
|
16860
17054
|
}
|
|
16861
17055
|
}
|
|
16862
17056
|
});
|
|
16863
|
-
import {resolve as resolve7, join as
|
|
16864
|
-
import {promises as
|
|
16865
|
-
import {homedir as
|
|
17057
|
+
import {resolve as resolve7, join as join4, basename as basename2, relative as relative2, dirname as dirname2} from "path";
|
|
17058
|
+
import {promises as fs22} from "fs";
|
|
17059
|
+
import {homedir as homedir4} from "os";
|
|
16866
17060
|
|
|
16867
17061
|
class MarketplacePluginNotFoundError extends Error {
|
|
16868
17062
|
pluginName;
|
|
@@ -16896,7 +17090,7 @@ class PluginManager {
|
|
|
16896
17090
|
}
|
|
16897
17091
|
async cleanupLoadedPluginContext(context) {
|
|
16898
17092
|
if (context?.tempDir) {
|
|
16899
|
-
await
|
|
17093
|
+
await fs22.rm(context.tempDir, { recursive: true, force: true }).catch(() => {
|
|
16900
17094
|
});
|
|
16901
17095
|
}
|
|
16902
17096
|
}
|
|
@@ -16968,13 +17162,13 @@ class PluginManager {
|
|
|
16968
17162
|
return `https://github.com/${source.owner}/${source.repo}`;
|
|
16969
17163
|
}
|
|
16970
17164
|
getGitHubFallbackTrust(source) {
|
|
16971
|
-
if (source.owner
|
|
17165
|
+
if (source.owner && source.repo && isVerifiedGitHubRepoSync(source.owner, source.repo)) {
|
|
16972
17166
|
return "verified";
|
|
16973
17167
|
}
|
|
16974
17168
|
return "unverified";
|
|
16975
17169
|
}
|
|
16976
17170
|
async resolvePreparedPluginDir(pluginDir, source) {
|
|
16977
|
-
const claudeMarketplaceManifestPath =
|
|
17171
|
+
const claudeMarketplaceManifestPath = join4(pluginDir, ".claude-plugin", "marketplace.json");
|
|
16978
17172
|
if (!await fileExists(claudeMarketplaceManifestPath)) {
|
|
16979
17173
|
return { pluginDir, warnings: [] };
|
|
16980
17174
|
}
|
|
@@ -17115,13 +17309,13 @@ class PluginManager {
|
|
|
17115
17309
|
}
|
|
17116
17310
|
async getClaudeNativeFeatureKinds(pluginDir, manifest) {
|
|
17117
17311
|
const featureChecks = await Promise.all([
|
|
17118
|
-
(async () => !!manifest.commands || await isDirectory(
|
|
17119
|
-
(async () => !!manifest.hooks || await isDirectory(
|
|
17120
|
-
(async () => !!manifest.agents || await isDirectory(
|
|
17121
|
-
isDirectory(
|
|
17122
|
-
isDirectory(
|
|
17123
|
-
isDirectory(
|
|
17124
|
-
isDirectory(
|
|
17312
|
+
(async () => !!manifest.commands || await isDirectory(join4(pluginDir, "commands")))(),
|
|
17313
|
+
(async () => !!manifest.hooks || await isDirectory(join4(pluginDir, "hooks")))(),
|
|
17314
|
+
(async () => !!manifest.agents || await isDirectory(join4(pluginDir, "agents")))(),
|
|
17315
|
+
isDirectory(join4(pluginDir, "prompts")),
|
|
17316
|
+
isDirectory(join4(pluginDir, "schemas")),
|
|
17317
|
+
isDirectory(join4(pluginDir, "scripts")),
|
|
17318
|
+
isDirectory(join4(pluginDir, "templates"))
|
|
17125
17319
|
]);
|
|
17126
17320
|
return [
|
|
17127
17321
|
...featureChecks[0] ? ["commands"] : [],
|
|
@@ -17137,7 +17331,7 @@ class PluginManager {
|
|
|
17137
17331
|
if (plugin.format !== "claude") {
|
|
17138
17332
|
return null;
|
|
17139
17333
|
}
|
|
17140
|
-
const manifestContent = await readFileIfExists(
|
|
17334
|
+
const manifestContent = await readFileIfExists(join4(pluginDir, ".claude-plugin", "plugin.json"));
|
|
17141
17335
|
if (!manifestContent) {
|
|
17142
17336
|
return null;
|
|
17143
17337
|
}
|
|
@@ -17157,7 +17351,7 @@ class PluginManager {
|
|
|
17157
17351
|
return {
|
|
17158
17352
|
namespace,
|
|
17159
17353
|
pluginKey: `${plugin.name}@${namespace}`,
|
|
17160
|
-
installPath:
|
|
17354
|
+
installPath: join4(homedir4(), ".claude", "plugins", "cache", namespace, plugin.name, versionDir),
|
|
17161
17355
|
features
|
|
17162
17356
|
};
|
|
17163
17357
|
}
|
|
@@ -17230,10 +17424,10 @@ class PluginManager {
|
|
|
17230
17424
|
warnings.push(`Skipped native Claude plugin install because Claude already has "${plugin.name}" installed as ${conflictingKey}.`);
|
|
17231
17425
|
return { installed, skipped, warnings };
|
|
17232
17426
|
}
|
|
17233
|
-
await
|
|
17427
|
+
await fs22.rm(nativeTarget.installPath, { recursive: true, force: true }).catch(() => {
|
|
17234
17428
|
});
|
|
17235
|
-
await
|
|
17236
|
-
await
|
|
17429
|
+
await fs22.mkdir(dirname2(nativeTarget.installPath), { recursive: true });
|
|
17430
|
+
await fs22.cp(pluginDir, nativeTarget.installPath, { recursive: true, dereference: true });
|
|
17237
17431
|
const now = new Date().toISOString();
|
|
17238
17432
|
claudeInstalled.plugins[nativeTarget.pluginKey] = [{
|
|
17239
17433
|
scope: "user",
|
|
@@ -17281,7 +17475,7 @@ class PluginManager {
|
|
|
17281
17475
|
claudeSettings.enabledPlugins = remainingEnabledPlugins;
|
|
17282
17476
|
await this.saveClaudeSettings(claudeSettings);
|
|
17283
17477
|
}
|
|
17284
|
-
await
|
|
17478
|
+
await fs22.rm(component.installPath, { recursive: true, force: true }).catch(() => {
|
|
17285
17479
|
});
|
|
17286
17480
|
return true;
|
|
17287
17481
|
}
|
|
@@ -17332,7 +17526,7 @@ class PluginManager {
|
|
|
17332
17526
|
repo
|
|
17333
17527
|
};
|
|
17334
17528
|
}
|
|
17335
|
-
const defaultMarketplace = this.getMarketplaceIds()[0];
|
|
17529
|
+
const defaultMarketplace = getConfiguredDefaultMarketplaceId() || this.getMarketplaceIds()[0];
|
|
17336
17530
|
if (defaultMarketplace) {
|
|
17337
17531
|
return {
|
|
17338
17532
|
type: "marketplace",
|
|
@@ -17351,43 +17545,81 @@ class PluginManager {
|
|
|
17351
17545
|
async ensureMarketplaceCache(registryId) {
|
|
17352
17546
|
const registry = this.getMarketplace(registryId);
|
|
17353
17547
|
if (!registry) {
|
|
17354
|
-
throw new Error(`Unknown marketplace: ${registryId}. Available: ${
|
|
17548
|
+
throw new Error(`Unknown marketplace: ${registryId}. Available: ${this.getMarketplaceIds().join(", ")}`);
|
|
17355
17549
|
}
|
|
17356
17550
|
const cacheDir = getMarketplaceCacheDir(registryId);
|
|
17357
|
-
const cacheMetaPath =
|
|
17358
|
-
|
|
17359
|
-
|
|
17360
|
-
|
|
17361
|
-
|
|
17362
|
-
|
|
17363
|
-
|
|
17364
|
-
|
|
17365
|
-
|
|
17366
|
-
|
|
17367
|
-
|
|
17368
|
-
|
|
17369
|
-
const { execFile } = await import("child_process");
|
|
17370
|
-
const { promisify } = await import("util");
|
|
17371
|
-
const exec = promisify(execFile);
|
|
17372
|
-
try {
|
|
17373
|
-
await exec("git", ["pull", "--ff-only"], { cwd: cacheDir, timeout: 30000 });
|
|
17374
|
-
} catch {
|
|
17375
|
-
await fs20.rm(cacheDir, { recursive: true, force: true });
|
|
17551
|
+
const cacheMetaPath = join4(cacheDir, ".agentinit-cache-meta.json");
|
|
17552
|
+
const cacheMeta = await this.readMarketplaceCacheMeta(cacheMetaPath);
|
|
17553
|
+
if (cacheMeta?.repoUrl === registry.repoUrl) {
|
|
17554
|
+
const age = Date.now() - cacheMeta.fetchedAt;
|
|
17555
|
+
if (age < registry.cacheTtlMs) {
|
|
17556
|
+
return cacheDir;
|
|
17557
|
+
}
|
|
17558
|
+
}
|
|
17559
|
+
if (await fileExists(join4(cacheDir, ".git"))) {
|
|
17560
|
+
const originUrl = await this.getMarketplaceCacheOriginUrl(cacheDir);
|
|
17561
|
+
if (originUrl !== registry.repoUrl) {
|
|
17562
|
+
await fs22.rm(cacheDir, { recursive: true, force: true });
|
|
17376
17563
|
await this.cloneMarketplace(registry.repoUrl, cacheDir);
|
|
17564
|
+
} else {
|
|
17565
|
+
const { execFile } = await import("child_process");
|
|
17566
|
+
const { promisify } = await import("util");
|
|
17567
|
+
const exec = promisify(execFile);
|
|
17568
|
+
try {
|
|
17569
|
+
await exec("git", ["pull", "--ff-only"], { cwd: cacheDir, timeout: 30000 });
|
|
17570
|
+
} catch {
|
|
17571
|
+
await fs22.rm(cacheDir, { recursive: true, force: true });
|
|
17572
|
+
await this.cloneMarketplace(registry.repoUrl, cacheDir);
|
|
17573
|
+
}
|
|
17377
17574
|
}
|
|
17378
17575
|
} else {
|
|
17379
17576
|
await this.cloneMarketplace(registry.repoUrl, cacheDir);
|
|
17380
17577
|
}
|
|
17381
|
-
await
|
|
17382
|
-
await
|
|
17578
|
+
await fs22.mkdir(cacheDir, { recursive: true });
|
|
17579
|
+
await fs22.writeFile(cacheMetaPath, JSON.stringify({
|
|
17580
|
+
fetchedAt: Date.now(),
|
|
17581
|
+
repoUrl: registry.repoUrl
|
|
17582
|
+
}));
|
|
17383
17583
|
return cacheDir;
|
|
17384
17584
|
}
|
|
17585
|
+
async readMarketplaceCacheMeta(cacheMetaPath) {
|
|
17586
|
+
if (!await fileExists(cacheMetaPath)) {
|
|
17587
|
+
return null;
|
|
17588
|
+
}
|
|
17589
|
+
try {
|
|
17590
|
+
const meta = JSON.parse(await fs22.readFile(cacheMetaPath, "utf8"));
|
|
17591
|
+
if (typeof meta.fetchedAt !== "number") {
|
|
17592
|
+
return null;
|
|
17593
|
+
}
|
|
17594
|
+
return {
|
|
17595
|
+
fetchedAt: meta.fetchedAt,
|
|
17596
|
+
...typeof meta.repoUrl === "string" ? { repoUrl: meta.repoUrl } : {}
|
|
17597
|
+
};
|
|
17598
|
+
} catch {
|
|
17599
|
+
return null;
|
|
17600
|
+
}
|
|
17601
|
+
}
|
|
17602
|
+
async getMarketplaceCacheOriginUrl(cacheDir) {
|
|
17603
|
+
const { execFile } = await import("child_process");
|
|
17604
|
+
const { promisify } = await import("util");
|
|
17605
|
+
const exec = promisify(execFile);
|
|
17606
|
+
try {
|
|
17607
|
+
const { stdout } = await exec("git", ["config", "--get", "remote.origin.url"], {
|
|
17608
|
+
cwd: cacheDir,
|
|
17609
|
+
timeout: 30000
|
|
17610
|
+
});
|
|
17611
|
+
const originUrl = stdout.trim();
|
|
17612
|
+
return originUrl || null;
|
|
17613
|
+
} catch {
|
|
17614
|
+
return null;
|
|
17615
|
+
}
|
|
17616
|
+
}
|
|
17385
17617
|
async cloneMarketplace(repoUrl, dest) {
|
|
17386
|
-
await
|
|
17618
|
+
await fs22.mkdir(dest, { recursive: true });
|
|
17387
17619
|
const { execFile } = await import("child_process");
|
|
17388
17620
|
const { promisify } = await import("util");
|
|
17389
17621
|
const exec = promisify(execFile);
|
|
17390
|
-
await
|
|
17622
|
+
await fs22.rm(dest, { recursive: true, force: true }).catch(() => {
|
|
17391
17623
|
});
|
|
17392
17624
|
await exec("git", ["clone", "--depth", "1", repoUrl, dest], { timeout: 60000 });
|
|
17393
17625
|
}
|
|
@@ -17397,7 +17629,7 @@ class PluginManager {
|
|
|
17397
17629
|
throw new Error(`Unknown marketplace: ${registryId}`);
|
|
17398
17630
|
const cacheDir = await this.ensureMarketplaceCache(registryId);
|
|
17399
17631
|
for (const dir of registry.pluginDirs) {
|
|
17400
|
-
const pluginPath =
|
|
17632
|
+
const pluginPath = join4(cacheDir, dir, name);
|
|
17401
17633
|
if (await isDirectory(pluginPath)) {
|
|
17402
17634
|
return pluginPath;
|
|
17403
17635
|
}
|
|
@@ -17413,36 +17645,36 @@ class PluginManager {
|
|
|
17413
17645
|
const cacheDir = await this.ensureMarketplaceCache(registryId);
|
|
17414
17646
|
const results = [];
|
|
17415
17647
|
for (const dir of registry.pluginDirs) {
|
|
17416
|
-
const fullDir =
|
|
17648
|
+
const fullDir = join4(cacheDir, dir);
|
|
17417
17649
|
if (!await isDirectory(fullDir))
|
|
17418
17650
|
continue;
|
|
17419
|
-
const cat =
|
|
17651
|
+
const cat = getMarketplaceCategoryForDir(dir);
|
|
17420
17652
|
if (category && cat !== category)
|
|
17421
17653
|
continue;
|
|
17422
17654
|
const entries = await listFiles(fullDir);
|
|
17423
17655
|
for (const entry of entries) {
|
|
17424
17656
|
if (entry.startsWith("."))
|
|
17425
17657
|
continue;
|
|
17426
|
-
const entryPath =
|
|
17658
|
+
const entryPath = join4(fullDir, entry);
|
|
17427
17659
|
if (!await isDirectory(entryPath))
|
|
17428
17660
|
continue;
|
|
17429
|
-
const manifestPath =
|
|
17661
|
+
const manifestPath = join4(entryPath, ".claude-plugin", "plugin.json");
|
|
17430
17662
|
let name = entry;
|
|
17431
17663
|
let description = "";
|
|
17432
17664
|
let version = "0.0.0";
|
|
17433
17665
|
if (await fileExists(manifestPath)) {
|
|
17434
17666
|
try {
|
|
17435
|
-
const manifest = JSON.parse(await
|
|
17667
|
+
const manifest = JSON.parse(await fs22.readFile(manifestPath, "utf8"));
|
|
17436
17668
|
name = manifest.name || entry;
|
|
17437
17669
|
description = manifest.description || "";
|
|
17438
17670
|
version = manifest.version || "0.0.0";
|
|
17439
17671
|
} catch {
|
|
17440
17672
|
}
|
|
17441
17673
|
} else {
|
|
17442
|
-
const skillMdPath =
|
|
17674
|
+
const skillMdPath = join4(entryPath, "SKILL.md");
|
|
17443
17675
|
if (await fileExists(skillMdPath)) {
|
|
17444
17676
|
try {
|
|
17445
|
-
const parsed = import_gray_matter.default(await
|
|
17677
|
+
const parsed = import_gray_matter.default(await fs22.readFile(skillMdPath, "utf8"));
|
|
17446
17678
|
if (parsed.data.name)
|
|
17447
17679
|
name = parsed.data.name;
|
|
17448
17680
|
if (parsed.data.description)
|
|
@@ -17450,10 +17682,10 @@ class PluginManager {
|
|
|
17450
17682
|
} catch {
|
|
17451
17683
|
}
|
|
17452
17684
|
} else {
|
|
17453
|
-
const mcpPath =
|
|
17685
|
+
const mcpPath = join4(entryPath, ".mcp.json");
|
|
17454
17686
|
if (await fileExists(mcpPath)) {
|
|
17455
17687
|
try {
|
|
17456
|
-
const mcpConfig = JSON.parse(await
|
|
17688
|
+
const mcpConfig = JSON.parse(await fs22.readFile(mcpPath, "utf8"));
|
|
17457
17689
|
const serverNames = Object.keys(mcpConfig.mcpServers || mcpConfig);
|
|
17458
17690
|
if (serverNames.length > 0) {
|
|
17459
17691
|
description = `MCP server(s): ${serverNames.join(", ")}`;
|
|
@@ -17475,10 +17707,10 @@ class PluginManager {
|
|
|
17475
17707
|
return results.sort((a, b) => a.name.localeCompare(b.name));
|
|
17476
17708
|
}
|
|
17477
17709
|
async detectFormat(pluginDir) {
|
|
17478
|
-
if (await fileExists(
|
|
17710
|
+
if (await fileExists(join4(pluginDir, ".claude-plugin", "plugin.json"))) {
|
|
17479
17711
|
return "claude";
|
|
17480
17712
|
}
|
|
17481
|
-
if (await fileExists(
|
|
17713
|
+
if (await fileExists(join4(pluginDir, ".cursor-plugin", "plugin.json"))) {
|
|
17482
17714
|
return "cursor";
|
|
17483
17715
|
}
|
|
17484
17716
|
return "generic";
|
|
@@ -17495,7 +17727,7 @@ class PluginManager {
|
|
|
17495
17727
|
}
|
|
17496
17728
|
}
|
|
17497
17729
|
async parseClaudePlugin(pluginDir, source) {
|
|
17498
|
-
const manifestPath =
|
|
17730
|
+
const manifestPath = join4(pluginDir, ".claude-plugin", "plugin.json");
|
|
17499
17731
|
const manifestContent = await readFileIfExists(manifestPath);
|
|
17500
17732
|
if (!manifestContent) {
|
|
17501
17733
|
throw new Error(`Missing .claude-plugin/plugin.json in ${pluginDir}`);
|
|
@@ -17506,10 +17738,10 @@ class PluginManager {
|
|
|
17506
17738
|
const convertedSkills = await this.convertCommandsToSkills(pluginDir, manifest);
|
|
17507
17739
|
skills.push(...convertedSkills);
|
|
17508
17740
|
const mcpServers = await this.parseMcpJson(pluginDir);
|
|
17509
|
-
if (await isDirectory(
|
|
17741
|
+
if (await isDirectory(join4(pluginDir, "hooks")) || manifest.hooks) {
|
|
17510
17742
|
warnings.push("Hooks (hooks/) are Claude Code-specific");
|
|
17511
17743
|
}
|
|
17512
|
-
if (await isDirectory(
|
|
17744
|
+
if (await isDirectory(join4(pluginDir, "agents")) || manifest.agents) {
|
|
17513
17745
|
warnings.push("Agent definitions (agents/) are Claude Code-specific");
|
|
17514
17746
|
}
|
|
17515
17747
|
return {
|
|
@@ -17524,7 +17756,7 @@ class PluginManager {
|
|
|
17524
17756
|
};
|
|
17525
17757
|
}
|
|
17526
17758
|
async parseCursorPlugin(pluginDir, source) {
|
|
17527
|
-
const manifestPath =
|
|
17759
|
+
const manifestPath = join4(pluginDir, ".cursor-plugin", "plugin.json");
|
|
17528
17760
|
const manifestContent = await readFileIfExists(manifestPath);
|
|
17529
17761
|
if (!manifestContent) {
|
|
17530
17762
|
throw new Error(`Missing .cursor-plugin/plugin.json in ${pluginDir}`);
|
|
@@ -17563,7 +17795,7 @@ class PluginManager {
|
|
|
17563
17795
|
};
|
|
17564
17796
|
}
|
|
17565
17797
|
async parseMcpJson(pluginDir) {
|
|
17566
|
-
const mcpPath =
|
|
17798
|
+
const mcpPath = join4(pluginDir, ".mcp.json");
|
|
17567
17799
|
const content = await readFileIfExists(mcpPath);
|
|
17568
17800
|
if (!content)
|
|
17569
17801
|
return [];
|
|
@@ -17610,7 +17842,7 @@ class PluginManager {
|
|
|
17610
17842
|
commandsDirs.push(resolve7(pluginDir, cmd));
|
|
17611
17843
|
}
|
|
17612
17844
|
} else {
|
|
17613
|
-
commandsDirs.push(
|
|
17845
|
+
commandsDirs.push(join4(pluginDir, "commands"));
|
|
17614
17846
|
}
|
|
17615
17847
|
for (const commandsDir of commandsDirs) {
|
|
17616
17848
|
if (!await isDirectory(commandsDir))
|
|
@@ -17619,7 +17851,7 @@ class PluginManager {
|
|
|
17619
17851
|
for (const entry of entries) {
|
|
17620
17852
|
if (!entry.endsWith(".md"))
|
|
17621
17853
|
continue;
|
|
17622
|
-
const cmdPath =
|
|
17854
|
+
const cmdPath = join4(commandsDir, entry);
|
|
17623
17855
|
const skill = await this.convertSingleCommandToSkill(cmdPath, manifest.name);
|
|
17624
17856
|
if (skill)
|
|
17625
17857
|
skills.push(skill);
|
|
@@ -17908,7 +18140,7 @@ ${body.trim()}
|
|
|
17908
18140
|
}
|
|
17909
18141
|
if (!removedSkillPaths.has(skill.path)) {
|
|
17910
18142
|
try {
|
|
17911
|
-
await
|
|
18143
|
+
await fs22.rm(skill.path, { recursive: true, force: true });
|
|
17912
18144
|
removedSkillPaths.add(skill.path);
|
|
17913
18145
|
} catch {
|
|
17914
18146
|
details.push(`Could not remove skill path: ${skill.path}`);
|
|
@@ -17917,7 +18149,7 @@ ${body.trim()}
|
|
|
17917
18149
|
}
|
|
17918
18150
|
if (skill.canonicalPath && skill.canonicalPath !== skill.path && !removedCanonicalPaths.has(skill.canonicalPath) && !sharedCanonicalPath) {
|
|
17919
18151
|
try {
|
|
17920
|
-
await
|
|
18152
|
+
await fs22.rm(skill.canonicalPath, { recursive: true, force: true });
|
|
17921
18153
|
removedCanonicalPaths.add(skill.canonicalPath);
|
|
17922
18154
|
} catch {
|
|
17923
18155
|
details.push(`Could not remove canonical skill path: ${skill.canonicalPath}`);
|
|
@@ -18021,27 +18253,28 @@ var init_pluginManager = __esm(() => {
|
|
|
18021
18253
|
init_mcpFilter();
|
|
18022
18254
|
init_marketplaceRegistry();
|
|
18023
18255
|
init_skillsManager();
|
|
18256
|
+
init_userConfig();
|
|
18024
18257
|
getMarketplaceCacheDir = function(registryId) {
|
|
18025
|
-
return
|
|
18258
|
+
return join4(homedir4(), ".agentinit", "marketplace-cache", registryId);
|
|
18026
18259
|
};
|
|
18027
18260
|
getRegistryPath = function(projectPath, global3) {
|
|
18028
18261
|
if (global3) {
|
|
18029
|
-
return
|
|
18262
|
+
return join4(homedir4(), ".agentinit", "plugins.json");
|
|
18030
18263
|
}
|
|
18031
|
-
return
|
|
18264
|
+
return join4(projectPath, ".agentinit", "plugins.json");
|
|
18032
18265
|
};
|
|
18033
18266
|
getClaudeInstalledPluginsPath = function() {
|
|
18034
|
-
return
|
|
18267
|
+
return join4(homedir4(), ".claude", "plugins", "installed_plugins.json");
|
|
18035
18268
|
};
|
|
18036
18269
|
getClaudeSettingsPath = function() {
|
|
18037
|
-
return
|
|
18270
|
+
return join4(homedir4(), ".claude", "settings.json");
|
|
18038
18271
|
};
|
|
18039
18272
|
});
|
|
18040
18273
|
|
|
18041
18274
|
// dist/core/skillsManager.js
|
|
18042
|
-
import {resolve as resolve8, join as
|
|
18043
|
-
import {promises as
|
|
18044
|
-
import {homedir as
|
|
18275
|
+
import {resolve as resolve8, join as join5, relative as relative3} from "path";
|
|
18276
|
+
import {promises as fs24} from "fs";
|
|
18277
|
+
import {homedir as homedir5, tmpdir} from "os";
|
|
18045
18278
|
import {execFile} from "child_process";
|
|
18046
18279
|
import {promisify} from "util";
|
|
18047
18280
|
|
|
@@ -18108,6 +18341,17 @@ class SkillsManager {
|
|
|
18108
18341
|
}
|
|
18109
18342
|
resolveSourceRequest(source, options2) {
|
|
18110
18343
|
if (this.isImplicitCatalogSkillSource(source, options2)) {
|
|
18344
|
+
const configuredDefaultMarketplace = getConfiguredDefaultMarketplaceId();
|
|
18345
|
+
if (configuredDefaultMarketplace) {
|
|
18346
|
+
return {
|
|
18347
|
+
source: {
|
|
18348
|
+
type: "marketplace",
|
|
18349
|
+
marketplace: configuredDefaultMarketplace,
|
|
18350
|
+
pluginName: source.trim()
|
|
18351
|
+
},
|
|
18352
|
+
implicitSkills: []
|
|
18353
|
+
};
|
|
18354
|
+
}
|
|
18111
18355
|
return {
|
|
18112
18356
|
source: {
|
|
18113
18357
|
type: "github",
|
|
@@ -18144,7 +18388,7 @@ class SkillsManager {
|
|
|
18144
18388
|
const fullDir = resolve8(repoPath, searchDir);
|
|
18145
18389
|
if (!await fileExists(fullDir))
|
|
18146
18390
|
continue;
|
|
18147
|
-
const directSkillMd =
|
|
18391
|
+
const directSkillMd = join5(fullDir, "SKILL.md");
|
|
18148
18392
|
if (await fileExists(directSkillMd)) {
|
|
18149
18393
|
const parsed = await this.parseSkillMd(directSkillMd);
|
|
18150
18394
|
if (parsed && !seen.has(parsed.name)) {
|
|
@@ -18152,7 +18396,7 @@ class SkillsManager {
|
|
|
18152
18396
|
skills.push({ ...parsed, path: resolve8(fullDir) });
|
|
18153
18397
|
}
|
|
18154
18398
|
}
|
|
18155
|
-
const directSkillMdLower =
|
|
18399
|
+
const directSkillMdLower = join5(fullDir, "skill.md");
|
|
18156
18400
|
if (await fileExists(directSkillMdLower)) {
|
|
18157
18401
|
const parsed = await this.parseSkillMd(directSkillMdLower);
|
|
18158
18402
|
if (parsed && !seen.has(parsed.name)) {
|
|
@@ -18164,11 +18408,11 @@ class SkillsManager {
|
|
|
18164
18408
|
continue;
|
|
18165
18409
|
const entries = await listFiles(fullDir);
|
|
18166
18410
|
for (const entry of entries) {
|
|
18167
|
-
const entryPath =
|
|
18411
|
+
const entryPath = join5(fullDir, entry);
|
|
18168
18412
|
if (!await isDirectory(entryPath))
|
|
18169
18413
|
continue;
|
|
18170
|
-
const skillMdPath =
|
|
18171
|
-
const skillMdPathLower =
|
|
18414
|
+
const skillMdPath = join5(entryPath, "SKILL.md");
|
|
18415
|
+
const skillMdPathLower = join5(entryPath, "skill.md");
|
|
18172
18416
|
const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
|
|
18173
18417
|
if (!skillFile)
|
|
18174
18418
|
continue;
|
|
@@ -18182,14 +18426,14 @@ class SkillsManager {
|
|
|
18182
18426
|
return skills;
|
|
18183
18427
|
}
|
|
18184
18428
|
async cloneRepo(url) {
|
|
18185
|
-
const tempDir = await
|
|
18186
|
-
await
|
|
18429
|
+
const tempDir = await fs24.mkdtemp(join5(tmpdir(), "agentinit-skills-"));
|
|
18430
|
+
await fs24.rm(tempDir, { recursive: true, force: true });
|
|
18187
18431
|
try {
|
|
18188
18432
|
await execFileAsync("git", ["clone", "--depth", "1", url, tempDir], {
|
|
18189
18433
|
timeout: 60000
|
|
18190
18434
|
});
|
|
18191
18435
|
} catch (error) {
|
|
18192
|
-
await
|
|
18436
|
+
await fs24.rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
18193
18437
|
});
|
|
18194
18438
|
throw new Error(`Failed to clone ${url}: ${error.message}`);
|
|
18195
18439
|
}
|
|
@@ -18283,7 +18527,7 @@ class SkillsManager {
|
|
|
18283
18527
|
return { skills, warnings };
|
|
18284
18528
|
} finally {
|
|
18285
18529
|
if (tempDir) {
|
|
18286
|
-
await
|
|
18530
|
+
await fs24.rm(tempDir, { recursive: true, force: true }).catch(() => {
|
|
18287
18531
|
});
|
|
18288
18532
|
}
|
|
18289
18533
|
}
|
|
@@ -18304,30 +18548,30 @@ class SkillsManager {
|
|
|
18304
18548
|
async installSkill(skillPath, skillName, targetDir, copy = false) {
|
|
18305
18549
|
const normalizedSkillName = this.normalizeSkillName(skillName);
|
|
18306
18550
|
const destPath = this.resolveInstallPath(targetDir, normalizedSkillName);
|
|
18307
|
-
await
|
|
18551
|
+
await fs24.mkdir(resolve8(targetDir), { recursive: true });
|
|
18308
18552
|
if (await fileExists(destPath)) {
|
|
18309
|
-
await
|
|
18553
|
+
await fs24.rm(destPath, { recursive: true, force: true });
|
|
18310
18554
|
}
|
|
18311
18555
|
if (copy) {
|
|
18312
18556
|
await this.copyDir(skillPath, destPath);
|
|
18313
18557
|
} else {
|
|
18314
|
-
await
|
|
18558
|
+
await fs24.symlink(skillPath, destPath, "dir");
|
|
18315
18559
|
}
|
|
18316
18560
|
return destPath;
|
|
18317
18561
|
}
|
|
18318
18562
|
async installSkillFromContent(skillName, skillContent, targetDir) {
|
|
18319
18563
|
const normalizedSkillName = this.normalizeSkillName(skillName);
|
|
18320
18564
|
const destPath = this.resolveInstallPath(targetDir, normalizedSkillName);
|
|
18321
|
-
await
|
|
18565
|
+
await fs24.mkdir(resolve8(targetDir), { recursive: true });
|
|
18322
18566
|
if (await fileExists(destPath)) {
|
|
18323
|
-
await
|
|
18567
|
+
await fs24.rm(destPath, { recursive: true, force: true });
|
|
18324
18568
|
}
|
|
18325
|
-
await
|
|
18326
|
-
await
|
|
18569
|
+
await fs24.mkdir(destPath, { recursive: true });
|
|
18570
|
+
await fs24.writeFile(join5(destPath, "SKILL.md"), skillContent, "utf8");
|
|
18327
18571
|
return destPath;
|
|
18328
18572
|
}
|
|
18329
18573
|
getCanonicalSkillsDir(projectPath, global3 = false) {
|
|
18330
|
-
return global3 ? resolve8(
|
|
18574
|
+
return global3 ? resolve8(homedir5(), ".agents/skills") : resolve8(projectPath, ".agents/skills");
|
|
18331
18575
|
}
|
|
18332
18576
|
async getInstallPlan(skillName, agent, projectPath, options2 = {}) {
|
|
18333
18577
|
const normalizedSkillName = this.normalizeSkillName(skillName);
|
|
@@ -18401,7 +18645,7 @@ class SkillsManager {
|
|
|
18401
18645
|
throw new Error(`Missing canonical path for ${skillName}`);
|
|
18402
18646
|
}
|
|
18403
18647
|
await this.cleanAndCreateDirectory(canonicalPath);
|
|
18404
|
-
await
|
|
18648
|
+
await fs24.writeFile(join5(canonicalPath, "SKILL.md"), skillContent, "utf8");
|
|
18405
18649
|
if (plan.path === canonicalPath) {
|
|
18406
18650
|
return plan;
|
|
18407
18651
|
}
|
|
@@ -18438,16 +18682,16 @@ class SkillsManager {
|
|
|
18438
18682
|
return this.resolveInstallPath(targetDir, this.normalizeSkillName(skillName));
|
|
18439
18683
|
}
|
|
18440
18684
|
async cleanAndCreateDirectory(path) {
|
|
18441
|
-
await
|
|
18685
|
+
await fs24.rm(path, { recursive: true, force: true }).catch(() => {
|
|
18442
18686
|
});
|
|
18443
|
-
await
|
|
18687
|
+
await fs24.mkdir(path, { recursive: true });
|
|
18444
18688
|
}
|
|
18445
18689
|
isWithinPath(basePath, targetPath) {
|
|
18446
18690
|
const relativePath = relative3(resolve8(basePath), resolve8(targetPath));
|
|
18447
18691
|
return relativePath === "" || !relativePath.startsWith("..") && !relativePath.includes("/../") && !relativePath.includes("\\..\\");
|
|
18448
18692
|
}
|
|
18449
18693
|
async copyDir(src, dest) {
|
|
18450
|
-
await
|
|
18694
|
+
await fs24.cp(src, dest, { recursive: true, dereference: true });
|
|
18451
18695
|
}
|
|
18452
18696
|
async addFromSource(source, projectPath, options2 = {}) {
|
|
18453
18697
|
const discovered = await this.discoverFromSource(source, projectPath, {
|
|
@@ -18522,11 +18766,11 @@ class SkillsManager {
|
|
|
18522
18766
|
continue;
|
|
18523
18767
|
const entries = await listFiles(dir);
|
|
18524
18768
|
for (const entry of entries) {
|
|
18525
|
-
const entryPath =
|
|
18769
|
+
const entryPath = join5(dir, entry);
|
|
18526
18770
|
if (!await isDirectory(entryPath))
|
|
18527
18771
|
continue;
|
|
18528
|
-
const skillMdPath =
|
|
18529
|
-
const skillMdPathLower =
|
|
18772
|
+
const skillMdPath = join5(entryPath, "SKILL.md");
|
|
18773
|
+
const skillMdPathLower = join5(entryPath, "skill.md");
|
|
18530
18774
|
const skillFile = await fileExists(skillMdPath) ? skillMdPath : await fileExists(skillMdPathLower) ? skillMdPathLower : null;
|
|
18531
18775
|
if (!skillFile)
|
|
18532
18776
|
continue;
|
|
@@ -18536,7 +18780,7 @@ class SkillsManager {
|
|
|
18536
18780
|
let isSymlink = false;
|
|
18537
18781
|
let canonicalPath;
|
|
18538
18782
|
try {
|
|
18539
|
-
const stat = await
|
|
18783
|
+
const stat = await fs24.lstat(entryPath);
|
|
18540
18784
|
isSymlink = stat.isSymbolicLink();
|
|
18541
18785
|
const canonicalBase = this.getCanonicalSkillsDir(projectPath, scope === "global");
|
|
18542
18786
|
const [resolvedEntryPath, resolvedCanonicalBase] = await Promise.all([
|
|
@@ -18602,7 +18846,7 @@ class SkillsManager {
|
|
|
18602
18846
|
}
|
|
18603
18847
|
if (!removedPaths.has(entry.path)) {
|
|
18604
18848
|
try {
|
|
18605
|
-
await
|
|
18849
|
+
await fs24.rm(entry.path, { recursive: true, force: true });
|
|
18606
18850
|
removedPaths.add(entry.path);
|
|
18607
18851
|
} catch {
|
|
18608
18852
|
skipped.push({
|
|
@@ -18615,7 +18859,7 @@ class SkillsManager {
|
|
|
18615
18859
|
if (entry.canonicalPath && entry.canonicalPath !== entry.path && !removedCanonicalPaths.has(entry.canonicalPath)) {
|
|
18616
18860
|
const stillReferenced = remainingEntries.some((other) => other.name.toLowerCase() === entry.name.toLowerCase() && other.canonicalPath === entry.canonicalPath);
|
|
18617
18861
|
if (!stillReferenced) {
|
|
18618
|
-
await
|
|
18862
|
+
await fs24.rm(entry.canonicalPath, { recursive: true, force: true }).catch(() => {
|
|
18619
18863
|
});
|
|
18620
18864
|
removedCanonicalPaths.add(entry.canonicalPath);
|
|
18621
18865
|
}
|
|
@@ -24851,27 +25095,27 @@ var require_windows = __commonJS((exports, module) => {
|
|
|
24851
25095
|
return checkPathExt(path, options2);
|
|
24852
25096
|
};
|
|
24853
25097
|
var isexe = function(path, options2, cb) {
|
|
24854
|
-
|
|
25098
|
+
fs31.stat(path, function(er, stat) {
|
|
24855
25099
|
cb(er, er ? false : checkStat(stat, path, options2));
|
|
24856
25100
|
});
|
|
24857
25101
|
};
|
|
24858
25102
|
var sync = function(path, options2) {
|
|
24859
|
-
return checkStat(
|
|
25103
|
+
return checkStat(fs31.statSync(path), path, options2);
|
|
24860
25104
|
};
|
|
24861
25105
|
module.exports = isexe;
|
|
24862
25106
|
isexe.sync = sync;
|
|
24863
|
-
var
|
|
25107
|
+
var fs31 = __require("fs");
|
|
24864
25108
|
});
|
|
24865
25109
|
|
|
24866
25110
|
// node_modules/isexe/mode.js
|
|
24867
25111
|
var require_mode = __commonJS((exports, module) => {
|
|
24868
25112
|
var isexe = function(path, options2, cb) {
|
|
24869
|
-
|
|
25113
|
+
fs31.stat(path, function(er, stat) {
|
|
24870
25114
|
cb(er, er ? false : checkStat(stat, options2));
|
|
24871
25115
|
});
|
|
24872
25116
|
};
|
|
24873
25117
|
var sync = function(path, options2) {
|
|
24874
|
-
return checkStat(
|
|
25118
|
+
return checkStat(fs31.statSync(path), options2);
|
|
24875
25119
|
};
|
|
24876
25120
|
var checkStat = function(stat, options2) {
|
|
24877
25121
|
return stat.isFile() && checkMode(stat, options2);
|
|
@@ -24891,7 +25135,7 @@ var require_mode = __commonJS((exports, module) => {
|
|
|
24891
25135
|
};
|
|
24892
25136
|
module.exports = isexe;
|
|
24893
25137
|
isexe.sync = sync;
|
|
24894
|
-
var
|
|
25138
|
+
var fs31 = __require("fs");
|
|
24895
25139
|
});
|
|
24896
25140
|
|
|
24897
25141
|
// node_modules/isexe/index.js
|
|
@@ -24936,7 +25180,7 @@ var require_isexe = __commonJS((exports, module) => {
|
|
|
24936
25180
|
}
|
|
24937
25181
|
}
|
|
24938
25182
|
};
|
|
24939
|
-
var
|
|
25183
|
+
var fs31 = __require("fs");
|
|
24940
25184
|
var core2;
|
|
24941
25185
|
if (process.platform === "win32" || global.TESTING_WINDOWS) {
|
|
24942
25186
|
core2 = require_windows();
|
|
@@ -25143,14 +25387,14 @@ var require_readShebang = __commonJS((exports, module) => {
|
|
|
25143
25387
|
const buffer = Buffer.alloc(size);
|
|
25144
25388
|
let fd;
|
|
25145
25389
|
try {
|
|
25146
|
-
fd =
|
|
25147
|
-
|
|
25148
|
-
|
|
25390
|
+
fd = fs31.openSync(command, "r");
|
|
25391
|
+
fs31.readSync(fd, buffer, 0, size, 0);
|
|
25392
|
+
fs31.closeSync(fd);
|
|
25149
25393
|
} catch (e) {
|
|
25150
25394
|
}
|
|
25151
25395
|
return shebangCommand(buffer.toString());
|
|
25152
25396
|
};
|
|
25153
|
-
var
|
|
25397
|
+
var fs31 = __require("fs");
|
|
25154
25398
|
var shebangCommand = require_shebang_command();
|
|
25155
25399
|
module.exports = readShebang;
|
|
25156
25400
|
});
|
|
@@ -27484,7 +27728,7 @@ import {relative as relative5} from "path";
|
|
|
27484
27728
|
|
|
27485
27729
|
// dist/core/propagator.js
|
|
27486
27730
|
var import_gray_matter3 = __toESM(require_gray_matter(), 1);
|
|
27487
|
-
import {promises as
|
|
27731
|
+
import {promises as fs26} from "fs";
|
|
27488
27732
|
import {resolve as resolve9} from "path";
|
|
27489
27733
|
|
|
27490
27734
|
// node_modules/js-yaml/dist/js-yaml.mjs
|
|
@@ -30252,7 +30496,7 @@ class Propagator {
|
|
|
30252
30496
|
resolvedTargets: []
|
|
30253
30497
|
};
|
|
30254
30498
|
const exists = await fileExists(generatedFile.path);
|
|
30255
|
-
const existingStats = exists ? await
|
|
30499
|
+
const existingStats = exists ? await fs26.lstat(generatedFile.path).catch(() => null) : null;
|
|
30256
30500
|
const existingContent = exists && !existingStats?.isSymbolicLink() ? await readFileIfExists(generatedFile.path) : null;
|
|
30257
30501
|
const existingTarget = existingStats?.isSymbolicLink() ? await readSymlinkTarget(generatedFile.path) : null;
|
|
30258
30502
|
if (options2.managedState && !options2.dryRun) {
|
|
@@ -30283,7 +30527,7 @@ class Propagator {
|
|
|
30283
30527
|
if (!options2.dryRun) {
|
|
30284
30528
|
if (generatedFile.kind === "file") {
|
|
30285
30529
|
if (existingStats?.isSymbolicLink()) {
|
|
30286
|
-
await
|
|
30530
|
+
await fs26.rm(generatedFile.path, { force: true }).catch(() => {
|
|
30287
30531
|
});
|
|
30288
30532
|
}
|
|
30289
30533
|
await writeFile(generatedFile.path, generatedFile.content || "");
|
|
@@ -30460,14 +30704,14 @@ ${content}
|
|
|
30460
30704
|
|
|
30461
30705
|
// dist/core/managedState.js
|
|
30462
30706
|
init_fs();
|
|
30463
|
-
import {promises as
|
|
30464
|
-
import {dirname as dirname3, join as
|
|
30707
|
+
import {promises as fs28} from "fs";
|
|
30708
|
+
import {dirname as dirname3, join as join6, relative as relative4, resolve as resolve10} from "path";
|
|
30465
30709
|
var toPosixPath = function(value) {
|
|
30466
30710
|
return value.replace(/\\/g, "/");
|
|
30467
30711
|
};
|
|
30468
30712
|
async function pathType(targetPath) {
|
|
30469
30713
|
try {
|
|
30470
|
-
const stat = await
|
|
30714
|
+
const stat = await fs28.lstat(targetPath);
|
|
30471
30715
|
if (stat.isSymbolicLink()) {
|
|
30472
30716
|
return "symlink";
|
|
30473
30717
|
}
|
|
@@ -30477,20 +30721,20 @@ async function pathType(targetPath) {
|
|
|
30477
30721
|
}
|
|
30478
30722
|
}
|
|
30479
30723
|
async function copyDirectory(src, dest) {
|
|
30480
|
-
await
|
|
30481
|
-
const entries = await
|
|
30724
|
+
await fs28.mkdir(dest, { recursive: true });
|
|
30725
|
+
const entries = await fs28.readdir(src, { withFileTypes: true });
|
|
30482
30726
|
for (const entry of entries) {
|
|
30483
|
-
const srcPath =
|
|
30484
|
-
const destPath =
|
|
30727
|
+
const srcPath = join6(src, entry.name);
|
|
30728
|
+
const destPath = join6(dest, entry.name);
|
|
30485
30729
|
if (entry.isDirectory()) {
|
|
30486
30730
|
await copyDirectory(srcPath, destPath);
|
|
30487
30731
|
} else if (entry.isSymbolicLink()) {
|
|
30488
|
-
const target = await
|
|
30489
|
-
await
|
|
30490
|
-
await
|
|
30732
|
+
const target = await fs28.readlink(srcPath);
|
|
30733
|
+
await fs28.mkdir(dirname3(destPath), { recursive: true });
|
|
30734
|
+
await fs28.symlink(target, destPath);
|
|
30491
30735
|
} else {
|
|
30492
|
-
await
|
|
30493
|
-
await
|
|
30736
|
+
await fs28.mkdir(dirname3(destPath), { recursive: true });
|
|
30737
|
+
await fs28.copyFile(srcPath, destPath);
|
|
30494
30738
|
}
|
|
30495
30739
|
}
|
|
30496
30740
|
}
|
|
@@ -30499,14 +30743,14 @@ async function copyPath(src, dest) {
|
|
|
30499
30743
|
if (!type2) {
|
|
30500
30744
|
return;
|
|
30501
30745
|
}
|
|
30502
|
-
await
|
|
30746
|
+
await fs28.mkdir(dirname3(dest), { recursive: true });
|
|
30503
30747
|
if (type2 === "symlink") {
|
|
30504
|
-
const target = await
|
|
30505
|
-
await
|
|
30748
|
+
const target = await fs28.readlink(src);
|
|
30749
|
+
await fs28.symlink(target, dest);
|
|
30506
30750
|
} else if (type2 === "directory") {
|
|
30507
30751
|
await copyDirectory(src, dest);
|
|
30508
30752
|
} else {
|
|
30509
|
-
await
|
|
30753
|
+
await fs28.copyFile(src, dest);
|
|
30510
30754
|
}
|
|
30511
30755
|
}
|
|
30512
30756
|
var MANAGED_STATE_FILE = "managed-state.json";
|
|
@@ -30520,11 +30764,11 @@ class ManagedStateStore {
|
|
|
30520
30764
|
this.state = state;
|
|
30521
30765
|
}
|
|
30522
30766
|
static async open(projectPath) {
|
|
30523
|
-
const agentInitDir =
|
|
30524
|
-
const statePath =
|
|
30767
|
+
const agentInitDir = join6(projectPath, ".agentinit");
|
|
30768
|
+
const statePath = join6(agentInitDir, MANAGED_STATE_FILE);
|
|
30525
30769
|
const emptyState = { version: 1, entries: [] };
|
|
30526
30770
|
try {
|
|
30527
|
-
const raw = await
|
|
30771
|
+
const raw = await fs28.readFile(statePath, "utf8");
|
|
30528
30772
|
const parsed = JSON.parse(raw);
|
|
30529
30773
|
if (!parsed || parsed.version !== 1 || !Array.isArray(parsed.entries)) {
|
|
30530
30774
|
return new ManagedStateStore(projectPath, emptyState);
|
|
@@ -30535,13 +30779,13 @@ class ManagedStateStore {
|
|
|
30535
30779
|
}
|
|
30536
30780
|
}
|
|
30537
30781
|
get agentInitDir() {
|
|
30538
|
-
return
|
|
30782
|
+
return join6(this.projectPath, ".agentinit");
|
|
30539
30783
|
}
|
|
30540
30784
|
get stateFilePath() {
|
|
30541
|
-
return
|
|
30785
|
+
return join6(this.agentInitDir, MANAGED_STATE_FILE);
|
|
30542
30786
|
}
|
|
30543
30787
|
get backupsDir() {
|
|
30544
|
-
return
|
|
30788
|
+
return join6(this.agentInitDir, BACKUPS_DIR);
|
|
30545
30789
|
}
|
|
30546
30790
|
normalizeRelativePath(targetPath, preserveTrailingSlash = false) {
|
|
30547
30791
|
const hasTrailingSlash = preserveTrailingSlash && /[\\/]$/.test(targetPath);
|
|
@@ -30563,14 +30807,14 @@ class ManagedStateStore {
|
|
|
30563
30807
|
}
|
|
30564
30808
|
if (type2 === "symlink") {
|
|
30565
30809
|
try {
|
|
30566
|
-
const backupLinkTarget = await
|
|
30810
|
+
const backupLinkTarget = await fs28.readlink(targetPath);
|
|
30567
30811
|
return { backupLinkTarget };
|
|
30568
30812
|
} catch {
|
|
30569
30813
|
return {};
|
|
30570
30814
|
}
|
|
30571
30815
|
}
|
|
30572
30816
|
const relativeTargetPath = this.normalizeRelativePath(targetPath);
|
|
30573
|
-
const backupPath =
|
|
30817
|
+
const backupPath = join6(this.backupsDir, relativeTargetPath);
|
|
30574
30818
|
if (!await fileExists(backupPath)) {
|
|
30575
30819
|
await copyPath(targetPath, backupPath);
|
|
30576
30820
|
}
|
|
@@ -30617,8 +30861,8 @@ class ManagedStateStore {
|
|
|
30617
30861
|
return [...paths5];
|
|
30618
30862
|
}
|
|
30619
30863
|
async save() {
|
|
30620
|
-
await
|
|
30621
|
-
await
|
|
30864
|
+
await fs28.mkdir(this.agentInitDir, { recursive: true });
|
|
30865
|
+
await fs28.writeFile(this.stateFilePath, JSON.stringify(this.state, null, 2), "utf8");
|
|
30622
30866
|
}
|
|
30623
30867
|
async revertAll(options2 = {}) {
|
|
30624
30868
|
const summary = {
|
|
@@ -30633,29 +30877,29 @@ class ManagedStateStore {
|
|
|
30633
30877
|
const backupLinkTarget = entry.backupLinkTarget;
|
|
30634
30878
|
if (entry.existedBefore && backupLinkTarget !== undefined) {
|
|
30635
30879
|
if (!options2.dryRun) {
|
|
30636
|
-
await
|
|
30880
|
+
await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
|
|
30637
30881
|
});
|
|
30638
|
-
await
|
|
30639
|
-
await
|
|
30882
|
+
await fs28.mkdir(dirname3(absolutePath), { recursive: true });
|
|
30883
|
+
await fs28.symlink(backupLinkTarget, absolutePath);
|
|
30640
30884
|
}
|
|
30641
30885
|
summary.restored++;
|
|
30642
30886
|
} else if (entry.existedBefore && backupPath && await fileExists(backupPath)) {
|
|
30643
30887
|
if (!options2.dryRun) {
|
|
30644
|
-
await
|
|
30888
|
+
await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
|
|
30645
30889
|
});
|
|
30646
30890
|
await copyPath(backupPath, absolutePath);
|
|
30647
30891
|
}
|
|
30648
30892
|
summary.restored++;
|
|
30649
30893
|
} else {
|
|
30650
30894
|
if (!options2.dryRun) {
|
|
30651
|
-
await
|
|
30895
|
+
await fs28.rm(absolutePath, { recursive: true, force: true }).catch(() => {
|
|
30652
30896
|
});
|
|
30653
30897
|
}
|
|
30654
30898
|
summary.removed++;
|
|
30655
30899
|
}
|
|
30656
30900
|
if (!options2.keepBackups && backupPath && await fileExists(backupPath)) {
|
|
30657
30901
|
if (!options2.dryRun) {
|
|
30658
|
-
await
|
|
30902
|
+
await fs28.rm(backupPath, { recursive: true, force: true }).catch(() => {
|
|
30659
30903
|
});
|
|
30660
30904
|
}
|
|
30661
30905
|
summary.backupsRemoved++;
|
|
@@ -30663,16 +30907,16 @@ class ManagedStateStore {
|
|
|
30663
30907
|
}
|
|
30664
30908
|
if (!options2.dryRun) {
|
|
30665
30909
|
this.state.entries.length = 0;
|
|
30666
|
-
await
|
|
30910
|
+
await fs28.rm(this.stateFilePath, { force: true }).catch(() => {
|
|
30667
30911
|
});
|
|
30668
30912
|
if (!options2.keepBackups) {
|
|
30669
|
-
await
|
|
30913
|
+
await fs28.rm(this.backupsDir, { recursive: true, force: true }).catch(() => {
|
|
30670
30914
|
});
|
|
30671
30915
|
}
|
|
30672
30916
|
try {
|
|
30673
|
-
const remainingEntries = await
|
|
30917
|
+
const remainingEntries = await fs28.readdir(this.agentInitDir);
|
|
30674
30918
|
if (remainingEntries.length === 0) {
|
|
30675
|
-
await
|
|
30919
|
+
await fs28.rm(this.agentInitDir, { recursive: true, force: true });
|
|
30676
30920
|
}
|
|
30677
30921
|
} catch {
|
|
30678
30922
|
}
|
|
@@ -31015,15 +31259,15 @@ class MCPParser {
|
|
|
31015
31259
|
}
|
|
31016
31260
|
|
|
31017
31261
|
// dist/constants/mcp.js
|
|
31018
|
-
import {readFileSync} from "fs";
|
|
31262
|
+
import {readFileSync as readFileSync2} from "fs";
|
|
31019
31263
|
import {fileURLToPath} from "url";
|
|
31020
|
-
import {dirname as dirname4, join as
|
|
31264
|
+
import {dirname as dirname4, join as join7} from "path";
|
|
31021
31265
|
var getPackageVersion = function() {
|
|
31022
31266
|
try {
|
|
31023
31267
|
const __filename2 = fileURLToPath(import.meta.url);
|
|
31024
31268
|
const __dirname2 = dirname4(__filename2);
|
|
31025
|
-
const packageJsonPath =
|
|
31026
|
-
const packageJson = JSON.parse(
|
|
31269
|
+
const packageJsonPath = join7(__dirname2, "../../package.json");
|
|
31270
|
+
const packageJson = JSON.parse(readFileSync2(packageJsonPath, "utf-8"));
|
|
31027
31271
|
return packageJson.version || "1.0.0";
|
|
31028
31272
|
} catch {
|
|
31029
31273
|
return "1.0.0";
|
|
@@ -31049,13 +31293,13 @@ var TOKEN_COUNT_THRESHOLDS = {
|
|
|
31049
31293
|
};
|
|
31050
31294
|
// dist/core/rulesParser.js
|
|
31051
31295
|
init_fs();
|
|
31052
|
-
import {readFileSync as
|
|
31296
|
+
import {readFileSync as readFileSync4} from "fs";
|
|
31053
31297
|
|
|
31054
31298
|
// dist/core/rulesTemplateLoader.js
|
|
31055
31299
|
var toml = __toESM(require_toml(), 1);
|
|
31056
31300
|
import {resolve as resolve11, dirname as dirname5} from "path";
|
|
31057
31301
|
import {fileURLToPath as fileURLToPath2} from "url";
|
|
31058
|
-
import {readFileSync as
|
|
31302
|
+
import {readFileSync as readFileSync3, readdirSync, existsSync as existsSync2} from "fs";
|
|
31059
31303
|
var __filename2 = fileURLToPath2(import.meta.url);
|
|
31060
31304
|
var __dirname2 = dirname5(__filename2);
|
|
31061
31305
|
|
|
@@ -31067,14 +31311,14 @@ class RulesTemplateLoader {
|
|
|
31067
31311
|
this.loadTemplates();
|
|
31068
31312
|
}
|
|
31069
31313
|
loadTemplates() {
|
|
31070
|
-
if (!
|
|
31314
|
+
if (!existsSync2(this.templatesPath)) {
|
|
31071
31315
|
throw new Error(`Rules templates directory not found: ${this.templatesPath}`);
|
|
31072
31316
|
}
|
|
31073
31317
|
const files = readdirSync(this.templatesPath).filter((file) => file.endsWith(".toml"));
|
|
31074
31318
|
for (const file of files) {
|
|
31075
31319
|
try {
|
|
31076
31320
|
const filePath = resolve11(this.templatesPath, file);
|
|
31077
|
-
const content =
|
|
31321
|
+
const content = readFileSync3(filePath, "utf-8");
|
|
31078
31322
|
const parsed = toml.default.parse(content);
|
|
31079
31323
|
const template = {
|
|
31080
31324
|
id: parsed.template.id,
|
|
@@ -31222,7 +31466,7 @@ class RulesParser {
|
|
|
31222
31466
|
throw new RulesParseError(`Rules file not found: ${filePath}`);
|
|
31223
31467
|
}
|
|
31224
31468
|
try {
|
|
31225
|
-
const content =
|
|
31469
|
+
const content = readFileSync4(filePath, "utf-8");
|
|
31226
31470
|
if (filePath.endsWith(".json")) {
|
|
31227
31471
|
const parsed = JSON.parse(content);
|
|
31228
31472
|
return this.extractRulesFromObject(parsed);
|
|
@@ -39292,8 +39536,8 @@ class MCPVerifier {
|
|
|
39292
39536
|
}
|
|
39293
39537
|
|
|
39294
39538
|
// dist/core/gitignoreManager.js
|
|
39295
|
-
import {promises as
|
|
39296
|
-
import {dirname as dirname6, join as
|
|
39539
|
+
import {promises as fs31} from "fs";
|
|
39540
|
+
import {dirname as dirname6, join as join8} from "path";
|
|
39297
39541
|
var normalizeIgnorePath = function(projectPath, value) {
|
|
39298
39542
|
const relative6 = value.startsWith(projectPath) ? value.slice(projectPath.length + 1) : value;
|
|
39299
39543
|
const normalized = relative6.replace(/\\/g, "/").replace(/^\/+/, "");
|
|
@@ -39340,12 +39584,12 @@ var updateManagedBlock = function(existingContent, entries) {
|
|
|
39340
39584
|
return content;
|
|
39341
39585
|
};
|
|
39342
39586
|
async function updateManagedIgnoreFile(projectPath, paths5, options2 = {}) {
|
|
39343
|
-
const ignoreFile = options2.local ?
|
|
39344
|
-
const ignoreFilePath =
|
|
39587
|
+
const ignoreFile = options2.local ? join8(".git", "info", "exclude") : ".gitignore";
|
|
39588
|
+
const ignoreFilePath = join8(projectPath, ignoreFile);
|
|
39345
39589
|
if (options2.local) {
|
|
39346
|
-
const gitDir =
|
|
39590
|
+
const gitDir = join8(projectPath, ".git");
|
|
39347
39591
|
try {
|
|
39348
|
-
const stat = await
|
|
39592
|
+
const stat = await fs31.stat(gitDir);
|
|
39349
39593
|
if (!stat.isDirectory()) {
|
|
39350
39594
|
throw new Error;
|
|
39351
39595
|
}
|
|
@@ -39356,21 +39600,21 @@ async function updateManagedIgnoreFile(projectPath, paths5, options2 = {}) {
|
|
|
39356
39600
|
const normalizedPaths = [...new Set(paths5.map((path) => normalizeIgnorePath(projectPath, path)).filter(Boolean))].sort();
|
|
39357
39601
|
let existingContent = "";
|
|
39358
39602
|
try {
|
|
39359
|
-
existingContent = await
|
|
39603
|
+
existingContent = await fs31.readFile(ignoreFilePath, "utf8");
|
|
39360
39604
|
} catch {
|
|
39361
39605
|
existingContent = "";
|
|
39362
39606
|
}
|
|
39363
39607
|
const updatedContent = updateManagedBlock(existingContent, normalizedPaths);
|
|
39364
|
-
await
|
|
39365
|
-
await
|
|
39608
|
+
await fs31.mkdir(dirname6(ignoreFilePath), { recursive: true });
|
|
39609
|
+
await fs31.writeFile(ignoreFilePath, updatedContent, "utf8");
|
|
39366
39610
|
return ignoreFilePath;
|
|
39367
39611
|
}
|
|
39368
39612
|
async function removeManagedIgnoreBlock(projectPath, options2 = {}) {
|
|
39369
|
-
const ignoreFile = options2.local ?
|
|
39370
|
-
const ignoreFilePath =
|
|
39613
|
+
const ignoreFile = options2.local ? join8(".git", "info", "exclude") : ".gitignore";
|
|
39614
|
+
const ignoreFilePath = join8(projectPath, ignoreFile);
|
|
39371
39615
|
let content;
|
|
39372
39616
|
try {
|
|
39373
|
-
content = await
|
|
39617
|
+
content = await fs31.readFile(ignoreFilePath, "utf8");
|
|
39374
39618
|
} catch {
|
|
39375
39619
|
return false;
|
|
39376
39620
|
}
|
|
@@ -39386,13 +39630,13 @@ async function removeManagedIgnoreBlock(projectPath, options2 = {}) {
|
|
|
39386
39630
|
const afterBlock = content.slice(endIndex + END_MARKER.length).replace(/^\n+/, "");
|
|
39387
39631
|
let nextContent = `${beforeBlock}${afterBlock}`.replace(/\n{3,}/g, "\n\n").replace(/^\n+/, "");
|
|
39388
39632
|
if (nextContent.trim() === "") {
|
|
39389
|
-
await
|
|
39633
|
+
await fs31.rm(ignoreFilePath, { force: true }).catch(() => {
|
|
39390
39634
|
});
|
|
39391
39635
|
} else {
|
|
39392
39636
|
if (!nextContent.endsWith("\n")) {
|
|
39393
39637
|
nextContent += "\n";
|
|
39394
39638
|
}
|
|
39395
|
-
await
|
|
39639
|
+
await fs31.writeFile(ignoreFilePath, nextContent, "utf8");
|
|
39396
39640
|
}
|
|
39397
39641
|
return true;
|
|
39398
39642
|
}
|
|
@@ -39403,12 +39647,12 @@ var END_MARKER = "# END AgentInit Generated Files";
|
|
|
39403
39647
|
init_agentManager();
|
|
39404
39648
|
init_skillsManager();
|
|
39405
39649
|
init_fs();
|
|
39406
|
-
import {dirname as dirname7, join as
|
|
39650
|
+
import {dirname as dirname7, join as join9} from "path";
|
|
39407
39651
|
async function discoverProjectSkills(projectPath, skillsManager4) {
|
|
39408
39652
|
const sources = [];
|
|
39409
39653
|
const skills = new Map;
|
|
39410
39654
|
for (const sourceDir of PROJECT_SKILL_SOURCE_DIRS) {
|
|
39411
|
-
const absoluteSourceDir =
|
|
39655
|
+
const absoluteSourceDir = join9(projectPath, sourceDir);
|
|
39412
39656
|
if (!await fileExists(absoluteSourceDir)) {
|
|
39413
39657
|
continue;
|
|
39414
39658
|
}
|
|
@@ -40300,9 +40544,197 @@ async function revertCommand(options2) {
|
|
|
40300
40544
|
}
|
|
40301
40545
|
}
|
|
40302
40546
|
|
|
40547
|
+
// dist/utils/colors.js
|
|
40548
|
+
var colorsEnabled = function() {
|
|
40549
|
+
const env2 = process.env || {};
|
|
40550
|
+
const isTTY2 = !!process.stdout?.isTTY;
|
|
40551
|
+
return !env2.NODE_DISABLE_COLORS && env2.NO_COLOR == null && env2.TERM !== "dumb" && (env2.FORCE_COLOR != null && env2.FORCE_COLOR !== "0" || isTTY2);
|
|
40552
|
+
};
|
|
40553
|
+
function orange(text) {
|
|
40554
|
+
if (!colorsEnabled()) {
|
|
40555
|
+
return text;
|
|
40556
|
+
}
|
|
40557
|
+
return `\x1B[38;5;208m${text}\x1B[39m`;
|
|
40558
|
+
}
|
|
40559
|
+
|
|
40560
|
+
// dist/commands/config.js
|
|
40561
|
+
init_marketplaceRegistry();
|
|
40562
|
+
init_userConfig();
|
|
40563
|
+
var sortConfig = function(config) {
|
|
40564
|
+
config.customMarketplaces.sort((left, right) => left.identifier.localeCompare(right.identifier));
|
|
40565
|
+
config.verifiedGithubRepos.sort((left, right) => left.localeCompare(right));
|
|
40566
|
+
return config;
|
|
40567
|
+
};
|
|
40568
|
+
var failConfigCommand = function(error) {
|
|
40569
|
+
logger.error(error instanceof Error ? error.message : "Configuration update failed.");
|
|
40570
|
+
process.exitCode = 1;
|
|
40571
|
+
};
|
|
40572
|
+
function registerConfigCommand(program2) {
|
|
40573
|
+
const config = program2.command("config").description("Manage AgentInit user configuration");
|
|
40574
|
+
const marketplaces = config.command("marketplaces").description("Manage configured marketplaces");
|
|
40575
|
+
marketplaces.command("list").description("List built-in and custom marketplaces").action(async () => {
|
|
40576
|
+
logger.titleBox("AgentInit Configuration");
|
|
40577
|
+
logger.section("Marketplaces");
|
|
40578
|
+
const defaultMarketplace = getConfiguredDefaultMarketplaceId();
|
|
40579
|
+
const marketplaceIds = getMarketplaceIds();
|
|
40580
|
+
for (let i = 0;i < marketplaceIds.length; i++) {
|
|
40581
|
+
const identifier = marketplaceIds[i];
|
|
40582
|
+
const marketplace = getMarketplace(identifier);
|
|
40583
|
+
if (!marketplace) {
|
|
40584
|
+
continue;
|
|
40585
|
+
}
|
|
40586
|
+
const flags = [
|
|
40587
|
+
BUILT_IN_MARKETPLACE_IDS.has(identifier) ? "built-in" : "custom",
|
|
40588
|
+
defaultMarketplace === identifier ? "default" : null
|
|
40589
|
+
].filter(Boolean).join(", ");
|
|
40590
|
+
logger.tree(`${cyan(identifier)} ${dim(`[${flags}]`)} ${marketplace.name} ${dim(`-> ${marketplace.repoUrl}`)}`, i === marketplaceIds.length - 1);
|
|
40591
|
+
}
|
|
40592
|
+
if (!defaultMarketplace) {
|
|
40593
|
+
logger.info("No default marketplace configured.");
|
|
40594
|
+
}
|
|
40595
|
+
});
|
|
40596
|
+
marketplaces.command("add <identifier> <repoUrl>").description("Add a custom marketplace").option("--name <displayName>", "Display name for this marketplace").option("--default", "Set this marketplace as the default").action(async (identifierArg, repoUrlArg, options2) => {
|
|
40597
|
+
logger.titleBox("AgentInit Configuration");
|
|
40598
|
+
try {
|
|
40599
|
+
const identifier = normalizeMarketplaceIdentifier(identifierArg);
|
|
40600
|
+
const repoUrl = normalizeMarketplaceRepoUrl(repoUrlArg);
|
|
40601
|
+
const configState = await readUserConfig();
|
|
40602
|
+
if (BUILT_IN_MARKETPLACE_IDS.has(identifier)) {
|
|
40603
|
+
throw new Error(`Marketplace "${identifier}" is built in and cannot be redefined.`);
|
|
40604
|
+
}
|
|
40605
|
+
if (configState.customMarketplaces.some((marketplace) => marketplace.identifier === identifier)) {
|
|
40606
|
+
throw new Error(`Marketplace "${identifier}" already exists.`);
|
|
40607
|
+
}
|
|
40608
|
+
configState.customMarketplaces.push({
|
|
40609
|
+
identifier,
|
|
40610
|
+
name: normalizeMarketplaceName(options2.name, identifier),
|
|
40611
|
+
repoUrl
|
|
40612
|
+
});
|
|
40613
|
+
if (options2.default) {
|
|
40614
|
+
configState.defaultMarketplace = identifier;
|
|
40615
|
+
}
|
|
40616
|
+
await writeUserConfig(sortConfig(configState));
|
|
40617
|
+
logger.success(`Added marketplace ${green(identifier)}.`);
|
|
40618
|
+
logger.info(` ${repoUrl}`);
|
|
40619
|
+
if (options2.default) {
|
|
40620
|
+
logger.info(" Set as the configured default marketplace.");
|
|
40621
|
+
}
|
|
40622
|
+
} catch (error) {
|
|
40623
|
+
failConfigCommand(error);
|
|
40624
|
+
}
|
|
40625
|
+
});
|
|
40626
|
+
marketplaces.command("remove <identifier>").description("Remove a custom marketplace").action(async (identifierArg) => {
|
|
40627
|
+
logger.titleBox("AgentInit Configuration");
|
|
40628
|
+
try {
|
|
40629
|
+
const identifier = normalizeMarketplaceIdentifier(identifierArg);
|
|
40630
|
+
if (BUILT_IN_MARKETPLACE_IDS.has(identifier)) {
|
|
40631
|
+
throw new Error(`Marketplace "${identifier}" is built in and cannot be removed.`);
|
|
40632
|
+
}
|
|
40633
|
+
const configState = await readUserConfig();
|
|
40634
|
+
const nextMarketplaces = configState.customMarketplaces.filter((marketplace) => marketplace.identifier !== identifier);
|
|
40635
|
+
if (nextMarketplaces.length === configState.customMarketplaces.length) {
|
|
40636
|
+
throw new Error(`Marketplace "${identifier}" is not configured.`);
|
|
40637
|
+
}
|
|
40638
|
+
configState.customMarketplaces = nextMarketplaces;
|
|
40639
|
+
const clearedDefault = configState.defaultMarketplace === identifier;
|
|
40640
|
+
if (clearedDefault) {
|
|
40641
|
+
delete configState.defaultMarketplace;
|
|
40642
|
+
}
|
|
40643
|
+
await writeUserConfig(sortConfig(configState));
|
|
40644
|
+
logger.success(`Removed marketplace ${green(identifier)}.`);
|
|
40645
|
+
if (clearedDefault) {
|
|
40646
|
+
logger.info(" Cleared the configured default marketplace.");
|
|
40647
|
+
}
|
|
40648
|
+
} catch (error) {
|
|
40649
|
+
failConfigCommand(error);
|
|
40650
|
+
}
|
|
40651
|
+
});
|
|
40652
|
+
marketplaces.command("default <identifier>").description("Set the configured default marketplace").action(async (identifierArg) => {
|
|
40653
|
+
logger.titleBox("AgentInit Configuration");
|
|
40654
|
+
try {
|
|
40655
|
+
const identifier = normalizeMarketplaceIdentifier(identifierArg);
|
|
40656
|
+
if (!getMarketplace(identifier)) {
|
|
40657
|
+
throw new Error(`Unknown marketplace: ${identifier}. Available: ${getMarketplaceIds().join(", ")}`);
|
|
40658
|
+
}
|
|
40659
|
+
const configState = await readUserConfig();
|
|
40660
|
+
configState.defaultMarketplace = identifier;
|
|
40661
|
+
await writeUserConfig(sortConfig(configState));
|
|
40662
|
+
logger.success(`Set ${green(identifier)} as the configured default marketplace.`);
|
|
40663
|
+
} catch (error) {
|
|
40664
|
+
failConfigCommand(error);
|
|
40665
|
+
}
|
|
40666
|
+
});
|
|
40667
|
+
marketplaces.command("clear-default").description("Clear the configured default marketplace").action(async () => {
|
|
40668
|
+
logger.titleBox("AgentInit Configuration");
|
|
40669
|
+
const configState = await readUserConfig();
|
|
40670
|
+
if (!configState.defaultMarketplace) {
|
|
40671
|
+
logger.info("No configured default marketplace to clear.");
|
|
40672
|
+
return;
|
|
40673
|
+
}
|
|
40674
|
+
delete configState.defaultMarketplace;
|
|
40675
|
+
await writeUserConfig(sortConfig(configState));
|
|
40676
|
+
logger.success("Cleared the configured default marketplace.");
|
|
40677
|
+
});
|
|
40678
|
+
const verifiedRepos = config.command("verified-repos").description("Manage exact verified GitHub repositories");
|
|
40679
|
+
verifiedRepos.command("list").description("List verified GitHub repositories").action(async () => {
|
|
40680
|
+
logger.titleBox("AgentInit Configuration");
|
|
40681
|
+
logger.section("Verified GitHub Repos");
|
|
40682
|
+
const configState = await readUserConfig();
|
|
40683
|
+
const entries = [
|
|
40684
|
+
...getBuiltInVerifiedGithubRepos().map((repo) => ({ repo, builtIn: true })),
|
|
40685
|
+
...configState.verifiedGithubRepos.filter((repo) => !BUILT_IN_VERIFIED_REPOS.has(repo)).map((repo) => ({ repo, builtIn: false }))
|
|
40686
|
+
];
|
|
40687
|
+
for (let i = 0;i < entries.length; i++) {
|
|
40688
|
+
const entry = entries[i];
|
|
40689
|
+
logger.tree(`${cyan(entry.repo)} ${dim(entry.builtIn ? "[built-in]" : "[custom]")}`, i === entries.length - 1);
|
|
40690
|
+
}
|
|
40691
|
+
});
|
|
40692
|
+
verifiedRepos.command("add <repo>").description("Add an exact verified GitHub repo in owner/repo form").action(async (repoArg) => {
|
|
40693
|
+
logger.titleBox("AgentInit Configuration");
|
|
40694
|
+
try {
|
|
40695
|
+
const repo = normalizeGitHubRepoRef(repoArg);
|
|
40696
|
+
if (BUILT_IN_VERIFIED_REPOS.has(repo)) {
|
|
40697
|
+
logger.info(`${repo} is already verified by AgentInit.`);
|
|
40698
|
+
return;
|
|
40699
|
+
}
|
|
40700
|
+
const configState = await readUserConfig();
|
|
40701
|
+
if (configState.verifiedGithubRepos.includes(repo)) {
|
|
40702
|
+
logger.info(`${repo} is already configured as verified.`);
|
|
40703
|
+
return;
|
|
40704
|
+
}
|
|
40705
|
+
configState.verifiedGithubRepos.push(repo);
|
|
40706
|
+
await writeUserConfig(sortConfig(configState));
|
|
40707
|
+
logger.success(`Added verified GitHub repo ${green(repo)}.`);
|
|
40708
|
+
} catch (error) {
|
|
40709
|
+
failConfigCommand(error);
|
|
40710
|
+
}
|
|
40711
|
+
});
|
|
40712
|
+
verifiedRepos.command("remove <repo>").description("Remove a custom verified GitHub repo").action(async (repoArg) => {
|
|
40713
|
+
logger.titleBox("AgentInit Configuration");
|
|
40714
|
+
try {
|
|
40715
|
+
const repo = normalizeGitHubRepoRef(repoArg);
|
|
40716
|
+
if (BUILT_IN_VERIFIED_REPOS.has(repo)) {
|
|
40717
|
+
throw new Error(`${repo} is built in and cannot be removed.`);
|
|
40718
|
+
}
|
|
40719
|
+
const configState = await readUserConfig();
|
|
40720
|
+
const nextRepos = configState.verifiedGithubRepos.filter((entry) => entry !== repo);
|
|
40721
|
+
if (nextRepos.length === configState.verifiedGithubRepos.length) {
|
|
40722
|
+
throw new Error(`${repo} is not configured as verified.`);
|
|
40723
|
+
}
|
|
40724
|
+
configState.verifiedGithubRepos = nextRepos;
|
|
40725
|
+
await writeUserConfig(sortConfig(configState));
|
|
40726
|
+
logger.success(`Removed verified GitHub repo ${green(repo)}.`);
|
|
40727
|
+
} catch (error) {
|
|
40728
|
+
failConfigCommand(error);
|
|
40729
|
+
}
|
|
40730
|
+
});
|
|
40731
|
+
}
|
|
40732
|
+
var BUILT_IN_MARKETPLACE_IDS = new Set(MARKETPLACES.map((marketplace) => marketplace.id));
|
|
40733
|
+
var BUILT_IN_VERIFIED_REPOS = new Set(getBuiltInVerifiedGithubRepos());
|
|
40734
|
+
|
|
40303
40735
|
// dist/commands/skills.js
|
|
40304
40736
|
var import_prompts2 = __toESM(require_prompts3(), 1);
|
|
40305
|
-
import {homedir as
|
|
40737
|
+
import {homedir as homedir6} from "os";
|
|
40306
40738
|
import {relative as relative7, resolve as resolve12} from "path";
|
|
40307
40739
|
init_skillsManager();
|
|
40308
40740
|
init_marketplaceRegistry();
|
|
@@ -40587,7 +41019,7 @@ var prependCanonicalGlobalGroup = function(agentManager9, projectPath, groups) {
|
|
|
40587
41019
|
var formatSkillsDir = function(projectPath, dir) {
|
|
40588
41020
|
const normalizedDir = dir.replace(/\\/g, "/").replace(/\/?$/, "/");
|
|
40589
41021
|
const normalizedProjectPath = projectPath.replace(/\\/g, "/");
|
|
40590
|
-
const normalizedHome =
|
|
41022
|
+
const normalizedHome = homedir6().replace(/\\/g, "/");
|
|
40591
41023
|
if (normalizedDir.startsWith(`${normalizedProjectPath}/`)) {
|
|
40592
41024
|
return `${relative7(projectPath, dir).replace(/\\/g, "/").replace(/\/?$/, "/")}`;
|
|
40593
41025
|
}
|
|
@@ -40598,7 +41030,7 @@ var formatSkillsDir = function(projectPath, dir) {
|
|
|
40598
41030
|
};
|
|
40599
41031
|
var formatPromptPath = function(path) {
|
|
40600
41032
|
const normalizedPath = path.replace(/\\/g, "/").replace(/\/?$/, "/");
|
|
40601
|
-
const normalizedHome =
|
|
41033
|
+
const normalizedHome = homedir6().replace(/\\/g, "/");
|
|
40602
41034
|
if (normalizedPath === `${normalizedHome}/`) {
|
|
40603
41035
|
return "~/";
|
|
40604
41036
|
}
|
|
@@ -40608,7 +41040,7 @@ var formatPromptPath = function(path) {
|
|
|
40608
41040
|
return normalizedPath;
|
|
40609
41041
|
};
|
|
40610
41042
|
var getCanonicalGlobalSkillsDir = function() {
|
|
40611
|
-
return resolve12(
|
|
41043
|
+
return resolve12(homedir6(), ".agents/skills");
|
|
40612
41044
|
};
|
|
40613
41045
|
var getCanonicalGlobalSkillsDisplayPath = function() {
|
|
40614
41046
|
return formatPromptPath(getCanonicalGlobalSkillsDir());
|
|
@@ -41550,25 +41982,12 @@ function registerRulesCommand(program2) {
|
|
|
41550
41982
|
// dist/commands/plugins.js
|
|
41551
41983
|
var import_prompts3 = __toESM(require_prompts3(), 1);
|
|
41552
41984
|
import {dirname as dirname8, relative as relative8} from "path";
|
|
41553
|
-
|
|
41554
|
-
// dist/utils/colors.js
|
|
41555
|
-
var colorsEnabled = function() {
|
|
41556
|
-
const env2 = process.env || {};
|
|
41557
|
-
const isTTY2 = !!process.stdout?.isTTY;
|
|
41558
|
-
return !env2.NODE_DISABLE_COLORS && env2.NO_COLOR == null && env2.TERM !== "dumb" && (env2.FORCE_COLOR != null && env2.FORCE_COLOR !== "0" || isTTY2);
|
|
41559
|
-
};
|
|
41560
|
-
function orange(text) {
|
|
41561
|
-
if (!colorsEnabled()) {
|
|
41562
|
-
return text;
|
|
41563
|
-
}
|
|
41564
|
-
return `\x1B[38;5;208m${text}\x1B[39m`;
|
|
41565
|
-
}
|
|
41566
|
-
|
|
41567
|
-
// dist/commands/plugins.js
|
|
41568
41985
|
init_pluginManager();
|
|
41569
41986
|
init_agentManager();
|
|
41987
|
+
init_marketplaceRegistry();
|
|
41570
41988
|
function registerPluginsCommand(program2) {
|
|
41571
41989
|
const marketplaceHelp = new PluginManager().getMarketplaceIds().join(", ");
|
|
41990
|
+
const marketplaceCategoryHelp = getMarketplaceCategories().join(", ");
|
|
41572
41991
|
const plugins = program2.command("plugins").description("Install agent-agnostic plugins from any marketplace or source");
|
|
41573
41992
|
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) => {
|
|
41574
41993
|
logger.titleBox("AgentInit Plugins");
|
|
@@ -41686,17 +42105,17 @@ function registerPluginsCommand(program2) {
|
|
|
41686
42105
|
logger.error(`Error: ${error instanceof Error ? error.message : "Unknown error"}`);
|
|
41687
42106
|
}
|
|
41688
42107
|
});
|
|
41689
|
-
plugins.command("search [query]").description("Search marketplace plugins").option("--from <marketplace>", `Which marketplace to search (available: ${marketplaceHelp})`).option("--category <category>",
|
|
42108
|
+
plugins.command("search [query]").description("Search marketplace plugins").option("--from <marketplace>", `Which marketplace to search (available: ${marketplaceHelp})`).option("--category <category>", `Filter by marketplace category (examples: ${marketplaceCategoryHelp})`).action(async (query, options2) => {
|
|
41690
42109
|
logger.titleBox("AgentInit Plugin Search");
|
|
41691
42110
|
const pluginManager2 = new PluginManager;
|
|
41692
|
-
|
|
42111
|
+
const registryId = options2.from || getConfiguredDefaultMarketplaceId();
|
|
42112
|
+
if (!registryId) {
|
|
41693
42113
|
logger.info(`Please specify a marketplace with --from <marketplace>. Available: ${marketplaceHelp}`);
|
|
41694
42114
|
logger.info("Examples:");
|
|
41695
42115
|
logger.info(" agentinit plugins search --from claude");
|
|
41696
42116
|
logger.info(" agentinit plugins search code-review --from claude");
|
|
41697
42117
|
return;
|
|
41698
42118
|
}
|
|
41699
|
-
const registryId = options2.from;
|
|
41700
42119
|
const spinner = ora(`Fetching ${registryId} marketplace...`).start();
|
|
41701
42120
|
try {
|
|
41702
42121
|
const results = await pluginManager2.listMarketplacePlugins(registryId, query, options2.category);
|
|
@@ -42111,6 +42530,7 @@ registerSkillsCommand(program2);
|
|
|
42111
42530
|
registerMcpCommand(program2);
|
|
42112
42531
|
registerRulesCommand(program2);
|
|
42113
42532
|
registerPluginsCommand(program2);
|
|
42533
|
+
registerConfigCommand(program2);
|
|
42114
42534
|
program2.command("init").description("Initialize agents.md configuration for the current project").option("-f, --force", "Overwrite existing configuration").option("-t, --template <template>", "Use specific template (web, cli, library)").action(initCommand);
|
|
42115
42535
|
program2.command("detect").description("Detect current project stack and existing agent configurations").option("-v, --verbose", "Show detailed detection results").action(detectCommand);
|
|
42116
42536
|
program2.command("sync").description("Sync agents.md with agent-specific configuration files").option("-a, --agent <agents...>", "Target specific agent(s)").option("-d, --dry-run", "Show what would be changed without making changes").option("-b, --backup", "Create backup before syncing").action(syncCommand);
|