ali-skills 0.0.15 → 0.0.16
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.
|
@@ -94,9 +94,32 @@ function parseSource(input) {
|
|
|
94
94
|
const githubRepoMatch = input.match(/github\.com\/([^/]+)\/([^/]+)/);
|
|
95
95
|
if (githubRepoMatch) {
|
|
96
96
|
const [, owner, repo] = githubRepoMatch;
|
|
97
|
+
const cleanRepo = repo.replace(/\.git$/, "");
|
|
98
|
+
const credentialMatch = input.match(/^(https?:\/\/)(?:([^@]+)@)?github\.com/);
|
|
99
|
+
const protocol = credentialMatch?.[1] ?? "https://";
|
|
100
|
+
const credential = credentialMatch?.[2];
|
|
97
101
|
return {
|
|
98
102
|
type: "github",
|
|
99
|
-
url:
|
|
103
|
+
url: credential ? `${protocol}${credential}@github.com/${owner}/${cleanRepo}.git` : `${protocol}github.com/${owner}/${cleanRepo}.git`
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
const internalTreeWithPathMatch = input.match(/^(https?:\/\/(?:[^@/]+@)?(?:code|gitlab)\.alibaba-inc\.com)\/(.+?)(?:\/-)?\/tree\/([^/]+)\/(.+)/);
|
|
107
|
+
if (internalTreeWithPathMatch) {
|
|
108
|
+
const [, host, repoPath, ref, subpath] = internalTreeWithPathMatch;
|
|
109
|
+
if (repoPath && repoPath.includes("/")) return {
|
|
110
|
+
type: "internal",
|
|
111
|
+
url: `${host.replace("gitlab.alibaba-inc.com", "code.alibaba-inc.com")}/${repoPath.replace(/\.git$/, "")}.git`,
|
|
112
|
+
ref,
|
|
113
|
+
subpath: subpath ? sanitizeSubpath(subpath) : subpath
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
const internalTreeMatch = input.match(/^(https?:\/\/(?:[^@/]+@)?(?:code|gitlab)\.alibaba-inc\.com)\/(.+?)(?:\/-)?\/tree\/([^/]+)$/);
|
|
117
|
+
if (internalTreeMatch) {
|
|
118
|
+
const [, host, repoPath, ref] = internalTreeMatch;
|
|
119
|
+
if (repoPath && repoPath.includes("/")) return {
|
|
120
|
+
type: "internal",
|
|
121
|
+
url: `${host.replace("gitlab.alibaba-inc.com", "code.alibaba-inc.com")}/${repoPath.replace(/\.git$/, "")}.git`,
|
|
122
|
+
ref
|
|
100
123
|
};
|
|
101
124
|
}
|
|
102
125
|
const gitlabTreeWithPathMatch = input.match(/^(https?):\/\/([^/]+)\/(.+?)\/-\/tree\/([^/]+)\/(.+)/);
|
|
@@ -144,25 +167,6 @@ function parseSource(input) {
|
|
|
144
167
|
subpath: subpath ? sanitizeSubpath(subpath) : subpath
|
|
145
168
|
};
|
|
146
169
|
}
|
|
147
|
-
const internalTreeWithPathMatch = input.match(/^(https?:\/\/(?:[^@/]+@)?(?:code|gitlab)\.alibaba-inc\.com)\/(.+?)(?:\/-)?\/tree\/([^/]+)\/(.+)/);
|
|
148
|
-
if (internalTreeWithPathMatch) {
|
|
149
|
-
const [, host, repoPath, ref, subpath] = internalTreeWithPathMatch;
|
|
150
|
-
if (repoPath && repoPath.includes("/")) return {
|
|
151
|
-
type: "internal",
|
|
152
|
-
url: `${host.replace("gitlab.alibaba-inc.com", "code.alibaba-inc.com")}/${repoPath.replace(/\.git$/, "")}.git`,
|
|
153
|
-
ref,
|
|
154
|
-
subpath: subpath ? sanitizeSubpath(subpath) : subpath
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
const internalTreeMatch = input.match(/^(https?:\/\/(?:[^@/]+@)?(?:code|gitlab)\.alibaba-inc\.com)\/(.+?)(?:\/-)?\/tree\/([^/]+)$/);
|
|
158
|
-
if (internalTreeMatch) {
|
|
159
|
-
const [, host, repoPath, ref] = internalTreeMatch;
|
|
160
|
-
if (repoPath && repoPath.includes("/")) return {
|
|
161
|
-
type: "internal",
|
|
162
|
-
url: `${host.replace("gitlab.alibaba-inc.com", "code.alibaba-inc.com")}/${repoPath.replace(/\.git$/, "")}.git`,
|
|
163
|
-
ref
|
|
164
|
-
};
|
|
165
|
-
}
|
|
166
170
|
const internalRepoWithSubpathMatch = input.match(/^(https?:\/\/(?:[^@/]+@)?(?:code|gitlab)\.alibaba-inc\.com)\/([^/]+)\/([^/]+)\/(.+)$/);
|
|
167
171
|
if (internalRepoWithSubpathMatch) {
|
|
168
172
|
const [, host, owner, repo, subpath] = internalRepoWithSubpathMatch;
|
|
@@ -220,6 +224,26 @@ function isWellKnownUrl(input) {
|
|
|
220
224
|
return false;
|
|
221
225
|
}
|
|
222
226
|
}
|
|
227
|
+
function getDisplaySource(sourceUrl) {
|
|
228
|
+
if (sourceUrl.startsWith("/") || sourceUrl.startsWith(".") || sourceUrl.startsWith("~")) return sourceUrl;
|
|
229
|
+
const sshMatch = sourceUrl.match(/^git@([^:]+):(.+)$/);
|
|
230
|
+
if (sshMatch) {
|
|
231
|
+
const [, host, path] = sshMatch;
|
|
232
|
+
if (!host || !path) return sourceUrl;
|
|
233
|
+
const cleanPath = path.replace(/\.git$/, "");
|
|
234
|
+
if (host === "code.alibaba-inc.com" || host === "gitlab.alibaba-inc.com") return cleanPath;
|
|
235
|
+
return `https://${host}/${cleanPath}`;
|
|
236
|
+
}
|
|
237
|
+
if (sourceUrl.startsWith("http://") || sourceUrl.startsWith("https://")) try {
|
|
238
|
+
const url = new URL(sourceUrl);
|
|
239
|
+
const cleanPath = url.pathname.replace(/\.git$/, "").replace(/^\//, "");
|
|
240
|
+
if (url.hostname === "code.alibaba-inc.com" || url.hostname === "gitlab.alibaba-inc.com") return cleanPath;
|
|
241
|
+
return `https://${url.hostname}/${cleanPath}`;
|
|
242
|
+
} catch {
|
|
243
|
+
return sourceUrl.replace(/^https?:\/\/[^@]+@/, "https://");
|
|
244
|
+
}
|
|
245
|
+
return sourceUrl;
|
|
246
|
+
}
|
|
223
247
|
const silentOutput = new Writable({ write(_chunk, _encoding, callback) {
|
|
224
248
|
callback();
|
|
225
249
|
} });
|
|
@@ -2056,6 +2080,25 @@ async function saveSelectedAgents(agents) {
|
|
|
2056
2080
|
lock.lastSelectedAgents = agents;
|
|
2057
2081
|
await writeSkillLock(lock);
|
|
2058
2082
|
}
|
|
2083
|
+
function sanitizeSourceUrl(url) {
|
|
2084
|
+
const sshMatch = url.match(/^git@([^:]+):(.+)$/);
|
|
2085
|
+
if (sshMatch) {
|
|
2086
|
+
const [, host, path] = sshMatch;
|
|
2087
|
+
if (!host || !path) return url;
|
|
2088
|
+
return `https://${host}/${path.replace(/\.git$/, "")}.git`;
|
|
2089
|
+
}
|
|
2090
|
+
if (url.startsWith("http://") || url.startsWith("https://")) try {
|
|
2091
|
+
const parsed = new URL(url);
|
|
2092
|
+
parsed.username = "";
|
|
2093
|
+
parsed.password = "";
|
|
2094
|
+
let cleanUrl = parsed.toString();
|
|
2095
|
+
if (!cleanUrl.endsWith(".git")) cleanUrl += ".git";
|
|
2096
|
+
return cleanUrl;
|
|
2097
|
+
} catch {
|
|
2098
|
+
return url;
|
|
2099
|
+
}
|
|
2100
|
+
return url;
|
|
2101
|
+
}
|
|
2059
2102
|
const LOCAL_LOCK_FILE = "skills-lock.json";
|
|
2060
2103
|
const CURRENT_VERSION = 1;
|
|
2061
2104
|
function getLocalLockPath(cwd) {
|
|
@@ -2066,11 +2109,27 @@ async function readLocalLock(cwd) {
|
|
|
2066
2109
|
try {
|
|
2067
2110
|
const content = await readFile(lockPath, "utf-8");
|
|
2068
2111
|
const parsed = JSON.parse(content);
|
|
2069
|
-
if (typeof parsed.version !== "number"
|
|
2070
|
-
|
|
2071
|
-
|
|
2112
|
+
if (typeof parsed.version !== "number") return {
|
|
2113
|
+
lock: parsed,
|
|
2114
|
+
isOutdated: true
|
|
2115
|
+
};
|
|
2116
|
+
if (parsed.version < CURRENT_VERSION) return {
|
|
2117
|
+
lock: parsed,
|
|
2118
|
+
isOutdated: true
|
|
2119
|
+
};
|
|
2120
|
+
if (!parsed.skills) return {
|
|
2121
|
+
lock: createEmptyLocalLock(),
|
|
2122
|
+
isOutdated: false
|
|
2123
|
+
};
|
|
2124
|
+
return {
|
|
2125
|
+
lock: parsed,
|
|
2126
|
+
isOutdated: false
|
|
2127
|
+
};
|
|
2072
2128
|
} catch {
|
|
2073
|
-
return
|
|
2129
|
+
return {
|
|
2130
|
+
lock: createEmptyLocalLock(),
|
|
2131
|
+
isOutdated: false
|
|
2132
|
+
};
|
|
2074
2133
|
}
|
|
2075
2134
|
}
|
|
2076
2135
|
async function writeLocalLock(lock, cwd) {
|
|
@@ -2112,7 +2171,7 @@ async function collectFiles(baseDir, currentDir, results) {
|
|
|
2112
2171
|
}));
|
|
2113
2172
|
}
|
|
2114
2173
|
async function addSkillToLocalLock(skillName, entry, cwd) {
|
|
2115
|
-
const lock = await readLocalLock(cwd);
|
|
2174
|
+
const { lock } = await readLocalLock(cwd);
|
|
2116
2175
|
lock.skills[skillName] = entry;
|
|
2117
2176
|
await writeLocalLock(lock, cwd);
|
|
2118
2177
|
}
|
|
@@ -2132,7 +2191,7 @@ function logSkillParseFailures(failures) {
|
|
|
2132
2191
|
if (f.hint) M.message(import_picocolors.default.yellow(` 提示: ${f.hint}`));
|
|
2133
2192
|
}
|
|
2134
2193
|
}
|
|
2135
|
-
var version$1 = "2.0.
|
|
2194
|
+
var version$1 = "2.0.16";
|
|
2136
2195
|
const isCancelled$1 = (value) => typeof value === "symbol";
|
|
2137
2196
|
async function isSourcePrivate(source) {
|
|
2138
2197
|
const ownerRepo = parseOwnerRepo(source);
|
|
@@ -2386,7 +2445,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2386
2445
|
value: key,
|
|
2387
2446
|
label: config.displayName
|
|
2388
2447
|
})));
|
|
2389
|
-
if (
|
|
2448
|
+
if (isCancelled$1(selected)) {
|
|
2390
2449
|
xe("Installation cancelled");
|
|
2391
2450
|
process.exit(0);
|
|
2392
2451
|
}
|
|
@@ -2400,7 +2459,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2400
2459
|
} else M.info(`Installing to: ${installedAgents.map((a) => import_picocolors.default.cyan(agents[a].displayName)).join(", ")}`);
|
|
2401
2460
|
} else {
|
|
2402
2461
|
const selected = await selectAgentsInteractive({ global: options.global });
|
|
2403
|
-
if (
|
|
2462
|
+
if (isCancelled$1(selected)) {
|
|
2404
2463
|
xe("Installation cancelled");
|
|
2405
2464
|
process.exit(0);
|
|
2406
2465
|
}
|
|
@@ -2524,8 +2583,7 @@ async function handleWellKnownSkills(source, url, options, spinner) {
|
|
|
2524
2583
|
await addSkillToLock(skill.installName, {
|
|
2525
2584
|
source: sourceIdentifier,
|
|
2526
2585
|
sourceType: "well-known",
|
|
2527
|
-
sourceUrl: skill.sourceUrl
|
|
2528
|
-
skillFolderHash: ""
|
|
2586
|
+
sourceUrl: sanitizeSourceUrl(skill.sourceUrl)
|
|
2529
2587
|
});
|
|
2530
2588
|
} catch {}
|
|
2531
2589
|
}
|
|
@@ -2886,7 +2944,7 @@ async function runAdd(args, options = {}) {
|
|
|
2886
2944
|
value: key,
|
|
2887
2945
|
label: config.displayName
|
|
2888
2946
|
})));
|
|
2889
|
-
if (
|
|
2947
|
+
if (isCancelled$1(selected)) {
|
|
2890
2948
|
xe("Installation cancelled");
|
|
2891
2949
|
await cleanup(tempDir);
|
|
2892
2950
|
process.exit(0);
|
|
@@ -2901,7 +2959,7 @@ async function runAdd(args, options = {}) {
|
|
|
2901
2959
|
} else M.info(`Installing to: ${installedAgents.map((a) => import_picocolors.default.cyan(agents[a].displayName)).join(", ")}`);
|
|
2902
2960
|
} else {
|
|
2903
2961
|
const selected = await selectAgentsInteractive({ global: options.global });
|
|
2904
|
-
if (
|
|
2962
|
+
if (isCancelled$1(selected)) {
|
|
2905
2963
|
xe("Installation cancelled");
|
|
2906
2964
|
await cleanup(tempDir);
|
|
2907
2965
|
process.exit(0);
|
|
@@ -3117,18 +3175,28 @@ async function runAdd(args, options = {}) {
|
|
|
3117
3175
|
for (const skill of selectedSkills) {
|
|
3118
3176
|
const skillDisplayName = getSkillDisplayName(skill);
|
|
3119
3177
|
if (successfulSkillNames.has(skillDisplayName)) try {
|
|
3120
|
-
let skillFolderHash
|
|
3178
|
+
let skillFolderHash;
|
|
3179
|
+
let commitHash;
|
|
3121
3180
|
const skillPathValue = skillFiles[skill.name];
|
|
3122
|
-
|
|
3181
|
+
let skillPath = skillPathValue;
|
|
3182
|
+
if (skillPath) {
|
|
3183
|
+
if (skillPath.endsWith("/SKILL.md")) skillPath = skillPath.slice(0, -9);
|
|
3184
|
+
else if (skillPath.endsWith("SKILL.md")) skillPath = skillPath.slice(0, -8);
|
|
3185
|
+
}
|
|
3186
|
+
if (effectiveSourceType === "github" && skillPathValue) {
|
|
3123
3187
|
const hash = await fetchSkillFolderHash(normalizedSource, skillPathValue, getGitHubToken());
|
|
3124
3188
|
if (hash) skillFolderHash = hash;
|
|
3189
|
+
} else if (effectiveSourceType === "internal" && skillPath !== void 0) {
|
|
3190
|
+
const hash = await fetchAliInternalCommitHash(normalizedSource, skillPath, null);
|
|
3191
|
+
if (hash) commitHash = hash;
|
|
3125
3192
|
}
|
|
3126
3193
|
await addSkillToLock(skill.name, {
|
|
3127
3194
|
source: lockSource || normalizedSource,
|
|
3128
3195
|
sourceType: effectiveSourceType,
|
|
3129
|
-
sourceUrl: parsed.url,
|
|
3130
|
-
skillPath
|
|
3131
|
-
skillFolderHash,
|
|
3196
|
+
sourceUrl: sanitizeSourceUrl(parsed.url),
|
|
3197
|
+
skillPath,
|
|
3198
|
+
...skillFolderHash && { skillFolderHash },
|
|
3199
|
+
...commitHash && { commitHash },
|
|
3132
3200
|
pluginName: skill.pluginName
|
|
3133
3201
|
});
|
|
3134
3202
|
} catch {}
|
|
@@ -3141,8 +3209,9 @@ async function runAdd(args, options = {}) {
|
|
|
3141
3209
|
if (successfulSkillNames.has(skillDisplayName)) try {
|
|
3142
3210
|
const computedHash = await computeSkillFolderHash(skill.path);
|
|
3143
3211
|
const skillFilePath = skillFiles[skill.name];
|
|
3212
|
+
const rawSource = lockSource || parsed.url;
|
|
3144
3213
|
const lockEntry = {
|
|
3145
|
-
source:
|
|
3214
|
+
source: effectiveSourceType === "internal" || effectiveSourceType === "github" ? rawSource.replace(/^https?:\/\/[^@]+@/, "https://") : rawSource,
|
|
3146
3215
|
sourceType: effectiveSourceType,
|
|
3147
3216
|
computedHash
|
|
3148
3217
|
};
|
|
@@ -3305,7 +3374,7 @@ const BOLD$2 = "\x1B[1m";
|
|
|
3305
3374
|
const DIM$5 = "\x1B[38;5;102m";
|
|
3306
3375
|
const TEXT$4 = "\x1B[38;5;145m";
|
|
3307
3376
|
const CYAN$1 = "\x1B[36m";
|
|
3308
|
-
const YELLOW$
|
|
3377
|
+
const YELLOW$5 = "\x1B[33m";
|
|
3309
3378
|
const SKILLS_API_URL = process.env.SKILLS_API_URL;
|
|
3310
3379
|
const SEARCH_ENDPOINT = SKILLS_API_URL ? `${SKILLS_API_URL.replace(/\/+$/, "")}/search` : "https://next-ai-base.pre-fn.alibaba-inc.com/api/skills/search";
|
|
3311
3380
|
function formatInstalls(count) {
|
|
@@ -3375,7 +3444,7 @@ async function runSearchPrompt(initialQuery = "") {
|
|
|
3375
3444
|
const source = skill.source ? ` ${DIM$5}${skill.source}${RESET$5}` : "";
|
|
3376
3445
|
const installs = formatInstalls(skill.installs);
|
|
3377
3446
|
const installsBadge = installs ? ` ${CYAN$1}${installs}${RESET$5}` : "";
|
|
3378
|
-
const githubBadge = skill.sourceType === "github" ? ` ${YELLOW$
|
|
3447
|
+
const githubBadge = skill.sourceType === "github" ? ` ${YELLOW$5}GitHub${RESET$5}` : "";
|
|
3379
3448
|
const loadingIndicator = loading && i === 0 ? ` ${DIM$5}...${RESET$5}` : "";
|
|
3380
3449
|
lines.push(` ${arrow} ${name}${source}${githubBadge}${installsBadge}${loadingIndicator}`);
|
|
3381
3450
|
}
|
|
@@ -3484,7 +3553,7 @@ ${DIM$5} 2) npx @ali/cli-skills add <owner/repo@skill>${RESET$5}`;
|
|
|
3484
3553
|
for (const skill of results.slice(0, 6)) {
|
|
3485
3554
|
const pkg = skill.source || skill.slug;
|
|
3486
3555
|
const installs = formatInstalls(skill.installs);
|
|
3487
|
-
const githubBadge = skill.sourceType === "github" ? ` ${YELLOW$
|
|
3556
|
+
const githubBadge = skill.sourceType === "github" ? ` ${YELLOW$5}GitHub${RESET$5}` : "";
|
|
3488
3557
|
console.log(`${TEXT$4}${pkg}@${skill.name}${RESET$5}${githubBadge}${installs ? ` ${CYAN$1}${installs}${RESET$5}` : ""}`);
|
|
3489
3558
|
const skillUrl = buildSkillUrl(skill);
|
|
3490
3559
|
console.log(`${DIM$5}└ ${skillUrl}${RESET$5}`);
|
|
@@ -3612,7 +3681,7 @@ async function runSync(args, options = {}) {
|
|
|
3612
3681
|
M.info(`${import_picocolors.default.cyan(skill.name)} ${import_picocolors.default.dim(`from ${skill.packageName}`)}`);
|
|
3613
3682
|
if (skill.description) M.message(import_picocolors.default.dim(` ${skill.description}`));
|
|
3614
3683
|
}
|
|
3615
|
-
const localLock = await readLocalLock(cwd);
|
|
3684
|
+
const { lock: localLock } = await readLocalLock(cwd);
|
|
3616
3685
|
const toInstall = [];
|
|
3617
3686
|
const upToDate = [];
|
|
3618
3687
|
if (options.force) {
|
|
@@ -3812,7 +3881,8 @@ function parseSyncOptions(args) {
|
|
|
3812
3881
|
return { options };
|
|
3813
3882
|
}
|
|
3814
3883
|
async function runInstallFromLock(args) {
|
|
3815
|
-
const lock = await readLocalLock(process.cwd());
|
|
3884
|
+
const { lock, isOutdated } = await readLocalLock(process.cwd());
|
|
3885
|
+
if (isOutdated) M.warn("Project lock file may be outdated. Some skills might not install correctly.");
|
|
3816
3886
|
const skillEntries = Object.entries(lock.skills);
|
|
3817
3887
|
if (skillEntries.length === 0) {
|
|
3818
3888
|
M.warn("No project skills found in skills-lock.json");
|
|
@@ -3863,7 +3933,7 @@ const RESET$4 = "\x1B[0m";
|
|
|
3863
3933
|
const BOLD$1 = "\x1B[1m";
|
|
3864
3934
|
const DIM$4 = "\x1B[38;5;102m";
|
|
3865
3935
|
const CYAN = "\x1B[36m";
|
|
3866
|
-
const YELLOW$
|
|
3936
|
+
const YELLOW$4 = "\x1B[33m";
|
|
3867
3937
|
function shortenPath(fullPath, cwd) {
|
|
3868
3938
|
const home = homedir();
|
|
3869
3939
|
if (fullPath.startsWith(home)) return fullPath.replace(home, "~");
|
|
@@ -3897,7 +3967,7 @@ async function runList(args) {
|
|
|
3897
3967
|
const validAgents = Object.keys(agents);
|
|
3898
3968
|
const invalidAgents = options.agent.filter((a) => !validAgents.includes(a));
|
|
3899
3969
|
if (invalidAgents.length > 0) {
|
|
3900
|
-
console.log(`${YELLOW$
|
|
3970
|
+
console.log(`${YELLOW$4}Invalid agents: ${invalidAgents.join(", ")}${RESET$4}`);
|
|
3901
3971
|
console.log(`${DIM$4}Valid agents: ${validAgents.join(", ")}${RESET$4}`);
|
|
3902
3972
|
process.exit(1);
|
|
3903
3973
|
}
|
|
@@ -3934,7 +4004,7 @@ async function runList(args) {
|
|
|
3934
4004
|
const prefix = indent ? " " : "";
|
|
3935
4005
|
const shortPath = shortenPath(skill.canonicalPath, cwd);
|
|
3936
4006
|
const agentNames = skill.agents.map((a) => agents[a].displayName);
|
|
3937
|
-
const agentInfo = skill.agents.length > 0 ? formatList(agentNames) : `${YELLOW$
|
|
4007
|
+
const agentInfo = skill.agents.length > 0 ? formatList(agentNames) : `${YELLOW$4}not linked${RESET$4}`;
|
|
3938
4008
|
console.log(`${prefix}${CYAN}${skill.name}${RESET$4} ${DIM$4}${shortPath}${RESET$4}`);
|
|
3939
4009
|
console.log(`${prefix} ${DIM$4}Agents:${RESET$4} ${agentInfo}`);
|
|
3940
4010
|
}
|
|
@@ -4537,7 +4607,7 @@ const DIM$3 = "\x1B[38;5;102m";
|
|
|
4537
4607
|
const TEXT$3 = "\x1B[38;5;145m";
|
|
4538
4608
|
const RESET$3 = "\x1B[0m";
|
|
4539
4609
|
const GREEN$2 = "\x1B[32m";
|
|
4540
|
-
const YELLOW$
|
|
4610
|
+
const YELLOW$3 = "\x1B[33m";
|
|
4541
4611
|
function startLocalServer() {
|
|
4542
4612
|
return new Promise((resolve) => {
|
|
4543
4613
|
let resolveCallback;
|
|
@@ -4685,7 +4755,7 @@ async function status() {
|
|
|
4685
4755
|
console.log(` 工号: ${auth.empId}`);
|
|
4686
4756
|
console.log(` 网关: ${auth.gatewayUrl}`);
|
|
4687
4757
|
if (expired) {
|
|
4688
|
-
console.log(` Token: ${YELLOW$
|
|
4758
|
+
console.log(` Token: ${YELLOW$3}即将过期${RESET$3}`);
|
|
4689
4759
|
console.log(`${TEXT$3}建议重新登录: npx ali-skills login${RESET$3}`);
|
|
4690
4760
|
} else console.log(` Token: ${GREEN$2}有效${RESET$3} (还剩 ${remainingDays} 天)`);
|
|
4691
4761
|
}
|
|
@@ -4773,7 +4843,7 @@ const TEXT$2 = "\x1B[38;5;145m";
|
|
|
4773
4843
|
const RESET$2 = "\x1B[0m";
|
|
4774
4844
|
const GREEN$1 = "\x1B[32m";
|
|
4775
4845
|
const RED$1 = "\x1B[31m";
|
|
4776
|
-
const YELLOW$
|
|
4846
|
+
const YELLOW$2 = "\x1B[33m";
|
|
4777
4847
|
function openBrowser$1(url) {
|
|
4778
4848
|
const platform = process.platform;
|
|
4779
4849
|
spawn(platform === "darwin" ? "open" : platform === "win32" ? "start" : "xdg-open", [url], {
|
|
@@ -4808,7 +4878,7 @@ function getPlatformPrivateToken(platformKey, explicitToken) {
|
|
|
4808
4878
|
}
|
|
4809
4879
|
async function promptConfigureToken(platformKey, platform) {
|
|
4810
4880
|
console.log();
|
|
4811
|
-
console.log(`${YELLOW$
|
|
4881
|
+
console.log(`${YELLOW$2}⚠️ ${platform.name} 需要配置 Private Token${RESET$2}`);
|
|
4812
4882
|
if (platform.tokenDocUrl) console.log(`${DIM$2}Token 获取地址: ${platform.tokenDocUrl}${RESET$2}`);
|
|
4813
4883
|
if (!await ye({
|
|
4814
4884
|
message: "是否现在配置?",
|
|
@@ -5038,7 +5108,7 @@ const DIM$1 = "\x1B[38;5;102m";
|
|
|
5038
5108
|
const TEXT$1 = "\x1B[38;5;145m";
|
|
5039
5109
|
const RESET$1 = "\x1B[0m";
|
|
5040
5110
|
const GREEN = "\x1B[32m";
|
|
5041
|
-
const YELLOW = "\x1B[33m";
|
|
5111
|
+
const YELLOW$1 = "\x1B[33m";
|
|
5042
5112
|
const RED = "\x1B[31m";
|
|
5043
5113
|
function showConfigHelp() {
|
|
5044
5114
|
console.log(`
|
|
@@ -5108,12 +5178,12 @@ async function configurePlatform(platformKey) {
|
|
|
5108
5178
|
console.log(`${GREEN}✓ ${platform.name} 使用内置凭证,无需配置${RESET$1}`);
|
|
5109
5179
|
break;
|
|
5110
5180
|
case "app_code+buc":
|
|
5111
|
-
console.log(`${YELLOW}! ${platform.name} 需要 BUC 登录${RESET$1}`);
|
|
5181
|
+
console.log(`${YELLOW$1}! ${platform.name} 需要 BUC 登录${RESET$1}`);
|
|
5112
5182
|
console.log(`${DIM$1}请运行: npx ali-skills login${RESET$1}`);
|
|
5113
5183
|
break;
|
|
5114
5184
|
case "buc_sso_refresh":
|
|
5115
5185
|
case "buc_sso_ticket":
|
|
5116
|
-
console.log(`${YELLOW}! ${platform.name} 需要 BUC 登录${RESET$1}`);
|
|
5186
|
+
console.log(`${YELLOW$1}! ${platform.name} 需要 BUC 登录${RESET$1}`);
|
|
5117
5187
|
console.log(`${DIM$1}请运行: npx ali-skills login${RESET$1}`);
|
|
5118
5188
|
break;
|
|
5119
5189
|
default:
|
|
@@ -5210,6 +5280,7 @@ const RESET = "\x1B[0m";
|
|
|
5210
5280
|
const BOLD = "\x1B[1m";
|
|
5211
5281
|
const DIM = "\x1B[38;5;102m";
|
|
5212
5282
|
const TEXT = "\x1B[38;5;145m";
|
|
5283
|
+
const YELLOW = "\x1B[33m";
|
|
5213
5284
|
const LOGO_LINES = [
|
|
5214
5285
|
" █████╗ ██╗ ██╗ ███████╗██╗ ██╗██╗██╗ ██╗ ███████╗",
|
|
5215
5286
|
"██╔══██╗██║ ██║ ██╔════╝██║ ██╔╝██║██║ ██║ ██╔════╝",
|
|
@@ -5571,26 +5642,42 @@ function readSkillLock() {
|
|
|
5571
5642
|
try {
|
|
5572
5643
|
const content = readFileSync(lockPath, "utf-8");
|
|
5573
5644
|
const parsed = JSON.parse(content);
|
|
5574
|
-
if (typeof parsed.version !== "number"
|
|
5575
|
-
|
|
5576
|
-
|
|
5645
|
+
if (typeof parsed.version !== "number") return {
|
|
5646
|
+
lock: {
|
|
5647
|
+
...parsed,
|
|
5648
|
+
version: CURRENT_LOCK_VERSION
|
|
5649
|
+
},
|
|
5650
|
+
isOutdated: true
|
|
5577
5651
|
};
|
|
5578
5652
|
if (parsed.version < CURRENT_LOCK_VERSION) return {
|
|
5579
|
-
|
|
5580
|
-
|
|
5653
|
+
lock: parsed,
|
|
5654
|
+
isOutdated: true
|
|
5655
|
+
};
|
|
5656
|
+
if (!parsed.skills) return {
|
|
5657
|
+
lock: {
|
|
5658
|
+
version: CURRENT_LOCK_VERSION,
|
|
5659
|
+
skills: {}
|
|
5660
|
+
},
|
|
5661
|
+
isOutdated: false
|
|
5662
|
+
};
|
|
5663
|
+
return {
|
|
5664
|
+
lock: parsed,
|
|
5665
|
+
isOutdated: false
|
|
5581
5666
|
};
|
|
5582
|
-
return parsed;
|
|
5583
5667
|
} catch {
|
|
5584
5668
|
return {
|
|
5585
|
-
|
|
5586
|
-
|
|
5669
|
+
lock: {
|
|
5670
|
+
version: CURRENT_LOCK_VERSION,
|
|
5671
|
+
skills: {}
|
|
5672
|
+
},
|
|
5673
|
+
isOutdated: false
|
|
5587
5674
|
};
|
|
5588
5675
|
}
|
|
5589
5676
|
}
|
|
5590
5677
|
function getSkipReason(entry) {
|
|
5591
5678
|
if (entry.sourceType === "local") return "Local path";
|
|
5592
5679
|
if (entry.sourceType === "git") return "Git URL (hash tracking not supported)";
|
|
5593
|
-
if (!entry.skillFolderHash) return "No version hash available";
|
|
5680
|
+
if (!(entry.sourceType === "internal" ? entry.commitHash : entry.skillFolderHash)) return "No version hash available";
|
|
5594
5681
|
if (!entry.skillPath) return "No skill path recorded";
|
|
5595
5682
|
return "No version tracking";
|
|
5596
5683
|
}
|
|
@@ -5599,6 +5686,39 @@ async function checkSkillsForUpdates(skills, token) {
|
|
|
5599
5686
|
const errors = [];
|
|
5600
5687
|
const skipped = [];
|
|
5601
5688
|
for (const [skillName, entry] of Object.entries(skills)) {
|
|
5689
|
+
if (entry.sourceType === "internal") {
|
|
5690
|
+
if (!entry.commitHash || !entry.skillPath) {
|
|
5691
|
+
skipped.push({
|
|
5692
|
+
name: skillName,
|
|
5693
|
+
reason: getSkipReason(entry),
|
|
5694
|
+
sourceUrl: entry.sourceUrl
|
|
5695
|
+
});
|
|
5696
|
+
continue;
|
|
5697
|
+
}
|
|
5698
|
+
try {
|
|
5699
|
+
const latestCommit = await fetchAliInternalCommitHash(entry.source, entry.skillPath, null);
|
|
5700
|
+
if (!latestCommit) {
|
|
5701
|
+
errors.push({
|
|
5702
|
+
name: skillName,
|
|
5703
|
+
source: entry.source,
|
|
5704
|
+
error: "Could not fetch from GitLab"
|
|
5705
|
+
});
|
|
5706
|
+
continue;
|
|
5707
|
+
}
|
|
5708
|
+
if (latestCommit !== entry.commitHash) updates.push({
|
|
5709
|
+
name: skillName,
|
|
5710
|
+
source: entry.source,
|
|
5711
|
+
entry
|
|
5712
|
+
});
|
|
5713
|
+
} catch (err) {
|
|
5714
|
+
errors.push({
|
|
5715
|
+
name: skillName,
|
|
5716
|
+
source: entry.source,
|
|
5717
|
+
error: err instanceof Error ? err.message : "Unknown error"
|
|
5718
|
+
});
|
|
5719
|
+
}
|
|
5720
|
+
continue;
|
|
5721
|
+
}
|
|
5602
5722
|
if (!entry.skillFolderHash || !entry.skillPath) {
|
|
5603
5723
|
skipped.push({
|
|
5604
5724
|
name: skillName,
|
|
@@ -5645,7 +5765,7 @@ async function runCheck(args = []) {
|
|
|
5645
5765
|
let skipped = [];
|
|
5646
5766
|
let skillCount = 0;
|
|
5647
5767
|
if (isGlobal) {
|
|
5648
|
-
const globalLock = readSkillLock();
|
|
5768
|
+
const { lock: globalLock, isOutdated: isGlobalLockOutdated } = readSkillLock();
|
|
5649
5769
|
const globalSkillNames = Object.keys(globalLock.skills);
|
|
5650
5770
|
skillCount = globalSkillNames.length;
|
|
5651
5771
|
if (globalSkillNames.length === 0) {
|
|
@@ -5667,9 +5787,11 @@ async function runCheck(args = []) {
|
|
|
5667
5787
|
if (skipped.length > 0) {
|
|
5668
5788
|
console.log();
|
|
5669
5789
|
console.log(`${DIM} ${skipped.length} skill(s) cannot be checked automatically:${RESET}`);
|
|
5790
|
+
if (isGlobalLockOutdated) console.log(`${YELLOW} Note: Your lock file may be outdated. Re-adding these skills may fix this.${RESET}`);
|
|
5670
5791
|
for (const skill of skipped) {
|
|
5671
5792
|
console.log(` ${TEXT}•${RESET} ${skill.name} ${DIM}(${skill.reason})${RESET}`);
|
|
5672
|
-
|
|
5793
|
+
const displaySource = getDisplaySource(skill.sourceUrl);
|
|
5794
|
+
console.log(` ${DIM}To update: ${TEXT}npx ali-skills add ${displaySource} -g -y${RESET}`);
|
|
5673
5795
|
}
|
|
5674
5796
|
}
|
|
5675
5797
|
console.log();
|
|
@@ -5679,7 +5801,7 @@ async function runCheck(args = []) {
|
|
|
5679
5801
|
console.log(`${DIM}Run${RESET} ${TEXT}npx ali-skills update -g${RESET} ${DIM}to update all global skills${RESET}`);
|
|
5680
5802
|
}
|
|
5681
5803
|
} else {
|
|
5682
|
-
const projectLock = await readLocalLock();
|
|
5804
|
+
const { lock: projectLock, isOutdated: isLocalLockOutdated } = await readLocalLock();
|
|
5683
5805
|
const projectSkillNames = Object.keys(projectLock.skills);
|
|
5684
5806
|
skillCount = projectSkillNames.length;
|
|
5685
5807
|
if (projectSkillNames.length === 0) {
|
|
@@ -5773,6 +5895,7 @@ async function runCheck(args = []) {
|
|
|
5773
5895
|
if (skipped.length > 0) {
|
|
5774
5896
|
console.log();
|
|
5775
5897
|
console.log(`${DIM} ${skipped.length} skill(s) cannot be checked automatically:${RESET}`);
|
|
5898
|
+
if (isLocalLockOutdated) console.log(`${YELLOW} Note: Your lock file may be outdated. Re-adding these skills may fix this.${RESET}`);
|
|
5776
5899
|
for (const skill of skipped) console.log(` ${TEXT}•${RESET} ${skill.name} ${DIM}(${skill.reason})${RESET}`);
|
|
5777
5900
|
}
|
|
5778
5901
|
console.log();
|
|
@@ -5800,10 +5923,11 @@ async function runUpdate(args = []) {
|
|
|
5800
5923
|
let skillsToCheck = {};
|
|
5801
5924
|
let scopeLabel = "project";
|
|
5802
5925
|
if (isGlobal) {
|
|
5803
|
-
|
|
5926
|
+
const { lock: globalLock } = readSkillLock();
|
|
5927
|
+
skillsToCheck = globalLock.skills;
|
|
5804
5928
|
scopeLabel = "global";
|
|
5805
5929
|
} else {
|
|
5806
|
-
const projectLock = await readLocalLock();
|
|
5930
|
+
const { lock: projectLock } = await readLocalLock();
|
|
5807
5931
|
for (const [name, entry] of Object.entries(projectLock.skills)) {
|
|
5808
5932
|
let sourceUrl;
|
|
5809
5933
|
if (entry.sourceType === "github") sourceUrl = `https://github.com/${entry.source}`;
|
|
@@ -5829,7 +5953,7 @@ async function runUpdate(args = []) {
|
|
|
5829
5953
|
}
|
|
5830
5954
|
const availableUpdates = [];
|
|
5831
5955
|
const skipped = [];
|
|
5832
|
-
const projectLock = !isGlobal ? await readLocalLock() : null;
|
|
5956
|
+
const projectLock = (!isGlobal ? await readLocalLock() : null)?.lock ?? null;
|
|
5833
5957
|
for (const skillName of skillNames) {
|
|
5834
5958
|
const entry = skillsToCheck[skillName];
|
|
5835
5959
|
if (!entry) continue;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "ali-skills",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.16",
|
|
4
4
|
"description": "The open agent skills ecosystem",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"bin": {
|
|
@@ -31,7 +31,7 @@
|
|
|
31
31
|
"author": "",
|
|
32
32
|
"license": "MIT",
|
|
33
33
|
"dependencies": {
|
|
34
|
-
"@ali/cli-skills": "^2.0.
|
|
34
|
+
"@ali/cli-skills": "^2.0.16"
|
|
35
35
|
},
|
|
36
36
|
"bundleDependencies": [
|
|
37
37
|
"@ali/cli-skills"
|