ali-skills 0.1.0 → 0.1.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/node_modules/@ali/cli-skills/dist/_chunks/plugin-manifest-validate.mjs +24 -17
- package/node_modules/@ali/cli-skills/dist/_chunks/plugin.mjs +127 -27
- package/node_modules/@ali/cli-skills/dist/_chunks/publish.mjs +1 -0
- package/node_modules/@ali/cli-skills/dist/_chunks/skill-lock.mjs +49 -1
- package/node_modules/@ali/cli-skills/dist/cli.mjs +2 -2
- package/node_modules/@ali/cli-skills/package.json +1 -1
- package/package.json +2 -2
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync, readdirSync, statSync } from "fs";
|
|
2
|
-
import { join, normalize, resolve, sep } from "path";
|
|
2
|
+
import { join, normalize, relative, resolve, sep } from "path";
|
|
3
3
|
const ENV_URLS = {
|
|
4
4
|
local: "http://localhost:3000/api/skills",
|
|
5
5
|
daily: "https://next-ai-base.fn.taobao.net/api/skills",
|
|
@@ -30,6 +30,11 @@ const SCAN_SKIP_DIRS = new Set([
|
|
|
30
30
|
"__pycache__",
|
|
31
31
|
".agents"
|
|
32
32
|
]);
|
|
33
|
+
function toSubpath(base, root) {
|
|
34
|
+
const rel = relative(base, root);
|
|
35
|
+
if (!rel || rel === ".") return "";
|
|
36
|
+
return rel.split(sep).join("/");
|
|
37
|
+
}
|
|
33
38
|
function isContainedIn(target, base) {
|
|
34
39
|
const nb = normalize(resolve(base));
|
|
35
40
|
const nt = normalize(resolve(target));
|
|
@@ -40,26 +45,25 @@ function detectDeclaredAgents(dir) {
|
|
|
40
45
|
for (const [manifestDir, agent] of Object.entries(MANIFEST_DIR_TO_AGENT)) if (existsSync(join(dir, manifestDir, "plugin.json"))) agents.push(agent);
|
|
41
46
|
return agents;
|
|
42
47
|
}
|
|
43
|
-
function
|
|
44
|
-
if (depth > MAX_SCAN_DEPTH) return
|
|
45
|
-
if (detectDeclaredAgents(baseDir).length > 0)
|
|
48
|
+
function collectPackageRoots(baseDir, depth, out) {
|
|
49
|
+
if (depth > MAX_SCAN_DEPTH) return;
|
|
50
|
+
if (detectDeclaredAgents(baseDir).length > 0) {
|
|
51
|
+
out.push(baseDir);
|
|
52
|
+
return;
|
|
53
|
+
}
|
|
46
54
|
let entries;
|
|
47
55
|
try {
|
|
48
56
|
entries = readdirSync(baseDir).sort();
|
|
49
57
|
} catch {
|
|
50
|
-
return
|
|
58
|
+
return;
|
|
51
59
|
}
|
|
52
60
|
for (const name of entries) {
|
|
53
61
|
if (SCAN_SKIP_DIRS.has(name) || MANIFEST_DIR_NAMES.includes(name)) continue;
|
|
54
62
|
const child = join(baseDir, name);
|
|
55
63
|
try {
|
|
56
|
-
if (statSync(child).isDirectory())
|
|
57
|
-
const hit = scanForFirstPackageRoot(child, depth + 1);
|
|
58
|
-
if (hit) return hit;
|
|
59
|
-
}
|
|
64
|
+
if (statSync(child).isDirectory()) collectPackageRoots(child, depth + 1, out);
|
|
60
65
|
} catch {}
|
|
61
66
|
}
|
|
62
|
-
return null;
|
|
63
67
|
}
|
|
64
68
|
function findPluginPackageRoots(baseDir, opts = {}) {
|
|
65
69
|
const base = resolve(baseDir);
|
|
@@ -70,20 +74,23 @@ function findPluginPackageRoots(baseDir, opts = {}) {
|
|
|
70
74
|
if (declaredAgents.length === 0) throw new Error(`No plugin manifest (.X-plugin/plugin.json) found at subpath: ${opts.subpath}`);
|
|
71
75
|
return [{
|
|
72
76
|
root,
|
|
73
|
-
declaredAgents
|
|
77
|
+
declaredAgents,
|
|
78
|
+
subpath: toSubpath(base, root)
|
|
74
79
|
}];
|
|
75
80
|
}
|
|
76
81
|
const rootAgents = detectDeclaredAgents(base);
|
|
77
82
|
if (rootAgents.length > 0) return [{
|
|
78
83
|
root: base,
|
|
79
|
-
declaredAgents: rootAgents
|
|
84
|
+
declaredAgents: rootAgents,
|
|
85
|
+
subpath: ""
|
|
80
86
|
}];
|
|
81
|
-
const
|
|
82
|
-
|
|
87
|
+
const roots = [];
|
|
88
|
+
collectPackageRoots(base, 0, roots);
|
|
89
|
+
return roots.sort().map((root) => ({
|
|
83
90
|
root,
|
|
84
|
-
declaredAgents: detectDeclaredAgents(root)
|
|
85
|
-
|
|
86
|
-
|
|
91
|
+
declaredAgents: detectDeclaredAgents(root),
|
|
92
|
+
subpath: toSubpath(base, root)
|
|
93
|
+
}));
|
|
87
94
|
}
|
|
88
95
|
const AGENT_REFERENCE_FIELDS = {
|
|
89
96
|
"claude-code": [
|
|
@@ -1,8 +1,8 @@
|
|
|
1
|
-
import "./rolldown-runtime.mjs";
|
|
2
|
-
import { l as pD } from "./libs/@clack/core.mjs";
|
|
1
|
+
import { i as __toESM } from "./rolldown-runtime.mjs";
|
|
2
|
+
import { l as pD, u as require_picocolors } from "./libs/@clack/core.mjs";
|
|
3
3
|
import { a as Y, n as M, s as fe } from "./libs/@clack/prompts.mjs";
|
|
4
4
|
import { i as SKILLS_API_BASE_URL, n as findPluginPackageRoots, t as validatePluginPackage } from "./plugin-manifest-validate.mjs";
|
|
5
|
-
import {
|
|
5
|
+
import { A as getDisplaySource, D as redactCliSnippet, F as resolveSourceInput, I as toInternalHttpsCloneUrl, P as parseSource, T as cloneRepo, b as AGENTS_DIR, f as saveSelectedAgents, k as embedInternalGitCredentials, s as getLastSelectedAgents, v as trackPluginCommand, x as PLUGINS_SUBDIR, y as trackPluginInstall } from "./skill-lock.mjs";
|
|
6
6
|
import "./libs/@kwsites/file-exists.mjs";
|
|
7
7
|
import "./libs/@kwsites/promise-deferred.mjs";
|
|
8
8
|
import "./libs/simple-git.mjs";
|
|
@@ -11,6 +11,7 @@ import { copyFileSync, createWriteStream, existsSync, lstatSync, mkdirSync, read
|
|
|
11
11
|
import { dirname, join, normalize, relative, resolve, sep } from "path";
|
|
12
12
|
import { homedir, platform } from "os";
|
|
13
13
|
import { createHash } from "crypto";
|
|
14
|
+
var import_picocolors = /* @__PURE__ */ __toESM(require_picocolors(), 1);
|
|
14
15
|
const MAX_PLUGIN_ID_PART = 64;
|
|
15
16
|
function sanitizePluginId(pluginId) {
|
|
16
17
|
const base = pluginId.toLowerCase().replace(/[^a-z0-9._]+/g, "-").replace(/^[.-]+|[.-]+$/g, "") || "unnamed-plugin";
|
|
@@ -39,6 +40,10 @@ function normalizeSourceKey(parsed) {
|
|
|
39
40
|
}
|
|
40
41
|
return parts.join("");
|
|
41
42
|
}
|
|
43
|
+
function appendSubpathToSourceKey(sourceKey, subpath) {
|
|
44
|
+
const sub = subpath.replace(/\\/g, "/").replace(/^\.?\//, "").replace(/\/$/, "");
|
|
45
|
+
return sub ? `${sourceKey}/${sub}` : sourceKey;
|
|
46
|
+
}
|
|
42
47
|
function buildNsKey(pluginId, sourceKey) {
|
|
43
48
|
return `${sanitizePluginId(pluginId)}__${shortHash(sourceKey)}`;
|
|
44
49
|
}
|
|
@@ -67,6 +72,7 @@ const pluginAgents = {
|
|
|
67
72
|
globalLoadDir: (home) => join(home, ".cursor", "plugins", "local")
|
|
68
73
|
}
|
|
69
74
|
};
|
|
75
|
+
const SUPPORTED_PLUGIN_AGENTS = Object.keys(pluginAgents);
|
|
70
76
|
function getPluginAgentConfig(agent) {
|
|
71
77
|
return pluginAgents[agent];
|
|
72
78
|
}
|
|
@@ -494,12 +500,17 @@ const CATALOGABLE_TYPES = new Set([
|
|
|
494
500
|
async function resolveSource(source, options = {}) {
|
|
495
501
|
const parsed = parseSource(resolveSourceInput(source, { github: options.github }));
|
|
496
502
|
const sourceKey = normalizeSourceKey(parsed);
|
|
503
|
+
const sourceKeyBase = normalizeSourceKey({
|
|
504
|
+
...parsed,
|
|
505
|
+
subpath: void 0
|
|
506
|
+
});
|
|
497
507
|
if (parsed.type === "local") {
|
|
498
508
|
const dir = parsed.localPath ?? parsed.url;
|
|
499
509
|
if (!existsSync(dir)) throw new Error(`本地路径不存在: ${dir}`);
|
|
500
510
|
return {
|
|
501
511
|
dir,
|
|
502
512
|
sourceKey,
|
|
513
|
+
sourceKeyBase,
|
|
503
514
|
displaySource: dir,
|
|
504
515
|
sourceType: "local",
|
|
505
516
|
subpath: parsed.subpath
|
|
@@ -510,6 +521,7 @@ async function resolveSource(source, options = {}) {
|
|
|
510
521
|
return {
|
|
511
522
|
dir: await cloneRepo(cloneUrl, parsed.ref),
|
|
512
523
|
sourceKey,
|
|
524
|
+
sourceKeyBase,
|
|
513
525
|
displaySource: getDisplaySource(parsed.url, { format: "compact" }),
|
|
514
526
|
sourceType: parsed.type,
|
|
515
527
|
subpath: parsed.subpath
|
|
@@ -572,29 +584,100 @@ async function runPluginAdd(source, options = {}) {
|
|
|
572
584
|
throw new Error(`未在 ${resolved.displaySource} 找到 plugin(缺少 .X-plugin/plugin.json)`);
|
|
573
585
|
}
|
|
574
586
|
progress?.stop("仓库就绪");
|
|
575
|
-
const
|
|
587
|
+
const candidates = [];
|
|
576
588
|
for (const pkg of packages) {
|
|
577
589
|
const validation = validatePluginPackage(pkg.root, pkg.declaredAgents);
|
|
578
590
|
for (const v of validation.perAgent) if (!v.valid) console.warn(`⚠️ ${v.agent} manifest 校验未通过,跳过:${v.errors.join("; ")}`);
|
|
579
|
-
if (validation.targetAgents.length === 0)
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
console.log("已取消");
|
|
583
|
-
return results;
|
|
591
|
+
if (validation.targetAgents.length === 0) {
|
|
592
|
+
console.warn(`⚠️ 跳过 ${pkg.subpath || "(仓库根)"}:无可安装的 agent(manifest 校验均未通过)`);
|
|
593
|
+
continue;
|
|
584
594
|
}
|
|
585
|
-
const targetAgents = resolvedAgents;
|
|
586
|
-
if (targetAgents.length === 0) throw new Error(`未选择任何 agent(--agent 指定的 agent 不在该插件已适配范围内)`);
|
|
587
595
|
const firstValid = validation.perAgent.find((v) => v.valid && v.manifest);
|
|
588
|
-
|
|
589
|
-
|
|
596
|
+
candidates.push({
|
|
597
|
+
pkg,
|
|
598
|
+
validation,
|
|
599
|
+
pluginId: String((firstValid?.manifest)?.name ?? "unnamed-plugin"),
|
|
600
|
+
description: String((firstValid?.manifest)?.description ?? ""),
|
|
601
|
+
version: String((firstValid?.manifest)?.version ?? "")
|
|
602
|
+
});
|
|
603
|
+
}
|
|
604
|
+
if (candidates.length === 0) throw new Error(`未在 ${resolved.displaySource} 找到可安装的 plugin(manifest 校验均未通过)`);
|
|
605
|
+
M.info(`发现 ${import_picocolors.default.green(candidates.length)} 个 plugin${candidates.length > 1 ? "s" : ""}`);
|
|
606
|
+
for (const c of candidates) {
|
|
607
|
+
const loc = c.pkg.subpath ? import_picocolors.default.dim(` (${c.pkg.subpath})`) : import_picocolors.default.dim(" (仓库根)");
|
|
608
|
+
M.message(` ${import_picocolors.default.cyan(c.pluginId)}${loc}`);
|
|
609
|
+
}
|
|
610
|
+
let selected = candidates;
|
|
611
|
+
if (options.plugins && options.plugins.length > 0) {
|
|
612
|
+
const want = options.plugins.map((s) => s.toLowerCase());
|
|
613
|
+
selected = candidates.filter((c) => want.includes(c.pluginId.toLowerCase()));
|
|
614
|
+
if (selected.length === 0) throw new Error(`未找到匹配的 plugin: ${options.plugins.join(", ")}。可用: ${candidates.map((c) => c.pluginId).join(", ")}`);
|
|
615
|
+
} else if (candidates.length > 1 && !resolved.subpath && process.stdout.isTTY && !options.yes) {
|
|
616
|
+
const chosen = await fe({
|
|
617
|
+
message: `选择要安装的 plugin(空格选择)`,
|
|
618
|
+
options: candidates.map((c) => ({
|
|
619
|
+
value: c,
|
|
620
|
+
label: c.pluginId,
|
|
621
|
+
hint: c.description ? `${c.pkg.subpath || "仓库根"} — ${c.description.slice(0, 50)}` : c.pkg.subpath || "仓库根"
|
|
622
|
+
})),
|
|
623
|
+
required: true
|
|
624
|
+
});
|
|
625
|
+
if (pD(chosen)) {
|
|
626
|
+
console.log("已取消");
|
|
627
|
+
return [];
|
|
628
|
+
}
|
|
629
|
+
selected = chosen;
|
|
630
|
+
} else if (candidates.length > 1 && !resolved.subpath) M.info(`非交互模式:将安装全部 ${candidates.length} 个 plugin`);
|
|
631
|
+
const unionAgents = [...new Set(selected.flatMap((c) => c.validation.targetAgents))];
|
|
632
|
+
const fmtAgents = (ids) => ids.map((a) => `${a}(${PLUGIN_AGENT_LABELS[a] ?? a})`).join("、");
|
|
633
|
+
if (options.agents && options.agents.length > 0) {
|
|
634
|
+
const unknown = options.agents.filter((a) => !SUPPORTED_PLUGIN_AGENTS.includes(a));
|
|
635
|
+
if (options.agents.filter((a) => unionAgents.includes(a)).length === 0) {
|
|
636
|
+
const lines = [
|
|
637
|
+
unknown.length > 0 ? `未知的 --agent 值:${unknown.join(", ")}` : `--agent 指定的 Agent 不在所选插件的已适配范围内:${options.agents.join(", ")}`,
|
|
638
|
+
`合法 Agent:${fmtAgents(SUPPORTED_PLUGIN_AGENTS)}`,
|
|
639
|
+
`所选插件已适配:${fmtAgents(unionAgents)}`,
|
|
640
|
+
`用法示例:--agent ${unionAgents[0] ?? "claude-code"}`
|
|
641
|
+
];
|
|
642
|
+
throw new Error(lines.join("\n "));
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
const chosenAgents = await resolveInstallAgents(unionAgents, options);
|
|
646
|
+
if (chosenAgents === null) {
|
|
647
|
+
console.log("已取消");
|
|
648
|
+
return [];
|
|
649
|
+
}
|
|
650
|
+
if (chosenAgents.length === 0) throw new Error(`未选择任何 Agent\n 所选插件已适配:${fmtAgents(unionAgents)}`);
|
|
651
|
+
const plan = selected.map((c) => ({
|
|
652
|
+
c,
|
|
653
|
+
targetAgents: chosenAgents.filter((a) => c.validation.targetAgents.includes(a))
|
|
654
|
+
})).filter((item) => {
|
|
655
|
+
if (item.targetAgents.length === 0) {
|
|
656
|
+
console.warn(`⚠️ 跳过 ${item.c.pluginId}:所选 Agent 不在该插件已适配范围内`);
|
|
657
|
+
return false;
|
|
658
|
+
}
|
|
659
|
+
return true;
|
|
660
|
+
});
|
|
661
|
+
if (plan.length === 0) throw new Error(`没有可安装的 plugin(所选 Agent 与所选插件均无交集)`);
|
|
662
|
+
M.info(`将安装 ${import_picocolors.default.green(plan.length)} 个 plugin:`);
|
|
663
|
+
for (const { c, targetAgents } of plan) {
|
|
664
|
+
const agentLabels = targetAgents.map((a) => PLUGIN_AGENT_LABELS[a] ?? a).join("、");
|
|
665
|
+
const loc = c.pkg.subpath ? import_picocolors.default.dim(` (${c.pkg.subpath})`) : "";
|
|
666
|
+
M.message(` ${import_picocolors.default.cyan(c.pluginId)} → ${agentLabels}${loc}`);
|
|
667
|
+
}
|
|
668
|
+
const results = [];
|
|
669
|
+
for (const { c, targetAgents } of plan) {
|
|
670
|
+
const { pkg, validation, pluginId, description, version } = c;
|
|
671
|
+
const nsKey = buildNsKey(pluginId, appendSubpathToSourceKey(resolved.sourceKeyBase, pkg.subpath));
|
|
590
672
|
const catalogItem = {
|
|
591
673
|
pluginId,
|
|
592
674
|
name: pluginId,
|
|
593
|
-
|
|
675
|
+
subpath: pkg.subpath,
|
|
676
|
+
description,
|
|
594
677
|
manifests: validation.manifests,
|
|
595
678
|
targetAgents: validation.targetAgents,
|
|
596
679
|
components: validation.components,
|
|
597
|
-
version
|
|
680
|
+
version
|
|
598
681
|
};
|
|
599
682
|
if (!options.skipCatalog && CATALOGABLE_TYPES.has(resolved.sourceType)) {
|
|
600
683
|
progress?.start("正在录入平台 catalog…");
|
|
@@ -619,7 +702,7 @@ async function runPluginAdd(source, options = {}) {
|
|
|
619
702
|
nsKey,
|
|
620
703
|
pluginId,
|
|
621
704
|
source: resolved.displaySource,
|
|
622
|
-
version
|
|
705
|
+
version,
|
|
623
706
|
targetAgents,
|
|
624
707
|
scope: options.scope,
|
|
625
708
|
channel: "cli",
|
|
@@ -637,6 +720,12 @@ async function runPluginAdd(source, options = {}) {
|
|
|
637
720
|
if (res.installedAgents.length > 0) console.log(`✅ 已安装 plugin "${pluginId}" → ${res.installedAgents.join(", ")}`);
|
|
638
721
|
for (const s of res.skipped) console.warn(`⚠️ 跳过 ${s.agent}:${redactCliSnippet(s.reason)}`);
|
|
639
722
|
}
|
|
723
|
+
const installed = results.filter((r) => r.targetAgents.length > 0);
|
|
724
|
+
if (installed.length > 0 && CATALOGABLE_TYPES.has(resolved.sourceType)) trackPluginInstall({
|
|
725
|
+
source: resolved.displaySource,
|
|
726
|
+
pluginIds: installed.map((r) => r.pluginId),
|
|
727
|
+
agents: [...new Set(installed.flatMap((r) => r.targetAgents))]
|
|
728
|
+
});
|
|
640
729
|
return results;
|
|
641
730
|
}
|
|
642
731
|
function runPluginList(options = {}) {
|
|
@@ -677,7 +766,7 @@ function runPluginRemove(idOrNsKey, options = {}) {
|
|
|
677
766
|
async function runPluginCommand(args) {
|
|
678
767
|
const sub = args[0];
|
|
679
768
|
const rest = args.slice(1);
|
|
680
|
-
if (sub === "
|
|
769
|
+
if (sub === "remove" || sub === "list" || sub === "publish") trackPluginCommand(sub);
|
|
681
770
|
else if (sub === "rm") trackPluginCommand("remove");
|
|
682
771
|
else if (sub === "ls") trackPluginCommand("list");
|
|
683
772
|
else if (sub === "pub") trackPluginCommand("publish");
|
|
@@ -685,6 +774,7 @@ async function runPluginCommand(args) {
|
|
|
685
774
|
case "add": {
|
|
686
775
|
let source;
|
|
687
776
|
const agents = [];
|
|
777
|
+
const plugins = [];
|
|
688
778
|
let scope = "user";
|
|
689
779
|
const github = rest.includes("--github");
|
|
690
780
|
for (let i = 0; i < rest.length; i++) {
|
|
@@ -693,24 +783,33 @@ async function runPluginCommand(args) {
|
|
|
693
783
|
if (arg === "--agent" || arg === "-a") {
|
|
694
784
|
const v = rest[++i];
|
|
695
785
|
if (v) agents.push(...v.split(",").map((s) => s.trim()).filter(Boolean));
|
|
786
|
+
} else if (arg === "--plugin" || arg === "-p") {
|
|
787
|
+
const v = rest[++i];
|
|
788
|
+
if (v) plugins.push(...v.split(",").map((s) => s.trim()).filter(Boolean));
|
|
696
789
|
} else if (arg === "--scope") {
|
|
697
790
|
const v = rest[++i];
|
|
698
791
|
if (v === "user" || v === "project" || v === "local") scope = v;
|
|
699
792
|
} else if (!arg.startsWith("-") && !source) source = arg;
|
|
700
793
|
}
|
|
701
794
|
if (!source) {
|
|
702
|
-
console.error("用法: cli-skills plugin add <source> [--agent <id>]... [--all] [--scope user|project|local] [--github] [-y]");
|
|
795
|
+
console.error("用法: cli-skills plugin add <source> [--plugin <id>]... [--agent <id>]... [--all] [--scope user|project|local] [--github] [-y]");
|
|
703
796
|
process.exitCode = 1;
|
|
704
797
|
return;
|
|
705
798
|
}
|
|
706
|
-
|
|
707
|
-
|
|
708
|
-
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
713
|
-
|
|
799
|
+
try {
|
|
800
|
+
await runPluginAdd(source, {
|
|
801
|
+
yes: rest.includes("-y") || rest.includes("--yes"),
|
|
802
|
+
agents: agents.length > 0 ? agents : void 0,
|
|
803
|
+
plugins: plugins.length > 0 ? plugins : void 0,
|
|
804
|
+
all: rest.includes("--all"),
|
|
805
|
+
scope,
|
|
806
|
+
github,
|
|
807
|
+
skipCatalog: rest.includes("--skip-catalog")
|
|
808
|
+
});
|
|
809
|
+
} catch (err) {
|
|
810
|
+
console.error(`✗ ${err instanceof Error ? err.message : String(err)}`);
|
|
811
|
+
process.exitCode = 1;
|
|
812
|
+
}
|
|
714
813
|
break;
|
|
715
814
|
}
|
|
716
815
|
case "remove":
|
|
@@ -736,7 +835,8 @@ async function runPluginCommand(args) {
|
|
|
736
835
|
}
|
|
737
836
|
default:
|
|
738
837
|
console.log("用法: cli-skills plugin <add|remove|list|publish>");
|
|
739
|
-
console.log(" add <source> [options] 安装 plugin
|
|
838
|
+
console.log(" add <source> [options] 安装 plugin(单仓多插件时交互勾选)");
|
|
839
|
+
console.log(" --plugin/-p <id> 限定要装的 plugin(可重复/逗号分隔);不传且多个时提问");
|
|
740
840
|
console.log(" --agent/-a <id> 限定目标 Agent(可重复/逗号分隔);不传则提问");
|
|
741
841
|
console.log(" --all 安装到全部已适配 Agent,不提问");
|
|
742
842
|
console.log(" --scope user|project|local 安装位置(默认 user/用户级;project/local 仅 Claude Code)");
|
|
@@ -710,6 +710,7 @@ async function runPluginPublish(_options = {}) {
|
|
|
710
710
|
items.push({
|
|
711
711
|
pluginId,
|
|
712
712
|
name: pluginId,
|
|
713
|
+
subpath: pkg.subpath,
|
|
713
714
|
description: String(manifest.description ?? ""),
|
|
714
715
|
manifests: validation.manifests,
|
|
715
716
|
targetAgents: validation.targetAgents,
|
|
@@ -475,6 +475,54 @@ function trackPluginCommand(command) {
|
|
|
475
475
|
});
|
|
476
476
|
} catch {}
|
|
477
477
|
}
|
|
478
|
+
function trackPluginInstall(input) {
|
|
479
|
+
if (!isEnabled()) return;
|
|
480
|
+
if (input.pluginIds.length === 0) return;
|
|
481
|
+
try {
|
|
482
|
+
let installerUsername;
|
|
483
|
+
let installerEmail;
|
|
484
|
+
const userParam = getUserParam();
|
|
485
|
+
if (userParam) try {
|
|
486
|
+
const u = JSON.parse(userParam);
|
|
487
|
+
installerUsername = u.username;
|
|
488
|
+
installerEmail = u.email;
|
|
489
|
+
} catch {}
|
|
490
|
+
const body = {
|
|
491
|
+
event: "install",
|
|
492
|
+
source: input.source,
|
|
493
|
+
pluginIds: input.pluginIds,
|
|
494
|
+
agents: input.agents,
|
|
495
|
+
cliVersion: cliVersion ?? void 0,
|
|
496
|
+
installerUsername,
|
|
497
|
+
installerEmail
|
|
498
|
+
};
|
|
499
|
+
pendingCount++;
|
|
500
|
+
const promise = postJsonWithRetry(PLUGIN_TELEMETRY_URL, body).catch((err) => {
|
|
501
|
+
console.error("[Telemetry] Failed to send plugin install telemetry:", err);
|
|
502
|
+
});
|
|
503
|
+
pendingPromises.push(promise);
|
|
504
|
+
promise.finally(() => {
|
|
505
|
+
const index = pendingPromises.indexOf(promise);
|
|
506
|
+
if (index > -1) pendingPromises.splice(index, 1);
|
|
507
|
+
});
|
|
508
|
+
} catch {}
|
|
509
|
+
}
|
|
510
|
+
async function postJsonWithRetry(url, body, attempts = 3) {
|
|
511
|
+
let lastErr;
|
|
512
|
+
const payload = JSON.stringify(body);
|
|
513
|
+
for (let i = 0; i < attempts; i++) try {
|
|
514
|
+
await fetch(url, {
|
|
515
|
+
method: "POST",
|
|
516
|
+
headers: { "Content-Type": "application/json" },
|
|
517
|
+
body: payload
|
|
518
|
+
});
|
|
519
|
+
return;
|
|
520
|
+
} catch (err) {
|
|
521
|
+
lastErr = err;
|
|
522
|
+
if (i < attempts - 1) await new Promise((r) => setTimeout(r, 150 * (i + 1)));
|
|
523
|
+
}
|
|
524
|
+
throw lastErr;
|
|
525
|
+
}
|
|
478
526
|
const AGENTS_DIR = ".agents";
|
|
479
527
|
const LOCK_FILE = ".skill-lock.json";
|
|
480
528
|
const CURRENT_VERSION = 3;
|
|
@@ -634,4 +682,4 @@ function sanitizeSourceUrl(url) {
|
|
|
634
682
|
}
|
|
635
683
|
return url;
|
|
636
684
|
}
|
|
637
|
-
export {
|
|
685
|
+
export { getDisplaySource as A, GitCloneError as C, redactCliSnippet as D, listRemoteBranches as E, resolveSourceInput as F, toInternalHttpsCloneUrl as I, isRepoPrivate as M, parseOwnerRepo as N, redactSensitiveText as O, parseSource as P, SKILLS_SUBDIR as S, cloneRepo as T, track as _, getAllLockedSkills as a, AGENTS_DIR$1 as b, getSkillFromLock as c, sanitizeSourceUrl as d, saveSelectedAgents as f, setVersion as g, getPendingTelemetryCount as h, fetchSkillFolderHash as i, getOwnerRepo as j, embedInternalGitCredentials as k, isPromptDismissed as l, flushTelemetry as m, dismissPrompt as n, getGitHubToken as o, fetchAuditData as p, fetchAliInternalCommitHash as r, getLastSelectedAgents as s, addSkillToLock as t, removeSkillFromLock as u, trackPluginCommand as v, cleanupTempDir as w, PLUGINS_SUBDIR as x, trackPluginInstall as y };
|
|
@@ -3,7 +3,7 @@ import { i as __toESM, n as __exportAll, r as __require } from "./_chunks/rolldo
|
|
|
3
3
|
import { l as pD, u as require_picocolors } from "./_chunks/libs/@clack/core.mjs";
|
|
4
4
|
import { a as Y, c as ge, d as ye, i as Se, l as ve, n as M, o as be, r as Me, s as fe, t as Ie, u as xe } from "./_chunks/libs/@clack/prompts.mjs";
|
|
5
5
|
import { i as SKILLS_API_BASE_URL, r as GITLAB_ACCOUNT } from "./_chunks/plugin-manifest-validate.mjs";
|
|
6
|
-
import { A as
|
|
6
|
+
import { A as getDisplaySource, C as GitCloneError, E as listRemoteBranches, F as resolveSourceInput, I as toInternalHttpsCloneUrl, M as isRepoPrivate, N as parseOwnerRepo, O as redactSensitiveText, P as parseSource, S as SKILLS_SUBDIR, T as cloneRepo, _ as track, a as getAllLockedSkills, b as AGENTS_DIR$1, c as getSkillFromLock, d as sanitizeSourceUrl, f as saveSelectedAgents, g as setVersion, h as getPendingTelemetryCount, i as fetchSkillFolderHash, j as getOwnerRepo, l as isPromptDismissed, m as flushTelemetry, n as dismissPrompt, o as getGitHubToken, p as fetchAuditData, r as fetchAliInternalCommitHash, s as getLastSelectedAgents, t as addSkillToLock, u as removeSkillFromLock, w as cleanupTempDir } from "./_chunks/skill-lock.mjs";
|
|
7
7
|
import "./_chunks/libs/@kwsites/file-exists.mjs";
|
|
8
8
|
import "./_chunks/libs/@kwsites/promise-deferred.mjs";
|
|
9
9
|
import "./_chunks/libs/simple-git.mjs";
|
|
@@ -1394,7 +1394,7 @@ var WellKnownProvider = class {
|
|
|
1394
1394
|
}
|
|
1395
1395
|
};
|
|
1396
1396
|
const wellKnownProvider = new WellKnownProvider();
|
|
1397
|
-
var version$1 = "2.1.
|
|
1397
|
+
var version$1 = "2.1.1";
|
|
1398
1398
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
1399
1399
|
async function isSourcePrivate(source) {
|
|
1400
1400
|
const ownerRepo = parseOwnerRepo(source);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ali-skills",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.1",
|
|
4
4
|
"description": "The open agent skills ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -32,7 +32,7 @@
|
|
|
32
32
|
"author": "",
|
|
33
33
|
"license": "MIT",
|
|
34
34
|
"dependencies": {
|
|
35
|
-
"@ali/cli-skills": "^2.1.
|
|
35
|
+
"@ali/cli-skills": "^2.1.1"
|
|
36
36
|
},
|
|
37
37
|
"bundleDependencies": [
|
|
38
38
|
"@ali/cli-skills"
|