@cleocode/caamp 0.4.0 → 0.4.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/dist/{chunk-ZYINKJDE.js → chunk-6HQDRJLS.js} +358 -154
- package/dist/chunk-6HQDRJLS.js.map +1 -0
- package/dist/cli.js +24 -40
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +56 -20
- package/dist/index.js +15 -1
- package/package.json +6 -3
- package/dist/chunk-ZYINKJDE.js.map +0 -1
|
@@ -1,58 +1,158 @@
|
|
|
1
|
-
// src/core/
|
|
2
|
-
import {
|
|
1
|
+
// src/core/paths/standard.ts
|
|
2
|
+
import { existsSync } from "fs";
|
|
3
3
|
import { homedir } from "os";
|
|
4
|
-
import { join,
|
|
5
|
-
|
|
6
|
-
function findRegistryPath() {
|
|
7
|
-
const thisDir = dirname(fileURLToPath(import.meta.url));
|
|
8
|
-
const devPath = join(thisDir, "..", "..", "..", "providers", "registry.json");
|
|
9
|
-
if (existsSync(devPath)) return devPath;
|
|
10
|
-
const distPath = join(thisDir, "..", "providers", "registry.json");
|
|
11
|
-
if (existsSync(distPath)) return distPath;
|
|
12
|
-
let dir = thisDir;
|
|
13
|
-
for (let i = 0; i < 5; i++) {
|
|
14
|
-
const candidate = join(dir, "providers", "registry.json");
|
|
15
|
-
if (existsSync(candidate)) return candidate;
|
|
16
|
-
dir = dirname(dir);
|
|
17
|
-
}
|
|
18
|
-
throw new Error(`Cannot find providers/registry.json (searched from ${thisDir})`);
|
|
19
|
-
}
|
|
20
|
-
var _registry = null;
|
|
21
|
-
var _providers = null;
|
|
22
|
-
var _aliasMap = null;
|
|
23
|
-
function getPlatformPaths() {
|
|
4
|
+
import { dirname, isAbsolute, join, resolve } from "path";
|
|
5
|
+
function getPlatformLocations() {
|
|
24
6
|
const home = homedir();
|
|
25
7
|
const platform = process.platform;
|
|
26
8
|
if (platform === "win32") {
|
|
27
9
|
const appData = process.env["APPDATA"] ?? join(home, "AppData", "Roaming");
|
|
28
10
|
return {
|
|
11
|
+
home,
|
|
29
12
|
config: appData,
|
|
30
13
|
vscodeConfig: join(appData, "Code", "User"),
|
|
31
14
|
zedConfig: join(appData, "Zed"),
|
|
32
|
-
claudeDesktopConfig: join(appData, "Claude")
|
|
15
|
+
claudeDesktopConfig: join(appData, "Claude"),
|
|
16
|
+
applications: []
|
|
33
17
|
};
|
|
34
|
-
}
|
|
18
|
+
}
|
|
19
|
+
if (platform === "darwin") {
|
|
20
|
+
const config2 = process.env["XDG_CONFIG_HOME"] ?? join(home, ".config");
|
|
35
21
|
return {
|
|
36
|
-
|
|
22
|
+
home,
|
|
23
|
+
config: config2,
|
|
37
24
|
vscodeConfig: join(home, "Library", "Application Support", "Code", "User"),
|
|
38
25
|
zedConfig: join(home, "Library", "Application Support", "Zed"),
|
|
39
|
-
claudeDesktopConfig: join(home, "Library", "Application Support", "Claude")
|
|
40
|
-
|
|
41
|
-
} else {
|
|
42
|
-
const config = process.env["XDG_CONFIG_HOME"] ?? join(home, ".config");
|
|
43
|
-
return {
|
|
44
|
-
config,
|
|
45
|
-
vscodeConfig: join(config, "Code", "User"),
|
|
46
|
-
zedConfig: join(config, "zed"),
|
|
47
|
-
claudeDesktopConfig: join(config, "Claude")
|
|
26
|
+
claudeDesktopConfig: join(home, "Library", "Application Support", "Claude"),
|
|
27
|
+
applications: ["/Applications", join(home, "Applications")]
|
|
48
28
|
};
|
|
49
29
|
}
|
|
30
|
+
const config = process.env["XDG_CONFIG_HOME"] ?? join(home, ".config");
|
|
31
|
+
return {
|
|
32
|
+
home,
|
|
33
|
+
config,
|
|
34
|
+
vscodeConfig: join(config, "Code", "User"),
|
|
35
|
+
zedConfig: join(config, "zed"),
|
|
36
|
+
claudeDesktopConfig: join(config, "Claude"),
|
|
37
|
+
applications: []
|
|
38
|
+
};
|
|
50
39
|
}
|
|
51
|
-
function
|
|
40
|
+
function normalizeHomeOverride(value) {
|
|
52
41
|
const home = homedir();
|
|
53
|
-
const
|
|
54
|
-
|
|
42
|
+
const trimmed = value.trim();
|
|
43
|
+
if (trimmed.startsWith("~/")) {
|
|
44
|
+
return join(home, trimmed.slice(2));
|
|
45
|
+
}
|
|
46
|
+
if (trimmed === "~") {
|
|
47
|
+
return home;
|
|
48
|
+
}
|
|
49
|
+
if (isAbsolute(trimmed)) {
|
|
50
|
+
return resolve(trimmed);
|
|
51
|
+
}
|
|
52
|
+
return resolve(home, trimmed);
|
|
53
|
+
}
|
|
54
|
+
function getAgentsHome() {
|
|
55
|
+
const override = process.env["AGENTS_HOME"];
|
|
56
|
+
if (override && override.trim().length > 0) {
|
|
57
|
+
return normalizeHomeOverride(override);
|
|
58
|
+
}
|
|
59
|
+
return join(homedir(), ".agents");
|
|
60
|
+
}
|
|
61
|
+
function getProjectAgentsDir(projectRoot = process.cwd()) {
|
|
62
|
+
return join(projectRoot, ".agents");
|
|
63
|
+
}
|
|
64
|
+
function resolveProjectPath(relativePath, projectDir = process.cwd()) {
|
|
65
|
+
return join(projectDir, relativePath);
|
|
55
66
|
}
|
|
67
|
+
function getCanonicalSkillsDir() {
|
|
68
|
+
return join(getAgentsHome(), "skills");
|
|
69
|
+
}
|
|
70
|
+
function getLockFilePath() {
|
|
71
|
+
return join(getAgentsHome(), ".caamp-lock.json");
|
|
72
|
+
}
|
|
73
|
+
function resolveRegistryTemplatePath(template) {
|
|
74
|
+
const locations = getPlatformLocations();
|
|
75
|
+
return template.replace(/\$HOME/g, locations.home).replace(/\$CONFIG/g, locations.config).replace(/\$VSCODE_CONFIG/g, locations.vscodeConfig).replace(/\$ZED_CONFIG/g, locations.zedConfig).replace(/\$CLAUDE_DESKTOP_CONFIG/g, locations.claudeDesktopConfig).replace(/\$AGENTS_HOME/g, getAgentsHome());
|
|
76
|
+
}
|
|
77
|
+
function resolveProviderConfigPath(provider, scope, projectDir = process.cwd()) {
|
|
78
|
+
if (scope === "global") {
|
|
79
|
+
return provider.configPathGlobal;
|
|
80
|
+
}
|
|
81
|
+
if (!provider.configPathProject) {
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
return resolveProjectPath(provider.configPathProject, projectDir);
|
|
85
|
+
}
|
|
86
|
+
function resolvePreferredConfigScope(provider, useGlobalFlag) {
|
|
87
|
+
if (useGlobalFlag) {
|
|
88
|
+
return "global";
|
|
89
|
+
}
|
|
90
|
+
return provider.configPathProject ? "project" : "global";
|
|
91
|
+
}
|
|
92
|
+
function resolveProviderSkillsDir(provider, scope, projectDir = process.cwd()) {
|
|
93
|
+
if (scope === "global") {
|
|
94
|
+
return provider.pathSkills;
|
|
95
|
+
}
|
|
96
|
+
return resolveProjectPath(provider.pathProjectSkills, projectDir);
|
|
97
|
+
}
|
|
98
|
+
function resolveProviderProjectPath(provider, projectDir = process.cwd()) {
|
|
99
|
+
return resolveProjectPath(provider.pathProject, projectDir);
|
|
100
|
+
}
|
|
101
|
+
function resolveProvidersRegistryPath(startDir) {
|
|
102
|
+
const candidates = [
|
|
103
|
+
join(startDir, "..", "..", "..", "providers", "registry.json"),
|
|
104
|
+
join(startDir, "..", "providers", "registry.json")
|
|
105
|
+
];
|
|
106
|
+
for (const candidate of candidates) {
|
|
107
|
+
if (existsSync(candidate)) {
|
|
108
|
+
return candidate;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
let current = startDir;
|
|
112
|
+
for (let i = 0; i < 8; i += 1) {
|
|
113
|
+
const candidate = join(current, "providers", "registry.json");
|
|
114
|
+
if (existsSync(candidate)) {
|
|
115
|
+
return candidate;
|
|
116
|
+
}
|
|
117
|
+
current = dirname(current);
|
|
118
|
+
}
|
|
119
|
+
throw new Error(`Cannot find providers/registry.json (searched from ${startDir})`);
|
|
120
|
+
}
|
|
121
|
+
function normalizeSkillSubPath(path) {
|
|
122
|
+
if (!path) return void 0;
|
|
123
|
+
const normalized = path.replace(/\\/g, "/").replace(/^\/+/, "").replace(/\/SKILL\.md$/i, "").trim();
|
|
124
|
+
return normalized.length > 0 ? normalized : void 0;
|
|
125
|
+
}
|
|
126
|
+
function buildSkillSubPathCandidates(marketplacePath, parsedPath) {
|
|
127
|
+
const candidates = [];
|
|
128
|
+
const base = normalizeSkillSubPath(marketplacePath);
|
|
129
|
+
const parsed = normalizeSkillSubPath(parsedPath);
|
|
130
|
+
if (base) candidates.push(base);
|
|
131
|
+
if (parsed) candidates.push(parsed);
|
|
132
|
+
const knownPrefixes = [".agents", ".claude"];
|
|
133
|
+
for (const value of [base, parsed]) {
|
|
134
|
+
if (!value || !value.startsWith("skills/")) continue;
|
|
135
|
+
for (const prefix of knownPrefixes) {
|
|
136
|
+
candidates.push(`${prefix}/${value}`);
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
if (candidates.length === 0) {
|
|
140
|
+
candidates.push(void 0);
|
|
141
|
+
}
|
|
142
|
+
return Array.from(new Set(candidates));
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// src/core/registry/providers.ts
|
|
146
|
+
import { readFileSync } from "fs";
|
|
147
|
+
import { dirname as dirname2 } from "path";
|
|
148
|
+
import { fileURLToPath } from "url";
|
|
149
|
+
function findRegistryPath() {
|
|
150
|
+
const thisDir = dirname2(fileURLToPath(import.meta.url));
|
|
151
|
+
return resolveProvidersRegistryPath(thisDir);
|
|
152
|
+
}
|
|
153
|
+
var _registry = null;
|
|
154
|
+
var _providers = null;
|
|
155
|
+
var _aliasMap = null;
|
|
56
156
|
function resolveProvider(raw) {
|
|
57
157
|
return {
|
|
58
158
|
id: raw.id,
|
|
@@ -60,19 +160,19 @@ function resolveProvider(raw) {
|
|
|
60
160
|
vendor: raw.vendor,
|
|
61
161
|
agentFlag: raw.agentFlag,
|
|
62
162
|
aliases: raw.aliases,
|
|
63
|
-
pathGlobal:
|
|
163
|
+
pathGlobal: resolveRegistryTemplatePath(raw.pathGlobal),
|
|
64
164
|
pathProject: raw.pathProject,
|
|
65
165
|
instructFile: raw.instructFile,
|
|
66
166
|
configKey: raw.configKey,
|
|
67
167
|
configFormat: raw.configFormat,
|
|
68
|
-
configPathGlobal:
|
|
168
|
+
configPathGlobal: resolveRegistryTemplatePath(raw.configPathGlobal),
|
|
69
169
|
configPathProject: raw.configPathProject,
|
|
70
|
-
pathSkills:
|
|
170
|
+
pathSkills: resolveRegistryTemplatePath(raw.pathSkills),
|
|
71
171
|
pathProjectSkills: raw.pathProjectSkills,
|
|
72
172
|
detection: {
|
|
73
173
|
methods: raw.detection.methods,
|
|
74
174
|
binary: raw.detection.binary,
|
|
75
|
-
directories: raw.detection.directories?.map(
|
|
175
|
+
directories: raw.detection.directories?.map(resolveRegistryTemplatePath),
|
|
76
176
|
appBundle: raw.detection.appBundle,
|
|
77
177
|
flatpakId: raw.detection.flatpakId
|
|
78
178
|
},
|
|
@@ -163,6 +263,8 @@ function isQuiet() {
|
|
|
163
263
|
import { existsSync as existsSync2 } from "fs";
|
|
164
264
|
import { execFileSync } from "child_process";
|
|
165
265
|
import { join as join2 } from "path";
|
|
266
|
+
var DEFAULT_DETECTION_CACHE_TTL_MS = 3e4;
|
|
267
|
+
var detectionCache = null;
|
|
166
268
|
function checkBinary(binary) {
|
|
167
269
|
try {
|
|
168
270
|
const cmd = process.platform === "win32" ? "where" : "which";
|
|
@@ -177,7 +279,8 @@ function checkDirectory(dir) {
|
|
|
177
279
|
}
|
|
178
280
|
function checkAppBundle(appName) {
|
|
179
281
|
if (process.platform !== "darwin") return false;
|
|
180
|
-
|
|
282
|
+
const applications = getPlatformLocations().applications;
|
|
283
|
+
return applications.some((base) => existsSync2(join2(base, appName)));
|
|
181
284
|
}
|
|
182
285
|
function checkFlatpak(flatpakId) {
|
|
183
286
|
if (process.platform !== "linux") return false;
|
|
@@ -229,24 +332,71 @@ function detectProvider(provider) {
|
|
|
229
332
|
projectDetected: false
|
|
230
333
|
};
|
|
231
334
|
}
|
|
335
|
+
function providerSignature(provider) {
|
|
336
|
+
return JSON.stringify({
|
|
337
|
+
id: provider.id,
|
|
338
|
+
methods: provider.detection.methods,
|
|
339
|
+
binary: provider.detection.binary,
|
|
340
|
+
directories: provider.detection.directories,
|
|
341
|
+
appBundle: provider.detection.appBundle,
|
|
342
|
+
flatpakId: provider.detection.flatpakId
|
|
343
|
+
});
|
|
344
|
+
}
|
|
345
|
+
function buildProvidersSignature(providers) {
|
|
346
|
+
return providers.map(providerSignature).join("|");
|
|
347
|
+
}
|
|
348
|
+
function cloneDetectionResults(results) {
|
|
349
|
+
return results.map((result) => ({
|
|
350
|
+
provider: result.provider,
|
|
351
|
+
installed: result.installed,
|
|
352
|
+
methods: [...result.methods],
|
|
353
|
+
projectDetected: result.projectDetected
|
|
354
|
+
}));
|
|
355
|
+
}
|
|
356
|
+
function getCachedResults(signature, options) {
|
|
357
|
+
if (!detectionCache || options.forceRefresh) return null;
|
|
358
|
+
if (detectionCache.signature !== signature) return null;
|
|
359
|
+
const ttlMs = options.ttlMs ?? DEFAULT_DETECTION_CACHE_TTL_MS;
|
|
360
|
+
if (ttlMs <= 0) return null;
|
|
361
|
+
if (Date.now() - detectionCache.createdAt > ttlMs) return null;
|
|
362
|
+
return cloneDetectionResults(detectionCache.results);
|
|
363
|
+
}
|
|
364
|
+
function setCachedResults(signature, results) {
|
|
365
|
+
detectionCache = {
|
|
366
|
+
createdAt: Date.now(),
|
|
367
|
+
signature,
|
|
368
|
+
results: cloneDetectionResults(results)
|
|
369
|
+
};
|
|
370
|
+
}
|
|
232
371
|
function detectProjectProvider(provider, projectDir) {
|
|
233
372
|
if (!provider.pathProject) return false;
|
|
234
|
-
return existsSync2(
|
|
373
|
+
return existsSync2(resolveProviderProjectPath(provider, projectDir));
|
|
235
374
|
}
|
|
236
|
-
function detectAllProviders() {
|
|
375
|
+
function detectAllProviders(options = {}) {
|
|
237
376
|
const providers = getAllProviders();
|
|
238
|
-
|
|
377
|
+
const signature = buildProvidersSignature(providers);
|
|
378
|
+
const cached = getCachedResults(signature, options);
|
|
379
|
+
if (cached) {
|
|
380
|
+
debug(`detection cache hit for ${providers.length} providers`);
|
|
381
|
+
return cached;
|
|
382
|
+
}
|
|
383
|
+
const results = providers.map(detectProvider);
|
|
384
|
+
setCachedResults(signature, results);
|
|
385
|
+
return cloneDetectionResults(results);
|
|
239
386
|
}
|
|
240
|
-
function getInstalledProviders() {
|
|
241
|
-
return detectAllProviders().filter((r) => r.installed).map((r) => r.provider);
|
|
387
|
+
function getInstalledProviders(options = {}) {
|
|
388
|
+
return detectAllProviders(options).filter((r) => r.installed).map((r) => r.provider);
|
|
242
389
|
}
|
|
243
|
-
function detectProjectProviders(projectDir) {
|
|
244
|
-
const results = detectAllProviders();
|
|
390
|
+
function detectProjectProviders(projectDir, options = {}) {
|
|
391
|
+
const results = detectAllProviders(options);
|
|
245
392
|
return results.map((r) => ({
|
|
246
393
|
...r,
|
|
247
394
|
projectDetected: detectProjectProvider(r.provider, projectDir)
|
|
248
395
|
}));
|
|
249
396
|
}
|
|
397
|
+
function resetDetectionCache() {
|
|
398
|
+
detectionCache = null;
|
|
399
|
+
}
|
|
250
400
|
|
|
251
401
|
// src/core/sources/parser.ts
|
|
252
402
|
var GITHUB_SHORTHAND = /^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)(?:\/(.+))?$/;
|
|
@@ -368,15 +518,20 @@ function isMarketplaceScoped(input) {
|
|
|
368
518
|
// src/core/skills/installer.ts
|
|
369
519
|
import { mkdir, symlink, rm, cp } from "fs/promises";
|
|
370
520
|
import { existsSync as existsSync3, lstatSync } from "fs";
|
|
371
|
-
import { homedir as homedir2 } from "os";
|
|
372
521
|
import { join as join3 } from "path";
|
|
373
|
-
|
|
522
|
+
|
|
523
|
+
// src/core/paths/agents.ts
|
|
524
|
+
var AGENTS_HOME = getAgentsHome();
|
|
525
|
+
var LOCK_FILE_PATH = getLockFilePath();
|
|
526
|
+
var CANONICAL_SKILLS_DIR = getCanonicalSkillsDir();
|
|
527
|
+
|
|
528
|
+
// src/core/skills/installer.ts
|
|
374
529
|
async function ensureCanonicalDir() {
|
|
375
|
-
await mkdir(
|
|
530
|
+
await mkdir(CANONICAL_SKILLS_DIR, { recursive: true });
|
|
376
531
|
}
|
|
377
532
|
async function installToCanonical(sourcePath, skillName) {
|
|
378
533
|
await ensureCanonicalDir();
|
|
379
|
-
const targetDir = join3(
|
|
534
|
+
const targetDir = join3(CANONICAL_SKILLS_DIR, skillName);
|
|
380
535
|
if (existsSync3(targetDir)) {
|
|
381
536
|
await rm(targetDir, { recursive: true });
|
|
382
537
|
}
|
|
@@ -384,7 +539,11 @@ async function installToCanonical(sourcePath, skillName) {
|
|
|
384
539
|
return targetDir;
|
|
385
540
|
}
|
|
386
541
|
async function linkToAgent(canonicalPath, provider, skillName, isGlobal, projectDir) {
|
|
387
|
-
const targetSkillsDir =
|
|
542
|
+
const targetSkillsDir = resolveProviderSkillsDir(
|
|
543
|
+
provider,
|
|
544
|
+
isGlobal ? "global" : "project",
|
|
545
|
+
projectDir
|
|
546
|
+
);
|
|
388
547
|
if (!targetSkillsDir) {
|
|
389
548
|
return { success: false, error: `Provider ${provider.id} has no skills directory` };
|
|
390
549
|
}
|
|
@@ -437,7 +596,11 @@ async function removeSkill(skillName, providers, isGlobal, projectDir) {
|
|
|
437
596
|
const removed = [];
|
|
438
597
|
const errors = [];
|
|
439
598
|
for (const provider of providers) {
|
|
440
|
-
const skillsDir =
|
|
599
|
+
const skillsDir = resolveProviderSkillsDir(
|
|
600
|
+
provider,
|
|
601
|
+
isGlobal ? "global" : "project",
|
|
602
|
+
projectDir
|
|
603
|
+
);
|
|
441
604
|
if (!skillsDir) continue;
|
|
442
605
|
const linkPath = join3(skillsDir, skillName);
|
|
443
606
|
if (existsSync3(linkPath)) {
|
|
@@ -449,7 +612,7 @@ async function removeSkill(skillName, providers, isGlobal, projectDir) {
|
|
|
449
612
|
}
|
|
450
613
|
}
|
|
451
614
|
}
|
|
452
|
-
const canonicalPath = join3(
|
|
615
|
+
const canonicalPath = join3(CANONICAL_SKILLS_DIR, skillName);
|
|
453
616
|
if (existsSync3(canonicalPath)) {
|
|
454
617
|
try {
|
|
455
618
|
await rm(canonicalPath, { recursive: true });
|
|
@@ -460,62 +623,95 @@ async function removeSkill(skillName, providers, isGlobal, projectDir) {
|
|
|
460
623
|
return { removed, errors };
|
|
461
624
|
}
|
|
462
625
|
async function listCanonicalSkills() {
|
|
463
|
-
if (!existsSync3(
|
|
626
|
+
if (!existsSync3(CANONICAL_SKILLS_DIR)) return [];
|
|
464
627
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
465
|
-
const entries = await readdir2(
|
|
628
|
+
const entries = await readdir2(CANONICAL_SKILLS_DIR, { withFileTypes: true });
|
|
466
629
|
return entries.filter((e) => e.isDirectory() || e.isSymbolicLink()).map((e) => e.name);
|
|
467
630
|
}
|
|
468
631
|
|
|
469
632
|
// src/core/lock-utils.ts
|
|
470
|
-
import { readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2 } from "fs/promises";
|
|
633
|
+
import { open, readFile as readFile2, writeFile as writeFile2, mkdir as mkdir2, rm as rm2, rename } from "fs/promises";
|
|
471
634
|
import { existsSync as existsSync4 } from "fs";
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
635
|
+
var LOCK_GUARD_PATH = `${LOCK_FILE_PATH}.lock`;
|
|
636
|
+
function sleep(ms) {
|
|
637
|
+
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
638
|
+
}
|
|
639
|
+
async function acquireLockGuard(retries = 40, delayMs = 25) {
|
|
640
|
+
await mkdir2(AGENTS_HOME, { recursive: true });
|
|
641
|
+
for (let attempt = 0; attempt < retries; attempt += 1) {
|
|
642
|
+
try {
|
|
643
|
+
const handle = await open(LOCK_GUARD_PATH, "wx");
|
|
644
|
+
await handle.close();
|
|
645
|
+
return;
|
|
646
|
+
} catch (error) {
|
|
647
|
+
if (!(error instanceof Error) || !("code" in error) || error.code !== "EEXIST") {
|
|
648
|
+
throw error;
|
|
649
|
+
}
|
|
650
|
+
await sleep(delayMs);
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
throw new Error("Timed out waiting for lock file guard");
|
|
654
|
+
}
|
|
655
|
+
async function releaseLockGuard() {
|
|
656
|
+
await rm2(LOCK_GUARD_PATH, { force: true });
|
|
657
|
+
}
|
|
658
|
+
async function writeLockFileUnsafe(lock) {
|
|
659
|
+
const tmpPath = `${LOCK_FILE_PATH}.tmp-${process.pid}-${Date.now()}`;
|
|
660
|
+
await writeFile2(tmpPath, JSON.stringify(lock, null, 2) + "\n", "utf-8");
|
|
661
|
+
await rename(tmpPath, LOCK_FILE_PATH);
|
|
662
|
+
}
|
|
476
663
|
async function readLockFile() {
|
|
477
664
|
try {
|
|
478
|
-
if (!existsSync4(
|
|
665
|
+
if (!existsSync4(LOCK_FILE_PATH)) {
|
|
479
666
|
return { version: 1, skills: {}, mcpServers: {} };
|
|
480
667
|
}
|
|
481
|
-
const content = await readFile2(
|
|
668
|
+
const content = await readFile2(LOCK_FILE_PATH, "utf-8");
|
|
482
669
|
return JSON.parse(content);
|
|
483
670
|
} catch {
|
|
484
671
|
return { version: 1, skills: {}, mcpServers: {} };
|
|
485
672
|
}
|
|
486
673
|
}
|
|
487
|
-
async function
|
|
488
|
-
await
|
|
489
|
-
|
|
674
|
+
async function updateLockFile(updater) {
|
|
675
|
+
await acquireLockGuard();
|
|
676
|
+
try {
|
|
677
|
+
const lock = await readLockFile();
|
|
678
|
+
await updater(lock);
|
|
679
|
+
await writeLockFileUnsafe(lock);
|
|
680
|
+
return lock;
|
|
681
|
+
} finally {
|
|
682
|
+
await releaseLockGuard();
|
|
683
|
+
}
|
|
490
684
|
}
|
|
491
685
|
|
|
492
686
|
// src/core/skills/lock.ts
|
|
493
687
|
import { simpleGit } from "simple-git";
|
|
494
688
|
async function recordSkillInstall(skillName, scopedName, source, sourceType, agents, canonicalPath, isGlobal, projectDir, version) {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
689
|
+
await updateLockFile((lock) => {
|
|
690
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
691
|
+
const existing = lock.skills[skillName];
|
|
692
|
+
lock.skills[skillName] = {
|
|
693
|
+
name: skillName,
|
|
694
|
+
scopedName,
|
|
695
|
+
source,
|
|
696
|
+
sourceType,
|
|
697
|
+
version,
|
|
698
|
+
installedAt: existing?.installedAt ?? now,
|
|
699
|
+
updatedAt: now,
|
|
700
|
+
agents: [.../* @__PURE__ */ new Set([...existing?.agents ?? [], ...agents])],
|
|
701
|
+
canonicalPath,
|
|
702
|
+
isGlobal,
|
|
703
|
+
projectDir
|
|
704
|
+
};
|
|
705
|
+
});
|
|
512
706
|
}
|
|
513
707
|
async function removeSkillFromLock(skillName) {
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
708
|
+
let removed = false;
|
|
709
|
+
await updateLockFile((lock) => {
|
|
710
|
+
if (!(skillName in lock.skills)) return;
|
|
711
|
+
delete lock.skills[skillName];
|
|
712
|
+
removed = true;
|
|
713
|
+
});
|
|
714
|
+
return removed;
|
|
519
715
|
}
|
|
520
716
|
async function getTrackedSkills() {
|
|
521
717
|
const lock = await readLockFile();
|
|
@@ -829,7 +1025,7 @@ var MarketplaceClient = class {
|
|
|
829
1025
|
// src/core/skills/discovery.ts
|
|
830
1026
|
import { readFile as readFile3, readdir } from "fs/promises";
|
|
831
1027
|
import { existsSync as existsSync5 } from "fs";
|
|
832
|
-
import { join as
|
|
1028
|
+
import { join as join4 } from "path";
|
|
833
1029
|
import matter from "gray-matter";
|
|
834
1030
|
async function parseSkillFile(filePath) {
|
|
835
1031
|
try {
|
|
@@ -853,7 +1049,7 @@ async function parseSkillFile(filePath) {
|
|
|
853
1049
|
}
|
|
854
1050
|
}
|
|
855
1051
|
async function discoverSkill(skillDir) {
|
|
856
|
-
const skillFile =
|
|
1052
|
+
const skillFile = join4(skillDir, "SKILL.md");
|
|
857
1053
|
if (!existsSync5(skillFile)) return null;
|
|
858
1054
|
const metadata = await parseSkillFile(skillFile);
|
|
859
1055
|
if (!metadata) return null;
|
|
@@ -870,7 +1066,7 @@ async function discoverSkills(rootDir) {
|
|
|
870
1066
|
const skills = [];
|
|
871
1067
|
for (const entry of entries) {
|
|
872
1068
|
if (!entry.isDirectory() && !entry.isSymbolicLink()) continue;
|
|
873
|
-
const skillDir =
|
|
1069
|
+
const skillDir = join4(rootDir, entry.name);
|
|
874
1070
|
const skill = await discoverSkill(skillDir);
|
|
875
1071
|
if (skill) {
|
|
876
1072
|
skills.push(skill);
|
|
@@ -1573,13 +1769,13 @@ async function scanFile(filePath, rules) {
|
|
|
1573
1769
|
}
|
|
1574
1770
|
async function scanDirectory(dirPath) {
|
|
1575
1771
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
1576
|
-
const { join:
|
|
1772
|
+
const { join: join7 } = await import("path");
|
|
1577
1773
|
if (!existsSync6(dirPath)) return [];
|
|
1578
1774
|
const entries = await readdir2(dirPath, { withFileTypes: true });
|
|
1579
1775
|
const results = [];
|
|
1580
1776
|
for (const entry of entries) {
|
|
1581
1777
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
1582
|
-
const skillFile =
|
|
1778
|
+
const skillFile = join7(dirPath, entry.name, "SKILL.md");
|
|
1583
1779
|
if (existsSync6(skillFile)) {
|
|
1584
1780
|
results.push(await scanFile(skillFile));
|
|
1585
1781
|
}
|
|
@@ -1794,8 +1990,8 @@ function getNestedValue(obj, keyPath) {
|
|
|
1794
1990
|
}
|
|
1795
1991
|
async function ensureDir(filePath) {
|
|
1796
1992
|
const { mkdir: mkdir5 } = await import("fs/promises");
|
|
1797
|
-
const { dirname:
|
|
1798
|
-
await mkdir5(
|
|
1993
|
+
const { dirname: dirname6 } = await import("path");
|
|
1994
|
+
await mkdir5(dirname6(filePath), { recursive: true });
|
|
1799
1995
|
}
|
|
1800
1996
|
|
|
1801
1997
|
// src/core/formats/json.ts
|
|
@@ -2107,14 +2303,9 @@ function getTransform(providerId) {
|
|
|
2107
2303
|
}
|
|
2108
2304
|
|
|
2109
2305
|
// src/core/mcp/reader.ts
|
|
2110
|
-
import { join as join6 } from "path";
|
|
2111
2306
|
import { existsSync as existsSync11 } from "fs";
|
|
2112
2307
|
function resolveConfigPath(provider, scope, projectDir) {
|
|
2113
|
-
|
|
2114
|
-
if (!provider.configPathProject) return null;
|
|
2115
|
-
return join6(projectDir ?? process.cwd(), provider.configPathProject);
|
|
2116
|
-
}
|
|
2117
|
-
return provider.configPathGlobal;
|
|
2308
|
+
return resolveProviderConfigPath(provider, scope, projectDir ?? process.cwd());
|
|
2118
2309
|
}
|
|
2119
2310
|
async function listMcpServers(provider, scope, projectDir) {
|
|
2120
2311
|
const configPath = resolveConfigPath(provider, scope, projectDir);
|
|
@@ -2237,37 +2428,39 @@ function buildServerConfig(source, transport, headers) {
|
|
|
2237
2428
|
|
|
2238
2429
|
// src/core/mcp/lock.ts
|
|
2239
2430
|
async function recordMcpInstall(serverName, source, sourceType, agents, isGlobal) {
|
|
2240
|
-
|
|
2241
|
-
|
|
2242
|
-
|
|
2243
|
-
|
|
2244
|
-
|
|
2245
|
-
|
|
2246
|
-
|
|
2247
|
-
|
|
2248
|
-
|
|
2249
|
-
|
|
2250
|
-
|
|
2251
|
-
|
|
2252
|
-
|
|
2253
|
-
|
|
2254
|
-
|
|
2431
|
+
await updateLockFile((lock) => {
|
|
2432
|
+
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
2433
|
+
const existing = lock.mcpServers[serverName];
|
|
2434
|
+
lock.mcpServers[serverName] = {
|
|
2435
|
+
name: serverName,
|
|
2436
|
+
scopedName: serverName,
|
|
2437
|
+
source,
|
|
2438
|
+
sourceType,
|
|
2439
|
+
installedAt: existing?.installedAt ?? now,
|
|
2440
|
+
updatedAt: now,
|
|
2441
|
+
agents: [.../* @__PURE__ */ new Set([...existing?.agents ?? [], ...agents])],
|
|
2442
|
+
canonicalPath: "",
|
|
2443
|
+
isGlobal
|
|
2444
|
+
};
|
|
2445
|
+
});
|
|
2255
2446
|
}
|
|
2256
2447
|
async function removeMcpFromLock(serverName) {
|
|
2257
|
-
|
|
2258
|
-
|
|
2259
|
-
|
|
2260
|
-
|
|
2261
|
-
|
|
2448
|
+
let removed = false;
|
|
2449
|
+
await updateLockFile((lock) => {
|
|
2450
|
+
if (!(serverName in lock.mcpServers)) return;
|
|
2451
|
+
delete lock.mcpServers[serverName];
|
|
2452
|
+
removed = true;
|
|
2453
|
+
});
|
|
2454
|
+
return removed;
|
|
2262
2455
|
}
|
|
2263
2456
|
async function getTrackedMcpServers() {
|
|
2264
2457
|
const lock = await readLockFile();
|
|
2265
2458
|
return lock.mcpServers;
|
|
2266
2459
|
}
|
|
2267
2460
|
async function saveLastSelectedAgents(agents) {
|
|
2268
|
-
|
|
2269
|
-
|
|
2270
|
-
|
|
2461
|
+
await updateLockFile((lock) => {
|
|
2462
|
+
lock.lastSelectedAgents = agents;
|
|
2463
|
+
});
|
|
2271
2464
|
}
|
|
2272
2465
|
async function getLastSelectedAgents() {
|
|
2273
2466
|
const lock = await readLockFile();
|
|
@@ -2277,7 +2470,7 @@ async function getLastSelectedAgents() {
|
|
|
2277
2470
|
// src/core/instructions/injector.ts
|
|
2278
2471
|
import { readFile as readFile9, writeFile as writeFile6 } from "fs/promises";
|
|
2279
2472
|
import { existsSync as existsSync12 } from "fs";
|
|
2280
|
-
import { join as
|
|
2473
|
+
import { join as join5, dirname as dirname4 } from "path";
|
|
2281
2474
|
import { mkdir as mkdir3 } from "fs/promises";
|
|
2282
2475
|
var MARKER_START = "<!-- CAAMP:START -->";
|
|
2283
2476
|
var MARKER_END = "<!-- CAAMP:END -->";
|
|
@@ -2307,7 +2500,7 @@ ${MARKER_END}`;
|
|
|
2307
2500
|
}
|
|
2308
2501
|
async function inject(filePath, content) {
|
|
2309
2502
|
const block = buildBlock(content);
|
|
2310
|
-
await mkdir3(
|
|
2503
|
+
await mkdir3(dirname4(filePath), { recursive: true });
|
|
2311
2504
|
if (!existsSync12(filePath)) {
|
|
2312
2505
|
await writeFile6(filePath, block + "\n", "utf-8");
|
|
2313
2506
|
return "created";
|
|
@@ -2328,8 +2521,8 @@ async function removeInjection(filePath) {
|
|
|
2328
2521
|
if (!MARKER_PATTERN.test(content)) return false;
|
|
2329
2522
|
const cleaned = content.replace(MARKER_PATTERN, "").replace(/^\n{2,}/, "\n").trim();
|
|
2330
2523
|
if (!cleaned) {
|
|
2331
|
-
const { rm:
|
|
2332
|
-
await
|
|
2524
|
+
const { rm: rm4 } = await import("fs/promises");
|
|
2525
|
+
await rm4(filePath);
|
|
2333
2526
|
} else {
|
|
2334
2527
|
await writeFile6(filePath, cleaned + "\n", "utf-8");
|
|
2335
2528
|
}
|
|
@@ -2339,7 +2532,7 @@ async function checkAllInjections(providers, projectDir, scope, expectedContent)
|
|
|
2339
2532
|
const results = [];
|
|
2340
2533
|
const checked = /* @__PURE__ */ new Set();
|
|
2341
2534
|
for (const provider of providers) {
|
|
2342
|
-
const filePath = scope === "global" ?
|
|
2535
|
+
const filePath = scope === "global" ? join5(provider.pathGlobal, provider.instructFile) : join5(projectDir, provider.instructFile);
|
|
2343
2536
|
if (checked.has(filePath)) continue;
|
|
2344
2537
|
checked.add(filePath);
|
|
2345
2538
|
const status = await checkInjection(filePath, expectedContent);
|
|
@@ -2356,7 +2549,7 @@ async function injectAll(providers, projectDir, scope, content) {
|
|
|
2356
2549
|
const results = /* @__PURE__ */ new Map();
|
|
2357
2550
|
const injected = /* @__PURE__ */ new Set();
|
|
2358
2551
|
for (const provider of providers) {
|
|
2359
|
-
const filePath = scope === "global" ?
|
|
2552
|
+
const filePath = scope === "global" ? join5(provider.pathGlobal, provider.instructFile) : join5(projectDir, provider.instructFile);
|
|
2360
2553
|
if (injected.has(filePath)) continue;
|
|
2361
2554
|
injected.add(filePath);
|
|
2362
2555
|
const action = await inject(filePath, content);
|
|
@@ -2400,25 +2593,25 @@ import {
|
|
|
2400
2593
|
mkdir as mkdir4,
|
|
2401
2594
|
readFile as readFile10,
|
|
2402
2595
|
readlink as readlink2,
|
|
2403
|
-
rm as
|
|
2596
|
+
rm as rm3,
|
|
2404
2597
|
symlink as symlink2,
|
|
2405
2598
|
writeFile as writeFile7
|
|
2406
2599
|
} from "fs/promises";
|
|
2407
|
-
import { homedir as
|
|
2408
|
-
import { basename as basename2, dirname as
|
|
2600
|
+
import { homedir as homedir2, tmpdir } from "os";
|
|
2601
|
+
import { basename as basename2, dirname as dirname5, join as join6 } from "path";
|
|
2409
2602
|
var PRIORITY_ORDER = {
|
|
2410
2603
|
high: 0,
|
|
2411
2604
|
medium: 1,
|
|
2412
2605
|
low: 2
|
|
2413
2606
|
};
|
|
2414
|
-
var
|
|
2607
|
+
var CANONICAL_SKILLS_DIR2 = join6(homedir2(), ".agents", "skills");
|
|
2415
2608
|
function selectProvidersByMinimumPriority(providers, minimumPriority = "low") {
|
|
2416
2609
|
const maxRank = PRIORITY_ORDER[minimumPriority];
|
|
2417
2610
|
return [...providers].filter((provider) => PRIORITY_ORDER[provider.priority] <= maxRank).sort((a, b) => PRIORITY_ORDER[a.priority] - PRIORITY_ORDER[b.priority]);
|
|
2418
2611
|
}
|
|
2419
2612
|
function resolveSkillLinkPath(provider, skillName, isGlobal, projectDir) {
|
|
2420
|
-
const skillDir = isGlobal ? provider.pathSkills :
|
|
2421
|
-
return
|
|
2613
|
+
const skillDir = isGlobal ? provider.pathSkills : join6(projectDir, provider.pathProjectSkills);
|
|
2614
|
+
return join6(skillDir, skillName);
|
|
2422
2615
|
}
|
|
2423
2616
|
async function snapshotConfigs(paths) {
|
|
2424
2617
|
const snapshots = /* @__PURE__ */ new Map();
|
|
@@ -2435,21 +2628,21 @@ async function snapshotConfigs(paths) {
|
|
|
2435
2628
|
async function restoreConfigSnapshots(snapshots) {
|
|
2436
2629
|
for (const [path, content] of snapshots) {
|
|
2437
2630
|
if (content === null) {
|
|
2438
|
-
await
|
|
2631
|
+
await rm3(path, { force: true });
|
|
2439
2632
|
continue;
|
|
2440
2633
|
}
|
|
2441
|
-
await mkdir4(
|
|
2634
|
+
await mkdir4(dirname5(path), { recursive: true });
|
|
2442
2635
|
await writeFile7(path, content, "utf-8");
|
|
2443
2636
|
}
|
|
2444
2637
|
}
|
|
2445
2638
|
async function snapshotSkillState(providerTargets, operation, projectDir, backupRoot) {
|
|
2446
2639
|
const skillName = operation.skillName;
|
|
2447
2640
|
const isGlobal = operation.isGlobal ?? true;
|
|
2448
|
-
const canonicalPath =
|
|
2641
|
+
const canonicalPath = join6(CANONICAL_SKILLS_DIR2, skillName);
|
|
2449
2642
|
const canonicalExisted = existsSync13(canonicalPath);
|
|
2450
|
-
const canonicalBackupPath =
|
|
2643
|
+
const canonicalBackupPath = join6(backupRoot, "canonical", skillName);
|
|
2451
2644
|
if (canonicalExisted) {
|
|
2452
|
-
await mkdir4(
|
|
2645
|
+
await mkdir4(dirname5(canonicalBackupPath), { recursive: true });
|
|
2453
2646
|
await cp2(canonicalPath, canonicalBackupPath, { recursive: true });
|
|
2454
2647
|
}
|
|
2455
2648
|
const pathSnapshots = [];
|
|
@@ -2468,8 +2661,8 @@ async function snapshotSkillState(providerTargets, operation, projectDir, backup
|
|
|
2468
2661
|
});
|
|
2469
2662
|
continue;
|
|
2470
2663
|
}
|
|
2471
|
-
const backupPath =
|
|
2472
|
-
await mkdir4(
|
|
2664
|
+
const backupPath = join6(backupRoot, "links", provider.id, `${skillName}-${basename2(linkPath)}`);
|
|
2665
|
+
await mkdir4(dirname5(backupPath), { recursive: true });
|
|
2473
2666
|
if (stat.isDirectory()) {
|
|
2474
2667
|
await cp2(linkPath, backupPath, { recursive: true });
|
|
2475
2668
|
pathSnapshots.push({ linkPath, state: "directory", backupPath });
|
|
@@ -2489,16 +2682,16 @@ async function snapshotSkillState(providerTargets, operation, projectDir, backup
|
|
|
2489
2682
|
}
|
|
2490
2683
|
async function restoreSkillSnapshot(snapshot) {
|
|
2491
2684
|
if (existsSync13(snapshot.canonicalPath)) {
|
|
2492
|
-
await
|
|
2685
|
+
await rm3(snapshot.canonicalPath, { recursive: true, force: true });
|
|
2493
2686
|
}
|
|
2494
2687
|
if (snapshot.canonicalExisted && snapshot.canonicalBackupPath && existsSync13(snapshot.canonicalBackupPath)) {
|
|
2495
|
-
await mkdir4(
|
|
2688
|
+
await mkdir4(dirname5(snapshot.canonicalPath), { recursive: true });
|
|
2496
2689
|
await cp2(snapshot.canonicalBackupPath, snapshot.canonicalPath, { recursive: true });
|
|
2497
2690
|
}
|
|
2498
2691
|
for (const pathSnapshot of snapshot.pathSnapshots) {
|
|
2499
|
-
await
|
|
2692
|
+
await rm3(pathSnapshot.linkPath, { recursive: true, force: true });
|
|
2500
2693
|
if (pathSnapshot.state === "missing") continue;
|
|
2501
|
-
await mkdir4(
|
|
2694
|
+
await mkdir4(dirname5(pathSnapshot.linkPath), { recursive: true });
|
|
2502
2695
|
if (pathSnapshot.state === "symlink" && pathSnapshot.symlinkTarget) {
|
|
2503
2696
|
const linkType = process.platform === "win32" ? "junction" : "dir";
|
|
2504
2697
|
await symlink2(pathSnapshot.symlinkTarget, pathSnapshot.linkPath, linkType);
|
|
@@ -2529,7 +2722,7 @@ async function installBatchWithRollback(options) {
|
|
|
2529
2722
|
return paths;
|
|
2530
2723
|
});
|
|
2531
2724
|
const configSnapshots = await snapshotConfigs(configPaths);
|
|
2532
|
-
const backupRoot =
|
|
2725
|
+
const backupRoot = join6(
|
|
2533
2726
|
tmpdir(),
|
|
2534
2727
|
`caamp-skill-backup-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`
|
|
2535
2728
|
);
|
|
@@ -2578,7 +2771,7 @@ async function installBatchWithRollback(options) {
|
|
|
2578
2771
|
}
|
|
2579
2772
|
skillsApplied += 1;
|
|
2580
2773
|
}
|
|
2581
|
-
await
|
|
2774
|
+
await rm3(backupRoot, { recursive: true, force: true });
|
|
2582
2775
|
return {
|
|
2583
2776
|
success: true,
|
|
2584
2777
|
providerIds: providers.map((provider) => provider.id),
|
|
@@ -2608,7 +2801,7 @@ async function installBatchWithRollback(options) {
|
|
|
2608
2801
|
rollbackErrors.push(err instanceof Error ? err.message : String(err));
|
|
2609
2802
|
}
|
|
2610
2803
|
}
|
|
2611
|
-
await
|
|
2804
|
+
await rm3(backupRoot, { recursive: true, force: true });
|
|
2612
2805
|
return {
|
|
2613
2806
|
success: false,
|
|
2614
2807
|
providerIds: providers.map((provider) => provider.id),
|
|
@@ -2720,7 +2913,7 @@ async function updateInstructionsSingleOperation(providers, content, scope = "pr
|
|
|
2720
2913
|
};
|
|
2721
2914
|
for (const [filePath, action] of actions.entries()) {
|
|
2722
2915
|
const providersForFile = providers.filter((provider) => {
|
|
2723
|
-
const expectedPath = scope === "global" ?
|
|
2916
|
+
const expectedPath = scope === "global" ? join6(provider.pathGlobal, provider.instructFile) : join6(projectDir, provider.instructFile);
|
|
2724
2917
|
return expectedPath === filePath;
|
|
2725
2918
|
});
|
|
2726
2919
|
const fallback = groupedByFile.get(basename2(filePath)) ?? [];
|
|
@@ -2786,6 +2979,16 @@ async function configureProviderGlobalAndProject(provider, options) {
|
|
|
2786
2979
|
}
|
|
2787
2980
|
|
|
2788
2981
|
export {
|
|
2982
|
+
getPlatformLocations,
|
|
2983
|
+
getAgentsHome,
|
|
2984
|
+
getProjectAgentsDir,
|
|
2985
|
+
getCanonicalSkillsDir,
|
|
2986
|
+
getLockFilePath,
|
|
2987
|
+
resolveRegistryTemplatePath,
|
|
2988
|
+
resolveProviderConfigPath,
|
|
2989
|
+
resolvePreferredConfigScope,
|
|
2990
|
+
resolveProviderSkillsDir,
|
|
2991
|
+
buildSkillSubPathCandidates,
|
|
2789
2992
|
getAllProviders,
|
|
2790
2993
|
getProvider,
|
|
2791
2994
|
resolveAlias,
|
|
@@ -2803,6 +3006,7 @@ export {
|
|
|
2803
3006
|
detectAllProviders,
|
|
2804
3007
|
getInstalledProviders,
|
|
2805
3008
|
detectProjectProviders,
|
|
3009
|
+
resetDetectionCache,
|
|
2806
3010
|
parseSource,
|
|
2807
3011
|
isMarketplaceScoped,
|
|
2808
3012
|
installSkill,
|
|
@@ -2865,4 +3069,4 @@ export {
|
|
|
2865
3069
|
updateInstructionsSingleOperation,
|
|
2866
3070
|
configureProviderGlobalAndProject
|
|
2867
3071
|
};
|
|
2868
|
-
//# sourceMappingURL=chunk-
|
|
3072
|
+
//# sourceMappingURL=chunk-6HQDRJLS.js.map
|