@cleocode/caamp 1.1.3 → 1.2.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-7YV3KXEJ.js → chunk-GR47LTXR.js} +89 -22
- package/dist/chunk-GR47LTXR.js.map +1 -0
- package/dist/cli.js +877 -268
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +16 -6
- package/dist/index.js +3 -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,12 +1614,24 @@ 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
1622
|
return new Promise((resolve3) => setTimeout(resolve3, ms));
|
|
1622
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;
|
|
1634
|
+
}
|
|
1623
1635
|
async function acquireLockGuard(retries = 40, delayMs = 25) {
|
|
1624
1636
|
await mkdir4(AGENTS_HOME, { recursive: true });
|
|
1625
1637
|
for (let attempt = 0; attempt < retries; attempt += 1) {
|
|
@@ -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
|
}
|
|
@@ -1715,7 +1731,12 @@ var GITLAB_URL = /^https?:\/\/(?:www\.)?gitlab\.com\/([^/]+)\/([^/]+)(?:\/-\/(?:
|
|
|
1715
1731
|
var HTTP_URL = /^https?:\/\//;
|
|
1716
1732
|
var NPM_SCOPED = /^@[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+$/;
|
|
1717
1733
|
var NPM_PACKAGE = /^[a-zA-Z0-9_.-]+$/;
|
|
1734
|
+
var LIBRARY_SKILL = /^(@[a-zA-Z0-9_.-]+\/[a-zA-Z0-9_.-]+|[a-zA-Z0-9_.-]+):([a-zA-Z0-9_.-]+)$/;
|
|
1718
1735
|
function inferName(source, type) {
|
|
1736
|
+
if (type === "library") {
|
|
1737
|
+
const match = source.match(LIBRARY_SKILL);
|
|
1738
|
+
return match?.[2] ?? source;
|
|
1739
|
+
}
|
|
1719
1740
|
if (type === "remote") {
|
|
1720
1741
|
try {
|
|
1721
1742
|
const url = new URL(source);
|
|
@@ -1829,6 +1850,18 @@ function parseSource(input) {
|
|
|
1829
1850
|
path
|
|
1830
1851
|
};
|
|
1831
1852
|
}
|
|
1853
|
+
const libraryMatch = input.match(LIBRARY_SKILL);
|
|
1854
|
+
if (libraryMatch) {
|
|
1855
|
+
return {
|
|
1856
|
+
type: "library",
|
|
1857
|
+
value: input,
|
|
1858
|
+
inferredName: inferName(input, "library"),
|
|
1859
|
+
owner: libraryMatch[1],
|
|
1860
|
+
// This will be the package name, e.g. @cleocode/ct-skills
|
|
1861
|
+
repo: libraryMatch[2]
|
|
1862
|
+
// This will be the skill name, e.g. ct-research-agent
|
|
1863
|
+
};
|
|
1864
|
+
}
|
|
1832
1865
|
if (NPM_SCOPED.test(input)) {
|
|
1833
1866
|
return {
|
|
1834
1867
|
type: "package",
|
|
@@ -2407,19 +2440,6 @@ function discoverLibrary() {
|
|
|
2407
2440
|
} catch {
|
|
2408
2441
|
}
|
|
2409
2442
|
}
|
|
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
2443
|
return null;
|
|
2424
2444
|
}
|
|
2425
2445
|
function getLibrary() {
|
|
@@ -2589,6 +2609,9 @@ async function discoverSkillsMulti(dirs) {
|
|
|
2589
2609
|
|
|
2590
2610
|
// src/core/skills/lock.ts
|
|
2591
2611
|
import { simpleGit } from "simple-git";
|
|
2612
|
+
import { execFile } from "child_process";
|
|
2613
|
+
import { promisify } from "util";
|
|
2614
|
+
var execFileAsync = promisify(execFile);
|
|
2592
2615
|
async function recordSkillInstall(skillName, scopedName, source, sourceType, agents, canonicalPath, isGlobal, projectDir, version) {
|
|
2593
2616
|
await updateLockFile((lock) => {
|
|
2594
2617
|
const now = (/* @__PURE__ */ new Date()).toISOString();
|
|
@@ -2635,13 +2658,21 @@ async function fetchLatestSha(repoUrl, ref) {
|
|
|
2635
2658
|
return null;
|
|
2636
2659
|
}
|
|
2637
2660
|
}
|
|
2661
|
+
async function fetchLatestPackageVersion(packageName) {
|
|
2662
|
+
try {
|
|
2663
|
+
const { stdout } = await execFileAsync("npm", ["view", packageName, "version"]);
|
|
2664
|
+
return stdout.trim() || null;
|
|
2665
|
+
} catch {
|
|
2666
|
+
return null;
|
|
2667
|
+
}
|
|
2668
|
+
}
|
|
2638
2669
|
async function checkSkillUpdate(skillName) {
|
|
2639
2670
|
const lock = await readLockFile();
|
|
2640
2671
|
const entry = lock.skills[skillName];
|
|
2641
2672
|
if (!entry) {
|
|
2642
2673
|
return { hasUpdate: false, status: "unknown" };
|
|
2643
2674
|
}
|
|
2644
|
-
if (entry.sourceType !== "github" && entry.sourceType !== "gitlab") {
|
|
2675
|
+
if (entry.sourceType !== "github" && entry.sourceType !== "gitlab" && entry.sourceType !== "library") {
|
|
2645
2676
|
return {
|
|
2646
2677
|
hasUpdate: false,
|
|
2647
2678
|
currentVersion: entry.version,
|
|
@@ -2649,7 +2680,33 @@ async function checkSkillUpdate(skillName) {
|
|
|
2649
2680
|
};
|
|
2650
2681
|
}
|
|
2651
2682
|
const parsed = parseSource(entry.source);
|
|
2652
|
-
if (!parsed.owner
|
|
2683
|
+
if (!parsed.owner) {
|
|
2684
|
+
return {
|
|
2685
|
+
hasUpdate: false,
|
|
2686
|
+
currentVersion: entry.version,
|
|
2687
|
+
status: "unknown"
|
|
2688
|
+
};
|
|
2689
|
+
}
|
|
2690
|
+
if (entry.sourceType === "library") {
|
|
2691
|
+
const packageName = parsed.owner;
|
|
2692
|
+
const latestVersion = await fetchLatestPackageVersion(packageName);
|
|
2693
|
+
if (!latestVersion) {
|
|
2694
|
+
return {
|
|
2695
|
+
hasUpdate: false,
|
|
2696
|
+
currentVersion: entry.version,
|
|
2697
|
+
status: "unknown"
|
|
2698
|
+
};
|
|
2699
|
+
}
|
|
2700
|
+
const currentVersion2 = entry.version;
|
|
2701
|
+
const hasUpdate2 = !currentVersion2 || currentVersion2 !== latestVersion;
|
|
2702
|
+
return {
|
|
2703
|
+
hasUpdate: hasUpdate2,
|
|
2704
|
+
currentVersion: currentVersion2 ?? "unknown",
|
|
2705
|
+
latestVersion,
|
|
2706
|
+
status: hasUpdate2 ? "update-available" : "up-to-date"
|
|
2707
|
+
};
|
|
2708
|
+
}
|
|
2709
|
+
if (!parsed.repo) {
|
|
2653
2710
|
return {
|
|
2654
2711
|
hasUpdate: false,
|
|
2655
2712
|
currentVersion: entry.version,
|
|
@@ -2675,6 +2732,15 @@ async function checkSkillUpdate(skillName) {
|
|
|
2675
2732
|
status: hasUpdate ? "update-available" : "up-to-date"
|
|
2676
2733
|
};
|
|
2677
2734
|
}
|
|
2735
|
+
async function checkAllSkillUpdates() {
|
|
2736
|
+
const lock = await readLockFile();
|
|
2737
|
+
const skillNames = Object.keys(lock.skills);
|
|
2738
|
+
const results = {};
|
|
2739
|
+
await Promise.all(skillNames.map(async (name) => {
|
|
2740
|
+
results[name] = await checkSkillUpdate(name);
|
|
2741
|
+
}));
|
|
2742
|
+
return results;
|
|
2743
|
+
}
|
|
2678
2744
|
|
|
2679
2745
|
// src/core/skills/recommendation.ts
|
|
2680
2746
|
var RECOMMENDATION_ERROR_CODES = {
|
|
@@ -3652,6 +3718,7 @@ export {
|
|
|
3652
3718
|
removeSkillFromLock,
|
|
3653
3719
|
getTrackedSkills,
|
|
3654
3720
|
checkSkillUpdate,
|
|
3721
|
+
checkAllSkillUpdates,
|
|
3655
3722
|
RECOMMENDATION_ERROR_CODES,
|
|
3656
3723
|
tokenizeCriteriaValue,
|
|
3657
3724
|
validateRecommendationCriteria,
|
|
@@ -3666,4 +3733,4 @@ export {
|
|
|
3666
3733
|
toSarif,
|
|
3667
3734
|
validateSkill
|
|
3668
3735
|
};
|
|
3669
|
-
//# sourceMappingURL=chunk-
|
|
3736
|
+
//# sourceMappingURL=chunk-GR47LTXR.js.map
|