@cleocode/caamp 1.1.3 → 1.3.0
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-7YV3KXEJ.js → chunk-O2YG5HT7.js} +250 -47
- package/dist/chunk-O2YG5HT7.js.map +1 -0
- package/dist/cli.js +768 -261
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +48 -6
- package/dist/index.js +17 -1
- package/package.json +1 -1
- package/dist/chunk-7YV3KXEJ.js.map +0 -1
|
@@ -1134,8 +1134,8 @@ async function linkToAgent(canonicalPath, provider, skillName, isGlobal, project
|
|
|
1134
1134
|
await mkdir2(targetSkillsDir, { recursive: true });
|
|
1135
1135
|
const linkPath = join4(targetSkillsDir, skillName);
|
|
1136
1136
|
if (existsSync8(linkPath)) {
|
|
1137
|
-
const
|
|
1138
|
-
if (
|
|
1137
|
+
const stat2 = lstatSync(linkPath);
|
|
1138
|
+
if (stat2.isSymbolicLink()) {
|
|
1139
1139
|
await rm(linkPath);
|
|
1140
1140
|
} else {
|
|
1141
1141
|
await rm(linkPath, { recursive: true });
|
|
@@ -1287,8 +1287,8 @@ async function snapshotSkillState(providerTargets, operation, projectDir, backup
|
|
|
1287
1287
|
pathSnapshots.push({ linkPath, state: "missing" });
|
|
1288
1288
|
continue;
|
|
1289
1289
|
}
|
|
1290
|
-
const
|
|
1291
|
-
if (
|
|
1290
|
+
const stat2 = lstatSync2(linkPath);
|
|
1291
|
+
if (stat2.isSymbolicLink()) {
|
|
1292
1292
|
pathSnapshots.push({
|
|
1293
1293
|
linkPath,
|
|
1294
1294
|
state: "symlink",
|
|
@@ -1298,7 +1298,7 @@ async function snapshotSkillState(providerTargets, operation, projectDir, backup
|
|
|
1298
1298
|
}
|
|
1299
1299
|
const backupPath = join5(backupRoot, "links", provider.id, `${skillName}-${basename(linkPath)}`);
|
|
1300
1300
|
await mkdir3(dirname4(backupPath), { recursive: true });
|
|
1301
|
-
if (
|
|
1301
|
+
if (stat2.isDirectory()) {
|
|
1302
1302
|
await cp2(linkPath, backupPath, { recursive: true });
|
|
1303
1303
|
pathSnapshots.push({ linkPath, state: "directory", backupPath });
|
|
1304
1304
|
continue;
|
|
@@ -1614,11 +1614,23 @@ async function configureProviderGlobalAndProject(provider, options) {
|
|
|
1614
1614
|
}
|
|
1615
1615
|
|
|
1616
1616
|
// src/core/lock-utils.ts
|
|
1617
|
-
import { open, readFile as readFile6, writeFile as writeFile6, mkdir as mkdir4, rm as rm3, rename } from "fs/promises";
|
|
1617
|
+
import { open, readFile as readFile6, writeFile as writeFile6, mkdir as mkdir4, rm as rm3, rename, stat } from "fs/promises";
|
|
1618
1618
|
import { existsSync as existsSync10 } from "fs";
|
|
1619
1619
|
var LOCK_GUARD_PATH = `${LOCK_FILE_PATH}.lock`;
|
|
1620
|
+
var STALE_LOCK_MS = 5e3;
|
|
1620
1621
|
function sleep(ms) {
|
|
1621
|
-
return new Promise((
|
|
1622
|
+
return new Promise((resolve4) => setTimeout(resolve4, ms));
|
|
1623
|
+
}
|
|
1624
|
+
async function removeStaleLock() {
|
|
1625
|
+
try {
|
|
1626
|
+
const info = await stat(LOCK_GUARD_PATH);
|
|
1627
|
+
if (Date.now() - info.mtimeMs > STALE_LOCK_MS) {
|
|
1628
|
+
await rm3(LOCK_GUARD_PATH, { force: true });
|
|
1629
|
+
return true;
|
|
1630
|
+
}
|
|
1631
|
+
} catch {
|
|
1632
|
+
}
|
|
1633
|
+
return false;
|
|
1622
1634
|
}
|
|
1623
1635
|
async function acquireLockGuard(retries = 40, delayMs = 25) {
|
|
1624
1636
|
await mkdir4(AGENTS_HOME, { recursive: true });
|
|
@@ -1631,6 +1643,10 @@ async function acquireLockGuard(retries = 40, delayMs = 25) {
|
|
|
1631
1643
|
if (!(error instanceof Error) || !("code" in error) || error.code !== "EEXIST") {
|
|
1632
1644
|
throw error;
|
|
1633
1645
|
}
|
|
1646
|
+
if (attempt === 0) {
|
|
1647
|
+
const removed = await removeStaleLock();
|
|
1648
|
+
if (removed) continue;
|
|
1649
|
+
}
|
|
1634
1650
|
await sleep(delayMs);
|
|
1635
1651
|
}
|
|
1636
1652
|
}
|
|
@@ -1708,6 +1724,135 @@ async function getLastSelectedAgents() {
|
|
|
1708
1724
|
return lock.lastSelectedAgents;
|
|
1709
1725
|
}
|
|
1710
1726
|
|
|
1727
|
+
// src/core/mcp/cleo.ts
|
|
1728
|
+
import { execFileSync as execFileSync2 } from "child_process";
|
|
1729
|
+
import { existsSync as existsSync11 } from "fs";
|
|
1730
|
+
import { homedir as homedir2 } from "os";
|
|
1731
|
+
import { isAbsolute as isAbsolute2, resolve as resolve3 } from "path";
|
|
1732
|
+
var CLEO_SERVER_NAMES = {
|
|
1733
|
+
stable: "cleo",
|
|
1734
|
+
beta: "cleo-beta",
|
|
1735
|
+
dev: "cleo-dev"
|
|
1736
|
+
};
|
|
1737
|
+
var CLEO_MCP_NPM_PACKAGE = "@cleocode/cleo";
|
|
1738
|
+
var CLEO_DEV_DIR_DEFAULT = "~/.cleo-dev";
|
|
1739
|
+
function normalizeCleoChannel(value) {
|
|
1740
|
+
if (!value || value.trim() === "") return "stable";
|
|
1741
|
+
const normalized = value.trim().toLowerCase();
|
|
1742
|
+
if (normalized === "stable" || normalized === "beta" || normalized === "dev") {
|
|
1743
|
+
return normalized;
|
|
1744
|
+
}
|
|
1745
|
+
throw new Error(`Invalid channel "${value}". Expected stable, beta, or dev.`);
|
|
1746
|
+
}
|
|
1747
|
+
function resolveCleoServerName(channel) {
|
|
1748
|
+
return CLEO_SERVER_NAMES[channel];
|
|
1749
|
+
}
|
|
1750
|
+
function resolveChannelFromServerName(serverName) {
|
|
1751
|
+
if (serverName === CLEO_SERVER_NAMES.stable) return "stable";
|
|
1752
|
+
if (serverName === CLEO_SERVER_NAMES.beta) return "beta";
|
|
1753
|
+
if (serverName === CLEO_SERVER_NAMES.dev) return "dev";
|
|
1754
|
+
return null;
|
|
1755
|
+
}
|
|
1756
|
+
function splitCommand(command, explicitArgs = []) {
|
|
1757
|
+
if (explicitArgs.length > 0) {
|
|
1758
|
+
return { command, args: explicitArgs };
|
|
1759
|
+
}
|
|
1760
|
+
const parts = command.trim().split(/\s+/);
|
|
1761
|
+
const binary = parts[0] ?? "";
|
|
1762
|
+
if (!binary) {
|
|
1763
|
+
throw new Error("Command is required for dev channel.");
|
|
1764
|
+
}
|
|
1765
|
+
return {
|
|
1766
|
+
command: binary,
|
|
1767
|
+
args: parts.slice(1)
|
|
1768
|
+
};
|
|
1769
|
+
}
|
|
1770
|
+
function normalizeEnv(env, channel, cleoDir) {
|
|
1771
|
+
const result = { ...env ?? {} };
|
|
1772
|
+
if (channel === "dev" && !result.CLEO_DIR) {
|
|
1773
|
+
result.CLEO_DIR = cleoDir ?? CLEO_DEV_DIR_DEFAULT;
|
|
1774
|
+
}
|
|
1775
|
+
return Object.keys(result).length > 0 ? result : void 0;
|
|
1776
|
+
}
|
|
1777
|
+
function resolvePackageSpec(channel, version) {
|
|
1778
|
+
const tag = version?.trim() || (channel === "stable" ? "latest" : "beta");
|
|
1779
|
+
return `${CLEO_MCP_NPM_PACKAGE}@${tag}`;
|
|
1780
|
+
}
|
|
1781
|
+
function buildCleoProfile(options) {
|
|
1782
|
+
const channel = options.channel;
|
|
1783
|
+
const serverName = resolveCleoServerName(channel);
|
|
1784
|
+
if (channel === "dev") {
|
|
1785
|
+
if (!options.command || options.command.trim() === "") {
|
|
1786
|
+
throw new Error("Dev channel requires --command.");
|
|
1787
|
+
}
|
|
1788
|
+
const parsed = splitCommand(options.command, options.args ?? []);
|
|
1789
|
+
const env = normalizeEnv(options.env, channel, options.cleoDir);
|
|
1790
|
+
return {
|
|
1791
|
+
channel,
|
|
1792
|
+
serverName,
|
|
1793
|
+
config: {
|
|
1794
|
+
command: parsed.command,
|
|
1795
|
+
args: parsed.args,
|
|
1796
|
+
...env ? { env } : {}
|
|
1797
|
+
}
|
|
1798
|
+
};
|
|
1799
|
+
}
|
|
1800
|
+
const packageSpec = resolvePackageSpec(channel, options.version);
|
|
1801
|
+
return {
|
|
1802
|
+
channel,
|
|
1803
|
+
serverName,
|
|
1804
|
+
packageSpec,
|
|
1805
|
+
config: {
|
|
1806
|
+
command: "npx",
|
|
1807
|
+
args: ["-y", packageSpec, "cleo-mcp"]
|
|
1808
|
+
}
|
|
1809
|
+
};
|
|
1810
|
+
}
|
|
1811
|
+
function expandHome(pathValue) {
|
|
1812
|
+
if (pathValue === "~") return homedir2();
|
|
1813
|
+
if (pathValue.startsWith("~/")) {
|
|
1814
|
+
return resolve3(homedir2(), pathValue.slice(2));
|
|
1815
|
+
}
|
|
1816
|
+
return pathValue;
|
|
1817
|
+
}
|
|
1818
|
+
function checkCommandReachability(command) {
|
|
1819
|
+
const hasPathSeparator = command.includes("/") || command.includes("\\");
|
|
1820
|
+
if (hasPathSeparator || command.startsWith("~")) {
|
|
1821
|
+
const expanded = expandHome(command);
|
|
1822
|
+
const candidate = isAbsolute2(expanded) ? expanded : resolve3(process.cwd(), expanded);
|
|
1823
|
+
if (existsSync11(candidate)) {
|
|
1824
|
+
return { reachable: true, method: "path", detail: candidate };
|
|
1825
|
+
}
|
|
1826
|
+
return { reachable: false, method: "path", detail: candidate };
|
|
1827
|
+
}
|
|
1828
|
+
try {
|
|
1829
|
+
const lookup = process.platform === "win32" ? "where" : "which";
|
|
1830
|
+
execFileSync2(lookup, [command], { stdio: "pipe" });
|
|
1831
|
+
return { reachable: true, method: "lookup", detail: command };
|
|
1832
|
+
} catch {
|
|
1833
|
+
return { reachable: false, method: "lookup", detail: command };
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
function parseEnvAssignments(values) {
|
|
1837
|
+
const env = {};
|
|
1838
|
+
for (const value of values) {
|
|
1839
|
+
const idx = value.indexOf("=");
|
|
1840
|
+
if (idx <= 0) {
|
|
1841
|
+
throw new Error(`Invalid --env value "${value}". Use KEY=value.`);
|
|
1842
|
+
}
|
|
1843
|
+
const key = value.slice(0, idx).trim();
|
|
1844
|
+
const val = value.slice(idx + 1).trim();
|
|
1845
|
+
if (!key) {
|
|
1846
|
+
throw new Error(`Invalid --env value "${value}". Key cannot be empty.`);
|
|
1847
|
+
}
|
|
1848
|
+
env[key] = val;
|
|
1849
|
+
}
|
|
1850
|
+
return env;
|
|
1851
|
+
}
|
|
1852
|
+
function isCleoSource(source) {
|
|
1853
|
+
return source.trim().toLowerCase() === "cleo";
|
|
1854
|
+
}
|
|
1855
|
+
|
|
1711
1856
|
// src/core/sources/parser.ts
|
|
1712
1857
|
var GITHUB_SHORTHAND = /^([a-zA-Z0-9_.-]+)\/([a-zA-Z0-9_.-]+)(?:\/(.+))?$/;
|
|
1713
1858
|
var GITHUB_URL = /^https?:\/\/(?:www\.)?github\.com\/([^/]+)\/([^/]+)(?:\/(?:tree|blob)\/([^/]+)(?:\/(.+))?)?/;
|
|
@@ -1715,7 +1860,12 @@ var GITLAB_URL = /^https?:\/\/(?:www\.)?gitlab\.com\/([^/]+)\/([^/]+)(?:\/-\/(?:
|
|
|
1715
1860
|
var HTTP_URL = /^https?:\/\//;
|
|
1716
1861
|
var NPM_SCOPED = /^@[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+$/;
|
|
1717
1862
|
var NPM_PACKAGE = /^[a-zA-Z0-9_.-]+$/;
|
|
1863
|
+
var LIBRARY_SKILL = /^(@[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+|[a-zA-Z0-9_.-]+):([a-zA-Z0-9_.-]+)$/;
|
|
1718
1864
|
function inferName(source, type) {
|
|
1865
|
+
if (type === "library") {
|
|
1866
|
+
const match = source.match(LIBRARY_SKILL);
|
|
1867
|
+
return match?.[2] ?? source;
|
|
1868
|
+
}
|
|
1719
1869
|
if (type === "remote") {
|
|
1720
1870
|
try {
|
|
1721
1871
|
const url = new URL(source);
|
|
@@ -1829,6 +1979,18 @@ function parseSource(input) {
|
|
|
1829
1979
|
path
|
|
1830
1980
|
};
|
|
1831
1981
|
}
|
|
1982
|
+
const libraryMatch = input.match(LIBRARY_SKILL);
|
|
1983
|
+
if (libraryMatch) {
|
|
1984
|
+
return {
|
|
1985
|
+
type: "library",
|
|
1986
|
+
value: input,
|
|
1987
|
+
inferredName: inferName(input, "library"),
|
|
1988
|
+
owner: libraryMatch[1],
|
|
1989
|
+
// This will be the package name, e.g. @cleocode/ct-skills
|
|
1990
|
+
repo: libraryMatch[2]
|
|
1991
|
+
// This will be the skill name, e.g. ct-research-agent
|
|
1992
|
+
};
|
|
1993
|
+
}
|
|
1832
1994
|
if (NPM_SCOPED.test(input)) {
|
|
1833
1995
|
return {
|
|
1834
1996
|
type: "package",
|
|
@@ -2105,7 +2267,7 @@ var MarketplaceClient = class {
|
|
|
2105
2267
|
|
|
2106
2268
|
// src/core/skills/library-loader.ts
|
|
2107
2269
|
import { createRequire } from "module";
|
|
2108
|
-
import { existsSync as
|
|
2270
|
+
import { existsSync as existsSync12, readdirSync, readFileSync as readFileSync2 } from "fs";
|
|
2109
2271
|
import { basename as basename2, dirname as dirname5, join as join6 } from "path";
|
|
2110
2272
|
var require2 = createRequire(import.meta.url);
|
|
2111
2273
|
function loadLibraryFromModule(root) {
|
|
@@ -2155,7 +2317,7 @@ function loadLibraryFromModule(root) {
|
|
|
2155
2317
|
}
|
|
2156
2318
|
function buildLibraryFromFiles(root) {
|
|
2157
2319
|
const catalogPath = join6(root, "skills.json");
|
|
2158
|
-
if (!
|
|
2320
|
+
if (!existsSync12(catalogPath)) {
|
|
2159
2321
|
throw new Error(`No skills.json found at ${root}`);
|
|
2160
2322
|
}
|
|
2161
2323
|
const catalogData = JSON.parse(readFileSync2(catalogPath, "utf-8"));
|
|
@@ -2163,7 +2325,7 @@ function buildLibraryFromFiles(root) {
|
|
|
2163
2325
|
const version = catalogData.version ?? "0.0.0";
|
|
2164
2326
|
const manifestPath = join6(root, "skills", "manifest.json");
|
|
2165
2327
|
let manifest;
|
|
2166
|
-
if (
|
|
2328
|
+
if (existsSync12(manifestPath)) {
|
|
2167
2329
|
manifest = JSON.parse(readFileSync2(manifestPath, "utf-8"));
|
|
2168
2330
|
} else {
|
|
2169
2331
|
manifest = {
|
|
@@ -2175,7 +2337,7 @@ function buildLibraryFromFiles(root) {
|
|
|
2175
2337
|
}
|
|
2176
2338
|
const profilesDir = join6(root, "profiles");
|
|
2177
2339
|
const profiles = /* @__PURE__ */ new Map();
|
|
2178
|
-
if (
|
|
2340
|
+
if (existsSync12(profilesDir)) {
|
|
2179
2341
|
for (const file of readdirSync(profilesDir)) {
|
|
2180
2342
|
if (!file.endsWith(".json")) continue;
|
|
2181
2343
|
try {
|
|
@@ -2224,7 +2386,7 @@ function buildLibraryFromFiles(root) {
|
|
|
2224
2386
|
return resolveDeps([...new Set(skills)]);
|
|
2225
2387
|
}
|
|
2226
2388
|
function discoverFiles(dir, ext) {
|
|
2227
|
-
if (!
|
|
2389
|
+
if (!existsSync12(dir)) return [];
|
|
2228
2390
|
return readdirSync(dir).filter((f) => f.endsWith(ext)).map((f) => basename2(f, ext));
|
|
2229
2391
|
}
|
|
2230
2392
|
const library = {
|
|
@@ -2248,7 +2410,7 @@ function buildLibraryFromFiles(root) {
|
|
|
2248
2410
|
getSkillDir: getSkillDir2,
|
|
2249
2411
|
readSkillContent(name) {
|
|
2250
2412
|
const skillPath = library.getSkillPath(name);
|
|
2251
|
-
if (!
|
|
2413
|
+
if (!existsSync12(skillPath)) {
|
|
2252
2414
|
throw new Error(`Skill content not found: ${skillPath}`);
|
|
2253
2415
|
}
|
|
2254
2416
|
return readFileSync2(skillPath, "utf-8");
|
|
@@ -2279,7 +2441,7 @@ function buildLibraryFromFiles(root) {
|
|
|
2279
2441
|
},
|
|
2280
2442
|
getSharedResourcePath(name) {
|
|
2281
2443
|
const resourcePath = join6(root, "skills", "_shared", `${name}.md`);
|
|
2282
|
-
return
|
|
2444
|
+
return existsSync12(resourcePath) ? resourcePath : void 0;
|
|
2283
2445
|
},
|
|
2284
2446
|
readSharedResource(name) {
|
|
2285
2447
|
const resourcePath = library.getSharedResourcePath(name);
|
|
@@ -2293,9 +2455,9 @@ function buildLibraryFromFiles(root) {
|
|
|
2293
2455
|
},
|
|
2294
2456
|
getProtocolPath(name) {
|
|
2295
2457
|
const rootPath = join6(root, "protocols", `${name}.md`);
|
|
2296
|
-
if (
|
|
2458
|
+
if (existsSync12(rootPath)) return rootPath;
|
|
2297
2459
|
const skillsPath = join6(root, "skills", "protocols", `${name}.md`);
|
|
2298
|
-
return
|
|
2460
|
+
return existsSync12(skillsPath) ? skillsPath : void 0;
|
|
2299
2461
|
},
|
|
2300
2462
|
readProtocol(name) {
|
|
2301
2463
|
const protocolPath = library.getProtocolPath(name);
|
|
@@ -2321,7 +2483,7 @@ function buildLibraryFromFiles(root) {
|
|
|
2321
2483
|
issues.push({ level: "warn", field: "version", message: "Missing version" });
|
|
2322
2484
|
}
|
|
2323
2485
|
const skillPath = join6(root, entry.path);
|
|
2324
|
-
if (!
|
|
2486
|
+
if (!existsSync12(skillPath)) {
|
|
2325
2487
|
issues.push({ level: "error", field: "path", message: `SKILL.md not found at ${entry.path}` });
|
|
2326
2488
|
}
|
|
2327
2489
|
return {
|
|
@@ -2376,7 +2538,7 @@ __export(catalog_exports, {
|
|
|
2376
2538
|
validateAll: () => validateAll,
|
|
2377
2539
|
validateSkillFrontmatter: () => validateSkillFrontmatter
|
|
2378
2540
|
});
|
|
2379
|
-
import { existsSync as
|
|
2541
|
+
import { existsSync as existsSync13 } from "fs";
|
|
2380
2542
|
import { join as join7 } from "path";
|
|
2381
2543
|
var _library = null;
|
|
2382
2544
|
function registerSkillLibrary(library) {
|
|
@@ -2384,7 +2546,7 @@ function registerSkillLibrary(library) {
|
|
|
2384
2546
|
}
|
|
2385
2547
|
function registerSkillLibraryFromPath(root) {
|
|
2386
2548
|
const indexPath = join7(root, "index.js");
|
|
2387
|
-
if (
|
|
2549
|
+
if (existsSync13(indexPath)) {
|
|
2388
2550
|
_library = loadLibraryFromModule(root);
|
|
2389
2551
|
return;
|
|
2390
2552
|
}
|
|
@@ -2395,31 +2557,18 @@ function clearRegisteredLibrary() {
|
|
|
2395
2557
|
}
|
|
2396
2558
|
function discoverLibrary() {
|
|
2397
2559
|
const envPath = process.env["CAAMP_SKILL_LIBRARY"];
|
|
2398
|
-
if (envPath &&
|
|
2560
|
+
if (envPath && existsSync13(envPath)) {
|
|
2399
2561
|
try {
|
|
2400
2562
|
const indexPath = join7(envPath, "index.js");
|
|
2401
|
-
if (
|
|
2563
|
+
if (existsSync13(indexPath)) {
|
|
2402
2564
|
return loadLibraryFromModule(envPath);
|
|
2403
2565
|
}
|
|
2404
|
-
if (
|
|
2566
|
+
if (existsSync13(join7(envPath, "skills.json"))) {
|
|
2405
2567
|
return buildLibraryFromFiles(envPath);
|
|
2406
2568
|
}
|
|
2407
2569
|
} catch {
|
|
2408
2570
|
}
|
|
2409
2571
|
}
|
|
2410
|
-
const canonicalPath = join7(getAgentsHome(), "skill-library");
|
|
2411
|
-
if (existsSync12(canonicalPath)) {
|
|
2412
|
-
try {
|
|
2413
|
-
const indexPath = join7(canonicalPath, "index.js");
|
|
2414
|
-
if (existsSync12(indexPath)) {
|
|
2415
|
-
return loadLibraryFromModule(canonicalPath);
|
|
2416
|
-
}
|
|
2417
|
-
if (existsSync12(join7(canonicalPath, "skills.json"))) {
|
|
2418
|
-
return buildLibraryFromFiles(canonicalPath);
|
|
2419
|
-
}
|
|
2420
|
-
} catch {
|
|
2421
|
-
}
|
|
2422
|
-
}
|
|
2423
2572
|
return null;
|
|
2424
2573
|
}
|
|
2425
2574
|
function getLibrary() {
|
|
@@ -2522,7 +2671,7 @@ function getLibraryRoot() {
|
|
|
2522
2671
|
|
|
2523
2672
|
// src/core/skills/discovery.ts
|
|
2524
2673
|
import { readFile as readFile7, readdir } from "fs/promises";
|
|
2525
|
-
import { existsSync as
|
|
2674
|
+
import { existsSync as existsSync14 } from "fs";
|
|
2526
2675
|
import { join as join8 } from "path";
|
|
2527
2676
|
import matter from "gray-matter";
|
|
2528
2677
|
async function parseSkillFile(filePath) {
|
|
@@ -2548,7 +2697,7 @@ async function parseSkillFile(filePath) {
|
|
|
2548
2697
|
}
|
|
2549
2698
|
async function discoverSkill(skillDir) {
|
|
2550
2699
|
const skillFile = join8(skillDir, "SKILL.md");
|
|
2551
|
-
if (!
|
|
2700
|
+
if (!existsSync14(skillFile)) return null;
|
|
2552
2701
|
const metadata = await parseSkillFile(skillFile);
|
|
2553
2702
|
if (!metadata) return null;
|
|
2554
2703
|
return {
|
|
@@ -2559,7 +2708,7 @@ async function discoverSkill(skillDir) {
|
|
|
2559
2708
|
};
|
|
2560
2709
|
}
|
|
2561
2710
|
async function discoverSkills(rootDir) {
|
|
2562
|
-
if (!
|
|
2711
|
+
if (!existsSync14(rootDir)) return [];
|
|
2563
2712
|
const entries = await readdir(rootDir, { withFileTypes: true });
|
|
2564
2713
|
const skills = [];
|
|
2565
2714
|
for (const entry of entries) {
|
|
@@ -2589,6 +2738,9 @@ async function discoverSkillsMulti(dirs) {
|
|
|
2589
2738
|
|
|
2590
2739
|
// src/core/skills/lock.ts
|
|
2591
2740
|
import { simpleGit } from "simple-git";
|
|
2741
|
+
import { execFile } from "child_process";
|
|
2742
|
+
import { promisify } from "util";
|
|
2743
|
+
var execFileAsync = promisify(execFile);
|
|
2592
2744
|
async function recordSkillInstall(skillName, scopedName, source, sourceType, agents, canonicalPath, isGlobal, projectDir, version) {
|
|
2593
2745
|
await updateLockFile((lock) => {
|
|
2594
2746
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2635,13 +2787,21 @@ async function fetchLatestSha(repoUrl, ref) {
|
|
|
2635
2787
|
return null;
|
|
2636
2788
|
}
|
|
2637
2789
|
}
|
|
2790
|
+
async function fetchLatestPackageVersion(packageName) {
|
|
2791
|
+
try {
|
|
2792
|
+
const { stdout } = await execFileAsync("npm", ["view", packageName, "version"]);
|
|
2793
|
+
return stdout.trim() || null;
|
|
2794
|
+
} catch {
|
|
2795
|
+
return null;
|
|
2796
|
+
}
|
|
2797
|
+
}
|
|
2638
2798
|
async function checkSkillUpdate(skillName) {
|
|
2639
2799
|
const lock = await readLockFile();
|
|
2640
2800
|
const entry = lock.skills[skillName];
|
|
2641
2801
|
if (!entry) {
|
|
2642
2802
|
return { hasUpdate: false, status: "unknown" };
|
|
2643
2803
|
}
|
|
2644
|
-
if (entry.sourceType !== "github" && entry.sourceType !== "gitlab") {
|
|
2804
|
+
if (entry.sourceType !== "github" && entry.sourceType !== "gitlab" && entry.sourceType !== "library") {
|
|
2645
2805
|
return {
|
|
2646
2806
|
hasUpdate: false,
|
|
2647
2807
|
currentVersion: entry.version,
|
|
@@ -2649,7 +2809,33 @@ async function checkSkillUpdate(skillName) {
|
|
|
2649
2809
|
};
|
|
2650
2810
|
}
|
|
2651
2811
|
const parsed = parseSource(entry.source);
|
|
2652
|
-
if (!parsed.owner
|
|
2812
|
+
if (!parsed.owner) {
|
|
2813
|
+
return {
|
|
2814
|
+
hasUpdate: false,
|
|
2815
|
+
currentVersion: entry.version,
|
|
2816
|
+
status: "unknown"
|
|
2817
|
+
};
|
|
2818
|
+
}
|
|
2819
|
+
if (entry.sourceType === "library") {
|
|
2820
|
+
const packageName = parsed.owner;
|
|
2821
|
+
const latestVersion = await fetchLatestPackageVersion(packageName);
|
|
2822
|
+
if (!latestVersion) {
|
|
2823
|
+
return {
|
|
2824
|
+
hasUpdate: false,
|
|
2825
|
+
currentVersion: entry.version,
|
|
2826
|
+
status: "unknown"
|
|
2827
|
+
};
|
|
2828
|
+
}
|
|
2829
|
+
const currentVersion2 = entry.version;
|
|
2830
|
+
const hasUpdate2 = !currentVersion2 || currentVersion2 !== latestVersion;
|
|
2831
|
+
return {
|
|
2832
|
+
hasUpdate: hasUpdate2,
|
|
2833
|
+
currentVersion: currentVersion2 ?? "unknown",
|
|
2834
|
+
latestVersion,
|
|
2835
|
+
status: hasUpdate2 ? "update-available" : "up-to-date"
|
|
2836
|
+
};
|
|
2837
|
+
}
|
|
2838
|
+
if (!parsed.repo) {
|
|
2653
2839
|
return {
|
|
2654
2840
|
hasUpdate: false,
|
|
2655
2841
|
currentVersion: entry.version,
|
|
@@ -2675,6 +2861,15 @@ async function checkSkillUpdate(skillName) {
|
|
|
2675
2861
|
status: hasUpdate ? "update-available" : "up-to-date"
|
|
2676
2862
|
};
|
|
2677
2863
|
}
|
|
2864
|
+
async function checkAllSkillUpdates() {
|
|
2865
|
+
const lock = await readLockFile();
|
|
2866
|
+
const skillNames = Object.keys(lock.skills);
|
|
2867
|
+
const results = {};
|
|
2868
|
+
await Promise.all(skillNames.map(async (name) => {
|
|
2869
|
+
results[name] = await checkSkillUpdate(name);
|
|
2870
|
+
}));
|
|
2871
|
+
return results;
|
|
2872
|
+
}
|
|
2678
2873
|
|
|
2679
2874
|
// src/core/skills/recommendation.ts
|
|
2680
2875
|
var RECOMMENDATION_ERROR_CODES = {
|
|
@@ -2944,7 +3139,7 @@ async function recommendSkills2(query, criteria, options = {}) {
|
|
|
2944
3139
|
}
|
|
2945
3140
|
|
|
2946
3141
|
// src/core/skills/audit/scanner.ts
|
|
2947
|
-
import { existsSync as
|
|
3142
|
+
import { existsSync as existsSync15 } from "fs";
|
|
2948
3143
|
import { readFile as readFile8 } from "fs/promises";
|
|
2949
3144
|
|
|
2950
3145
|
// src/core/skills/audit/rules.ts
|
|
@@ -3324,7 +3519,7 @@ var SEVERITY_WEIGHTS = {
|
|
|
3324
3519
|
info: 0
|
|
3325
3520
|
};
|
|
3326
3521
|
async function scanFile(filePath, rules) {
|
|
3327
|
-
if (!
|
|
3522
|
+
if (!existsSync15(filePath)) {
|
|
3328
3523
|
return { file: filePath, findings: [], score: 100, passed: true };
|
|
3329
3524
|
}
|
|
3330
3525
|
const content = await readFile8(filePath, "utf-8");
|
|
@@ -3357,13 +3552,13 @@ async function scanFile(filePath, rules) {
|
|
|
3357
3552
|
async function scanDirectory(dirPath) {
|
|
3358
3553
|
const { readdir: readdir2 } = await import("fs/promises");
|
|
3359
3554
|
const { join: join9 } = await import("path");
|
|
3360
|
-
if (!
|
|
3555
|
+
if (!existsSync15(dirPath)) return [];
|
|
3361
3556
|
const entries = await readdir2(dirPath, { withFileTypes: true });
|
|
3362
3557
|
const results = [];
|
|
3363
3558
|
for (const entry of entries) {
|
|
3364
3559
|
if (entry.isDirectory() || entry.isSymbolicLink()) {
|
|
3365
3560
|
const skillFile = join9(dirPath, entry.name, "SKILL.md");
|
|
3366
|
-
if (
|
|
3561
|
+
if (existsSync15(skillFile)) {
|
|
3367
3562
|
results.push(await scanFile(skillFile));
|
|
3368
3563
|
}
|
|
3369
3564
|
}
|
|
@@ -3416,7 +3611,7 @@ function toSarif(results) {
|
|
|
3416
3611
|
|
|
3417
3612
|
// src/core/skills/validator.ts
|
|
3418
3613
|
import { readFile as readFile9 } from "fs/promises";
|
|
3419
|
-
import { existsSync as
|
|
3614
|
+
import { existsSync as existsSync16 } from "fs";
|
|
3420
3615
|
import matter2 from "gray-matter";
|
|
3421
3616
|
var RESERVED_NAMES = [
|
|
3422
3617
|
"anthropic",
|
|
@@ -3437,7 +3632,7 @@ var WARN_BODY_LINES = 500;
|
|
|
3437
3632
|
var WARN_DESCRIPTION_LENGTH = 50;
|
|
3438
3633
|
async function validateSkill(filePath) {
|
|
3439
3634
|
const issues = [];
|
|
3440
|
-
if (!
|
|
3635
|
+
if (!existsSync16(filePath)) {
|
|
3441
3636
|
return {
|
|
3442
3637
|
valid: false,
|
|
3443
3638
|
issues: [{ level: "error", field: "file", message: "File does not exist" }],
|
|
@@ -3628,6 +3823,13 @@ export {
|
|
|
3628
3823
|
getTrackedMcpServers,
|
|
3629
3824
|
saveLastSelectedAgents,
|
|
3630
3825
|
getLastSelectedAgents,
|
|
3826
|
+
normalizeCleoChannel,
|
|
3827
|
+
resolveCleoServerName,
|
|
3828
|
+
resolveChannelFromServerName,
|
|
3829
|
+
buildCleoProfile,
|
|
3830
|
+
checkCommandReachability,
|
|
3831
|
+
parseEnvAssignments,
|
|
3832
|
+
isCleoSource,
|
|
3631
3833
|
parseSource,
|
|
3632
3834
|
isMarketplaceScoped,
|
|
3633
3835
|
formatNetworkError,
|
|
@@ -3652,6 +3854,7 @@ export {
|
|
|
3652
3854
|
removeSkillFromLock,
|
|
3653
3855
|
getTrackedSkills,
|
|
3654
3856
|
checkSkillUpdate,
|
|
3857
|
+
checkAllSkillUpdates,
|
|
3655
3858
|
RECOMMENDATION_ERROR_CODES,
|
|
3656
3859
|
tokenizeCriteriaValue,
|
|
3657
3860
|
validateRecommendationCriteria,
|
|
@@ -3666,4 +3869,4 @@ export {
|
|
|
3666
3869
|
toSarif,
|
|
3667
3870
|
validateSkill
|
|
3668
3871
|
};
|
|
3669
|
-
//# sourceMappingURL=chunk-
|
|
3872
|
+
//# sourceMappingURL=chunk-O2YG5HT7.js.map
|