@hasna/skills 0.1.56 → 0.1.58
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/bin/index.js +315 -20
- package/bin/mcp.js +95 -3
- package/dist/index.js +239 -132
- package/dist/lib/hosted-availability.d.ts +13 -0
- package/dist/lib/registry-types.d.ts +7 -0
- package/package.json +1 -1
package/bin/index.js
CHANGED
|
@@ -36860,7 +36860,7 @@ var package_default;
|
|
|
36860
36860
|
var init_package = __esm(() => {
|
|
36861
36861
|
package_default = {
|
|
36862
36862
|
name: "@hasna/skills",
|
|
36863
|
-
version: "0.1.
|
|
36863
|
+
version: "0.1.58",
|
|
36864
36864
|
description: "Skills library for AI coding agents",
|
|
36865
36865
|
type: "module",
|
|
36866
36866
|
bin: {
|
|
@@ -57778,6 +57778,65 @@ var init_auth_store = __esm(() => {
|
|
|
57778
57778
|
LEGACY_AUTH_FILE = join9(homedir4(), ".skills", "auth.json");
|
|
57779
57779
|
});
|
|
57780
57780
|
|
|
57781
|
+
// src/lib/hosted-availability.ts
|
|
57782
|
+
var exports_hosted_availability = {};
|
|
57783
|
+
__export(exports_hosted_availability, {
|
|
57784
|
+
getHostedRunAvailability: () => getHostedRunAvailability,
|
|
57785
|
+
getHostedAvailabilityMetadata: () => getHostedAvailabilityMetadata
|
|
57786
|
+
});
|
|
57787
|
+
function getHostedRunAvailability(slug) {
|
|
57788
|
+
const canonicalSlug = resolveSkillAlias(slug);
|
|
57789
|
+
if (!UNAVAILABLE_HOSTED_PROVIDER_SKILLS.has(canonicalSlug)) {
|
|
57790
|
+
return { ok: true };
|
|
57791
|
+
}
|
|
57792
|
+
return {
|
|
57793
|
+
ok: false,
|
|
57794
|
+
status: 503,
|
|
57795
|
+
code: "HOSTED_PROVIDER_UNAVAILABLE",
|
|
57796
|
+
message: "hosted execution is temporarily unavailable for this skill",
|
|
57797
|
+
details: [
|
|
57798
|
+
"This skill requires a platform-managed execution path that is not enabled for live hosted runs yet.",
|
|
57799
|
+
"No balance was charged."
|
|
57800
|
+
]
|
|
57801
|
+
};
|
|
57802
|
+
}
|
|
57803
|
+
function getHostedAvailabilityMetadata(slug) {
|
|
57804
|
+
const availability = getHostedRunAvailability(slug);
|
|
57805
|
+
if (availability.ok)
|
|
57806
|
+
return { status: "available" };
|
|
57807
|
+
return {
|
|
57808
|
+
status: "unavailable",
|
|
57809
|
+
code: availability.code,
|
|
57810
|
+
message: availability.message,
|
|
57811
|
+
details: availability.details
|
|
57812
|
+
};
|
|
57813
|
+
}
|
|
57814
|
+
var UNAVAILABLE_HOSTED_PROVIDER_SKILLS;
|
|
57815
|
+
var init_hosted_availability = __esm(() => {
|
|
57816
|
+
init_skill_aliases();
|
|
57817
|
+
UNAVAILABLE_HOSTED_PROVIDER_SKILLS = new Set([
|
|
57818
|
+
"audio",
|
|
57819
|
+
"brand-photo-shoot",
|
|
57820
|
+
"browse",
|
|
57821
|
+
"deepresearch",
|
|
57822
|
+
"generate-book-cover",
|
|
57823
|
+
"icon-pack",
|
|
57824
|
+
"image",
|
|
57825
|
+
"music",
|
|
57826
|
+
"music-album",
|
|
57827
|
+
"pdf-read",
|
|
57828
|
+
"photo-album",
|
|
57829
|
+
"playlist-maker",
|
|
57830
|
+
"read-pdf",
|
|
57831
|
+
"remove-background",
|
|
57832
|
+
"short-video-pack",
|
|
57833
|
+
"transcript",
|
|
57834
|
+
"video",
|
|
57835
|
+
"voiceover-jingle-pack",
|
|
57836
|
+
"webcrawling"
|
|
57837
|
+
]);
|
|
57838
|
+
});
|
|
57839
|
+
|
|
57781
57840
|
// src/lib/remote-registry.ts
|
|
57782
57841
|
function getConfiguredApiUrl(config2 = loadConfig(), env3 = process.env) {
|
|
57783
57842
|
const raw = env3["SKILLS_API_URL"] || config2.apiUrl;
|
|
@@ -57819,9 +57878,30 @@ function normalizeRemoteSkill(skill) {
|
|
|
57819
57878
|
dependencies: skill.dependencies,
|
|
57820
57879
|
...skill.version ? { version: skill.version } : {},
|
|
57821
57880
|
...skill.pricing ? { pricing: skill.pricing } : {},
|
|
57881
|
+
availability: normalizeRemoteAvailability(name, skill.availability),
|
|
57822
57882
|
source: "remote"
|
|
57823
57883
|
};
|
|
57824
57884
|
}
|
|
57885
|
+
function normalizeRemoteAvailability(name, availability) {
|
|
57886
|
+
if (!availability)
|
|
57887
|
+
return getHostedAvailabilityMetadata(name);
|
|
57888
|
+
if (availability.status === "available")
|
|
57889
|
+
return { status: "available" };
|
|
57890
|
+
return {
|
|
57891
|
+
status: availability.status,
|
|
57892
|
+
...safeAvailabilityCode(availability.code) ? { code: safeAvailabilityCode(availability.code) } : {},
|
|
57893
|
+
...availability.message ? { message: sanitizeAvailabilityText(availability.message) } : {},
|
|
57894
|
+
...availability.details ? { details: availability.details.map(sanitizeAvailabilityText).filter(Boolean) } : {}
|
|
57895
|
+
};
|
|
57896
|
+
}
|
|
57897
|
+
function safeAvailabilityCode(code) {
|
|
57898
|
+
if (!code)
|
|
57899
|
+
return;
|
|
57900
|
+
return /^[A-Z0-9_]+$/.test(code) ? code : undefined;
|
|
57901
|
+
}
|
|
57902
|
+
function sanitizeAvailabilityText(text) {
|
|
57903
|
+
return secretValuePatterns.reduce((value, pattern) => value.replace(pattern, "credential"), sanitizePublicDiscoveryText(text).replace(/\b[A-Z0-9_]*(?:API_KEY|SECRET|TOKEN|CREDENTIAL)[A-Z0-9_]*\b/g, "credential")).replace(/\s{2,}/g, " ").trim();
|
|
57904
|
+
}
|
|
57825
57905
|
function parseRemoteRegistryPayload(payload) {
|
|
57826
57906
|
const parsed = parseRemoteContract(remoteRegistrySchema, payload, "Remote registry payload did not match the expected skills contract");
|
|
57827
57907
|
const rawSkills = Array.isArray(parsed) ? parsed : ("skills" in parsed) ? parsed.skills : parsed.data;
|
|
@@ -57883,11 +57963,19 @@ async function loadRemoteSkill(name, options = {}) {
|
|
|
57883
57963
|
const url2 = buildSkillsApiUrl(apiUrl, options.endpoint ?? `/skills/${slug}`);
|
|
57884
57964
|
return parseRemoteSkillPayload(await fetchRemoteJson(url2, options));
|
|
57885
57965
|
}
|
|
57886
|
-
var remotePricingSchema, remoteSkillSchema, remoteSkillDetailSchema, remoteRegistrySchema;
|
|
57966
|
+
var remoteAvailabilitySchema, remotePricingSchema, remoteSkillSchema, secretValuePatterns, remoteSkillDetailSchema, remoteRegistrySchema;
|
|
57887
57967
|
var init_remote_registry = __esm(() => {
|
|
57888
57968
|
init_zod();
|
|
57889
57969
|
init_auth_store();
|
|
57890
57970
|
init_config();
|
|
57971
|
+
init_discovery();
|
|
57972
|
+
init_hosted_availability();
|
|
57973
|
+
remoteAvailabilitySchema = exports_external.object({
|
|
57974
|
+
status: exports_external.enum(["available", "unavailable"]),
|
|
57975
|
+
code: exports_external.string().optional(),
|
|
57976
|
+
message: exports_external.string().optional(),
|
|
57977
|
+
details: exports_external.array(exports_external.string()).optional()
|
|
57978
|
+
}).passthrough();
|
|
57891
57979
|
remotePricingSchema = exports_external.object({
|
|
57892
57980
|
formattedCost: exports_external.string(),
|
|
57893
57981
|
tier: exports_external.string().optional(),
|
|
@@ -57909,10 +57997,22 @@ var init_remote_registry = __esm(() => {
|
|
|
57909
57997
|
tags: exports_external.array(exports_external.string()).optional(),
|
|
57910
57998
|
dependencies: exports_external.array(exports_external.string()).optional(),
|
|
57911
57999
|
version: exports_external.string().optional(),
|
|
57912
|
-
pricing: remotePricingSchema.optional()
|
|
58000
|
+
pricing: remotePricingSchema.optional(),
|
|
58001
|
+
availability: remoteAvailabilitySchema.optional()
|
|
57913
58002
|
}).passthrough().refine((skill) => skill.name || skill.slug, {
|
|
57914
58003
|
message: "Remote skill requires name or slug"
|
|
57915
58004
|
});
|
|
58005
|
+
secretValuePatterns = [
|
|
58006
|
+
/\bsk-[A-Za-z0-9_-]{8,}\b/g,
|
|
58007
|
+
/\bgh[opsur]_[A-Za-z0-9_]{8,}\b/g,
|
|
58008
|
+
/\bgithub_pat_[A-Za-z0-9_]{8,}\b/g,
|
|
58009
|
+
/\bnpm_[A-Za-z0-9_]{8,}\b/g,
|
|
58010
|
+
/\bAKIA[A-Z0-9]{12,}\b/g,
|
|
58011
|
+
/\bAIza[A-Za-z0-9_-]{10,}\b/g,
|
|
58012
|
+
new RegExp("\\bsecret" + "-token:\\s*[A-Za-z0-9._-]+", "gi"),
|
|
58013
|
+
/\bctx7sk\-[A-Za-z0-9_-]{8,}\b/g,
|
|
58014
|
+
/\bxai\-[A-Za-z0-9_-]{8,}\b/g
|
|
58015
|
+
];
|
|
57916
58016
|
remoteSkillDetailSchema = exports_external.union([
|
|
57917
58017
|
remoteSkillSchema,
|
|
57918
58018
|
exports_external.object({ skill: remoteSkillSchema }),
|
|
@@ -75774,7 +75874,7 @@ var MCP_CONTRACT_SCHEMA_VERSION = 1, stringSchema = (description) => ({
|
|
|
75774
75874
|
type: "array",
|
|
75775
75875
|
items,
|
|
75776
75876
|
...description ? { description } : {}
|
|
75777
|
-
}), skillNameInput, optionalAgentInput, scopeInput, runInputSchema, runArgsSchema, paidRunApprovalSchema, errorSchema, pricingSchema, skillSummarySchema, toolPrimitiveSummarySchema, skillToolDependencySchema, validationMessageSchema, validationOutputSchema, installOutputSchema, runOutputSchema, toolContracts, contracts, resourceContracts;
|
|
75877
|
+
}), skillNameInput, optionalAgentInput, scopeInput, runInputSchema, runArgsSchema, paidRunApprovalSchema, errorSchema, pricingSchema, skillAvailabilitySchema, skillSummarySchema, toolPrimitiveSummarySchema, skillToolDependencySchema, validationMessageSchema, validationOutputSchema, installOutputSchema, runOutputSchema, toolContracts, contracts, resourceContracts;
|
|
75778
75878
|
var init_mcp_contracts = __esm(() => {
|
|
75779
75879
|
skillNameInput = stringSchema("skill name or alias.");
|
|
75780
75880
|
optionalAgentInput = stringSchema("Optional target agent slug. Use MCP registration instead of direct skill-folder installs.");
|
|
@@ -75812,6 +75912,16 @@ var init_mcp_contracts = __esm(() => {
|
|
|
75812
75912
|
quoteDependsOnInput: { type: "boolean", description: "Whether input affects the quote." },
|
|
75813
75913
|
quoteRequired: { type: "boolean", description: "Whether callers should quote before running." }
|
|
75814
75914
|
}, [], "Public pricing metadata.");
|
|
75915
|
+
skillAvailabilitySchema = objectSchema({
|
|
75916
|
+
status: {
|
|
75917
|
+
type: "string",
|
|
75918
|
+
enum: ["available", "unavailable"],
|
|
75919
|
+
description: "Whether hosted execution is currently available for this skill."
|
|
75920
|
+
},
|
|
75921
|
+
code: stringSchema("Optional stable unavailability code."),
|
|
75922
|
+
message: stringSchema("Optional human-readable availability message."),
|
|
75923
|
+
details: stringArraySchema("Optional availability details.")
|
|
75924
|
+
}, ["status"], "Hosted skill availability metadata.");
|
|
75815
75925
|
skillSummarySchema = objectSchema({
|
|
75816
75926
|
name: stringSchema("Canonical skill slug."),
|
|
75817
75927
|
category: stringSchema("Skill category."),
|
|
@@ -76167,7 +76277,14 @@ var init_mcp_contracts = __esm(() => {
|
|
|
76167
76277
|
sideEffects: "none",
|
|
76168
76278
|
stable: true,
|
|
76169
76279
|
inputSchema: objectSchema({ name: skillNameInput, input: runInputSchema, args: runArgsSchema }, ["name"]),
|
|
76170
|
-
outputSchema: objectSchema({
|
|
76280
|
+
outputSchema: objectSchema({
|
|
76281
|
+
skill: stringSchema("Skill slug."),
|
|
76282
|
+
pricing: pricingSchema,
|
|
76283
|
+
availability: skillAvailabilitySchema,
|
|
76284
|
+
error: stringSchema("Optional error message when the quote cannot be used to run."),
|
|
76285
|
+
code: stringSchema("Optional stable error code."),
|
|
76286
|
+
details: stringArraySchema("Optional error details.")
|
|
76287
|
+
}, ["skill", "pricing", "availability"])
|
|
76171
76288
|
},
|
|
76172
76289
|
{
|
|
76173
76290
|
name: "run_skill",
|
|
@@ -77014,9 +77131,33 @@ function registerOperationTools(server) {
|
|
|
77014
77131
|
return mcpError("INVALID_BLOG_ARTICLE_OPTIONS", validation.errors.join(" "));
|
|
77015
77132
|
}
|
|
77016
77133
|
}
|
|
77134
|
+
const pricing = getPublicSkillPricing2(skill.name, runInput, runArgs);
|
|
77135
|
+
const hostedAvailability = getHostedRunAvailability(skill.name);
|
|
77136
|
+
if (!hostedAvailability.ok) {
|
|
77137
|
+
return {
|
|
77138
|
+
content: [{
|
|
77139
|
+
type: "text",
|
|
77140
|
+
text: JSON.stringify({
|
|
77141
|
+
skill: skill.name,
|
|
77142
|
+
pricing,
|
|
77143
|
+
error: hostedAvailability.message,
|
|
77144
|
+
code: hostedAvailability.code,
|
|
77145
|
+
details: hostedAvailability.details,
|
|
77146
|
+
availability: {
|
|
77147
|
+
status: "unavailable",
|
|
77148
|
+
code: hostedAvailability.code,
|
|
77149
|
+
message: hostedAvailability.message,
|
|
77150
|
+
details: hostedAvailability.details
|
|
77151
|
+
}
|
|
77152
|
+
})
|
|
77153
|
+
}],
|
|
77154
|
+
isError: true
|
|
77155
|
+
};
|
|
77156
|
+
}
|
|
77017
77157
|
return mcpJson({
|
|
77018
77158
|
skill: skill.name,
|
|
77019
|
-
pricing
|
|
77159
|
+
pricing,
|
|
77160
|
+
availability: { status: "available" }
|
|
77020
77161
|
});
|
|
77021
77162
|
});
|
|
77022
77163
|
server.registerTool("run_skill", {
|
|
@@ -77059,6 +77200,18 @@ function registerOperationTools(server) {
|
|
|
77059
77200
|
remote: isPremiumSkill2(skillName),
|
|
77060
77201
|
costCents
|
|
77061
77202
|
});
|
|
77203
|
+
if (isPremiumSkill2(skillName)) {
|
|
77204
|
+
const hostedAvailability = getHostedRunAvailability(skillName);
|
|
77205
|
+
if (!hostedAvailability.ok) {
|
|
77206
|
+
const error48 = `${hostedAvailability.code}: ${hostedAvailability.message}`;
|
|
77207
|
+
writeRunLogs(runContext, "", `${error48}
|
|
77208
|
+
${hostedAvailability.details.join(`
|
|
77209
|
+
`)}
|
|
77210
|
+
`);
|
|
77211
|
+
const run = completeSkillRun(runContext, { status: "failed", error: error48, costCents });
|
|
77212
|
+
return mcpError(hostedAvailability.code, `${hostedAvailability.message}. ${hostedAvailability.details.join(" ")} Local run metadata: ${run.paths.runDir}/run.json`);
|
|
77213
|
+
}
|
|
77214
|
+
}
|
|
77062
77215
|
if (isPremiumSkill2(skillName) && !apiKey) {
|
|
77063
77216
|
const cost = formatCost2(costCents ?? 0);
|
|
77064
77217
|
const error48 = `${skillName} is a hosted skill (${cost}). Run: skills setup --mode hosted && skills auth login`;
|
|
@@ -77302,6 +77455,7 @@ var init_operation_tools = __esm(() => {
|
|
|
77302
77455
|
init_run_state();
|
|
77303
77456
|
init_portable_skills();
|
|
77304
77457
|
init_helpers();
|
|
77458
|
+
init_hosted_availability();
|
|
77305
77459
|
});
|
|
77306
77460
|
|
|
77307
77461
|
// src/lib/feedback.ts
|
|
@@ -78710,7 +78864,20 @@ function handleQuote(name, args2, options) {
|
|
|
78710
78864
|
}
|
|
78711
78865
|
}
|
|
78712
78866
|
const pricing = getPublicSkillPricing(skill.name, {}, quoteArgs);
|
|
78713
|
-
const
|
|
78867
|
+
const hostedAvailability = getHostedRunAvailability(skill.name);
|
|
78868
|
+
if (!hostedAvailability.ok) {
|
|
78869
|
+
const payload2 = unavailableHostedPayload(skill.name, pricing, hostedAvailability);
|
|
78870
|
+
if (json2) {
|
|
78871
|
+
console.log(JSON.stringify(payload2, null, 2));
|
|
78872
|
+
} else {
|
|
78873
|
+
console.error(source_default.red(`${skill.name}: ${hostedAvailability.message}`));
|
|
78874
|
+
for (const detail of hostedAvailability.details)
|
|
78875
|
+
console.error(source_default.dim(` ${detail}`));
|
|
78876
|
+
}
|
|
78877
|
+
process.exitCode = 1;
|
|
78878
|
+
return;
|
|
78879
|
+
}
|
|
78880
|
+
const payload = { skill: skill.name, pricing, availability: { status: "available" } };
|
|
78714
78881
|
if (json2) {
|
|
78715
78882
|
console.log(JSON.stringify(payload, null, 2));
|
|
78716
78883
|
return;
|
|
@@ -78760,6 +78927,32 @@ async function handleRun(name, args2, options) {
|
|
|
78760
78927
|
costCents
|
|
78761
78928
|
});
|
|
78762
78929
|
if (isPremium) {
|
|
78930
|
+
const hostedAvailability = getHostedRunAvailability(skill.name);
|
|
78931
|
+
if (!hostedAvailability.ok) {
|
|
78932
|
+
const payload = unavailableHostedPayload(skill.name, publicPricing, hostedAvailability);
|
|
78933
|
+
const error48 = `${hostedAvailability.code}: ${hostedAvailability.message}`;
|
|
78934
|
+
writeRunLogs(runContext, "", `${error48}
|
|
78935
|
+
${hostedAvailability.details.join(`
|
|
78936
|
+
`)}
|
|
78937
|
+
`);
|
|
78938
|
+
const run = completeSkillRun(runContext, { status: "failed", error: error48, costCents });
|
|
78939
|
+
if (options.json) {
|
|
78940
|
+
console.log(JSON.stringify({
|
|
78941
|
+
contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
|
|
78942
|
+
args: args2,
|
|
78943
|
+
exitCode: 1,
|
|
78944
|
+
remote: true,
|
|
78945
|
+
...payload,
|
|
78946
|
+
run
|
|
78947
|
+
}, null, 2));
|
|
78948
|
+
} else {
|
|
78949
|
+
console.error(source_default.red(`${skill.name}: ${hostedAvailability.message}`));
|
|
78950
|
+
for (const detail of hostedAvailability.details)
|
|
78951
|
+
console.error(source_default.dim(` ${detail}`));
|
|
78952
|
+
}
|
|
78953
|
+
process.exitCode = 1;
|
|
78954
|
+
return;
|
|
78955
|
+
}
|
|
78763
78956
|
const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
|
|
78764
78957
|
const apiKey = getApiKey2();
|
|
78765
78958
|
if (!apiKey) {
|
|
@@ -78912,6 +79105,21 @@ async function handleRun(name, args2, options) {
|
|
|
78912
79105
|
}
|
|
78913
79106
|
process.exitCode = result2.exitCode;
|
|
78914
79107
|
}
|
|
79108
|
+
function unavailableHostedPayload(skill, pricing, availability) {
|
|
79109
|
+
return {
|
|
79110
|
+
skill,
|
|
79111
|
+
pricing,
|
|
79112
|
+
error: availability.message,
|
|
79113
|
+
code: availability.code,
|
|
79114
|
+
details: availability.details,
|
|
79115
|
+
availability: {
|
|
79116
|
+
status: "unavailable",
|
|
79117
|
+
code: availability.code,
|
|
79118
|
+
message: availability.message,
|
|
79119
|
+
details: availability.details
|
|
79120
|
+
}
|
|
79121
|
+
};
|
|
79122
|
+
}
|
|
78915
79123
|
async function approvePaidHostedRun(params) {
|
|
78916
79124
|
if (params.yes)
|
|
78917
79125
|
return { approved: true };
|
|
@@ -79355,6 +79563,7 @@ var init_runtime = __esm(() => {
|
|
|
79355
79563
|
init_skillinfo();
|
|
79356
79564
|
init_pricing();
|
|
79357
79565
|
init_config();
|
|
79566
|
+
init_hosted_availability();
|
|
79358
79567
|
init_run_state();
|
|
79359
79568
|
init_runtime_mcp();
|
|
79360
79569
|
});
|
|
@@ -79822,6 +80031,18 @@ Next: skills schedule list --cursor ${page.nextOffset} --limit ${page.limit}`));
|
|
|
79822
80031
|
return;
|
|
79823
80032
|
}
|
|
79824
80033
|
const dueDetails = await Promise.all(due.map((schedule) => describeDueSchedule(schedule)));
|
|
80034
|
+
const unavailable = dueDetails.filter((schedule) => schedule.availability?.status === "unavailable");
|
|
80035
|
+
if (unavailable.length > 0 && !options.dryRun) {
|
|
80036
|
+
const code = unavailable[0]?.availability?.code ?? "HOSTED_PROVIDER_UNAVAILABLE";
|
|
80037
|
+
const error48 = `Hosted execution is temporarily unavailable for ${unavailable.map((schedule) => schedule.skill).join(", ")}. No balance was charged.`;
|
|
80038
|
+
if (options.json) {
|
|
80039
|
+
console.log(JSON.stringify({ ran: 0, error: error48, code, unavailable, schedules: dueDetails }));
|
|
80040
|
+
} else {
|
|
80041
|
+
console.error(source_default.red(`\u2717 ${error48}`));
|
|
80042
|
+
}
|
|
80043
|
+
process.exitCode = 1;
|
|
80044
|
+
return;
|
|
80045
|
+
}
|
|
79825
80046
|
const paidTotalCents = dueDetails.reduce((total, schedule) => total + (schedule.costCents ?? 0), 0);
|
|
79826
80047
|
if (options.dryRun) {
|
|
79827
80048
|
console.log(options.json ? JSON.stringify({ due: dueDetails, paidTotalCents, paidTotal: formatCost2(paidTotalCents) }) : source_default.bold(`${due.length} schedule(s) due:
|
|
@@ -79907,6 +80128,11 @@ async function executeScheduledSkill(skillName, args2, options) {
|
|
|
79907
80128
|
throw new Error(`Skill '${skillName}' not found`);
|
|
79908
80129
|
const pricing = await Promise.resolve().then(() => (init_pricing(), exports_pricing));
|
|
79909
80130
|
if (pricing.isPremiumSkill(skill.name)) {
|
|
80131
|
+
const { getHostedRunAvailability: getHostedRunAvailability2 } = await Promise.resolve().then(() => (init_hosted_availability(), exports_hosted_availability));
|
|
80132
|
+
const hostedAvailability = getHostedRunAvailability2(skill.name);
|
|
80133
|
+
if (!hostedAvailability.ok) {
|
|
80134
|
+
throw new Error(`${hostedAvailability.code}: ${hostedAvailability.message}. ${hostedAvailability.details.join(" ")}`);
|
|
80135
|
+
}
|
|
79910
80136
|
const publicPricing = pricing.getPublicSkillPricing(skill.name, {}, args2);
|
|
79911
80137
|
if (!options.allowPaid) {
|
|
79912
80138
|
throw new Error(`${skill.name} is a paid hosted skill (${publicPricing.formattedCost}). Review with skills schedule run --dry-run, then rerun with --allow-paid --max-paid-cents ${publicPricing.costCents}.`);
|
|
@@ -79933,16 +80159,24 @@ async function executeScheduledSkill(skillName, args2, options) {
|
|
|
79933
80159
|
async function describeDueSchedule(schedule) {
|
|
79934
80160
|
const { getSkill: getSkill2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
|
|
79935
80161
|
const pricing = await Promise.resolve().then(() => (init_pricing(), exports_pricing));
|
|
80162
|
+
const { getHostedRunAvailability: getHostedRunAvailability2 } = await Promise.resolve().then(() => (init_hosted_availability(), exports_hosted_availability));
|
|
79936
80163
|
const skill = getSkill2(schedule.skill);
|
|
79937
80164
|
const paid = Boolean(skill && pricing.isPremiumSkill(skill.name));
|
|
79938
80165
|
const publicPricing = paid && skill ? pricing.getPublicSkillPricing(skill.name, {}, schedule.args ?? []) : null;
|
|
80166
|
+
const availability = skill ? getHostedRunAvailability2(skill.name) : { ok: true };
|
|
79939
80167
|
return {
|
|
79940
80168
|
name: schedule.name,
|
|
79941
80169
|
skill: schedule.skill,
|
|
79942
80170
|
cron: schedule.cron,
|
|
79943
80171
|
paid,
|
|
79944
80172
|
costCents: publicPricing?.costCents,
|
|
79945
|
-
cost: publicPricing?.formattedCost
|
|
80173
|
+
cost: publicPricing?.formattedCost,
|
|
80174
|
+
availability: availability.ok ? { status: "available" } : {
|
|
80175
|
+
status: "unavailable",
|
|
80176
|
+
code: availability.code,
|
|
80177
|
+
message: availability.message,
|
|
80178
|
+
details: availability.details
|
|
80179
|
+
}
|
|
79946
80180
|
};
|
|
79947
80181
|
}
|
|
79948
80182
|
function parseMaxPaidCents(value) {
|
|
@@ -80164,6 +80398,54 @@ function writeCommandError(err, fallback, json2) {
|
|
|
80164
80398
|
console.error(source_default.red(String(payload.detail || payload.error || fallback)));
|
|
80165
80399
|
process.exitCode = 1;
|
|
80166
80400
|
}
|
|
80401
|
+
function envApiKey() {
|
|
80402
|
+
const key = process.env.SKILLS_API_KEY || process.env.SKILL_API_KEY;
|
|
80403
|
+
const trimmed = key?.trim();
|
|
80404
|
+
return trimmed || null;
|
|
80405
|
+
}
|
|
80406
|
+
function stringField2(value) {
|
|
80407
|
+
return typeof value === "string" && value.length > 0 ? value : undefined;
|
|
80408
|
+
}
|
|
80409
|
+
function recordField(value) {
|
|
80410
|
+
return isRecord3(value) ? value : undefined;
|
|
80411
|
+
}
|
|
80412
|
+
function authIdentityPayload(authSource, live, cached2, offline = false) {
|
|
80413
|
+
const root = recordField(live) ?? {};
|
|
80414
|
+
const data = recordField(root.data);
|
|
80415
|
+
const user = recordField(root.user) ?? recordField(data?.user);
|
|
80416
|
+
const organization = recordField(root.organization) ?? recordField(root.org) ?? recordField(data?.organization);
|
|
80417
|
+
const email3 = stringField2(user?.email) ?? cached2?.email;
|
|
80418
|
+
const orgSlug = stringField2(organization?.slug) ?? cached2?.orgSlug;
|
|
80419
|
+
const orgName = stringField2(organization?.name);
|
|
80420
|
+
const userId = stringField2(user?.id) ?? cached2?.userId;
|
|
80421
|
+
const orgId = stringField2(organization?.id) ?? cached2?.orgId;
|
|
80422
|
+
const role = stringField2(user?.role);
|
|
80423
|
+
return {
|
|
80424
|
+
status: "authenticated",
|
|
80425
|
+
authSource,
|
|
80426
|
+
...offline ? { offline: true } : {},
|
|
80427
|
+
...email3 ? { email: email3 } : {},
|
|
80428
|
+
...orgSlug ? { organization: orgSlug } : {},
|
|
80429
|
+
...orgName ? { organizationName: orgName } : {},
|
|
80430
|
+
...userId ? { userId } : {},
|
|
80431
|
+
...orgId ? { orgId } : {},
|
|
80432
|
+
...role ? { role } : {}
|
|
80433
|
+
};
|
|
80434
|
+
}
|
|
80435
|
+
function printWhoami(payload) {
|
|
80436
|
+
if (payload.email)
|
|
80437
|
+
console.log(source_default.bold("Email: ") + payload.email);
|
|
80438
|
+
if (payload.organization)
|
|
80439
|
+
console.log(source_default.bold("Org: ") + payload.organization);
|
|
80440
|
+
if (payload.role)
|
|
80441
|
+
console.log(source_default.bold("Role: ") + payload.role);
|
|
80442
|
+
if (payload.organizationName)
|
|
80443
|
+
console.log(source_default.bold("Name: ") + payload.organizationName);
|
|
80444
|
+
if (payload.authSource === "env")
|
|
80445
|
+
console.log(source_default.dim("Auth: SKILLS_API_KEY"));
|
|
80446
|
+
if (payload.offline)
|
|
80447
|
+
console.log(source_default.dim("(offline \u2014 showing cached info)"));
|
|
80448
|
+
}
|
|
80167
80449
|
function sleep(ms) {
|
|
80168
80450
|
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
80169
80451
|
}
|
|
@@ -80428,26 +80710,39 @@ function registerAuth(parent) {
|
|
|
80428
80710
|
clearAuthConfig();
|
|
80429
80711
|
console.log(source_default.green(`\u2713 Signed out (was ${existing.email})`));
|
|
80430
80712
|
});
|
|
80431
|
-
auth.command("whoami").description("Show current account info").action(async () => {
|
|
80713
|
+
auth.command("whoami").description("Show current account info").option("--json", "Output as JSON", false).action(async (options) => {
|
|
80714
|
+
const envKey = envApiKey();
|
|
80432
80715
|
const config2 = getAuthConfig();
|
|
80433
|
-
|
|
80434
|
-
|
|
80716
|
+
const apiKey = envKey ?? config2?.apiKey;
|
|
80717
|
+
if (!apiKey) {
|
|
80718
|
+
const payload = { status: "unauthenticated", error: "Not signed in. Run: skills auth login" };
|
|
80719
|
+
if (options.json)
|
|
80720
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
80721
|
+
else
|
|
80722
|
+
console.log(source_default.dim(payload.error));
|
|
80435
80723
|
return;
|
|
80436
80724
|
}
|
|
80437
|
-
|
|
80438
|
-
console.log(source_default.bold("Org: ") + config2.orgSlug);
|
|
80725
|
+
const authSource = envKey ? "env" : "stored";
|
|
80439
80726
|
try {
|
|
80440
80727
|
const res = await apiRequest("/api/auth/whoami", {
|
|
80441
|
-
headers: { Authorization: `Bearer ${
|
|
80728
|
+
headers: { Authorization: `Bearer ${apiKey}` }
|
|
80442
80729
|
});
|
|
80443
|
-
|
|
80444
|
-
|
|
80730
|
+
const payload = authIdentityPayload(authSource, res, envKey ? null : config2);
|
|
80731
|
+
if (options.json) {
|
|
80732
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
80733
|
+
} else {
|
|
80734
|
+
printWhoami(payload);
|
|
80445
80735
|
}
|
|
80446
|
-
|
|
80447
|
-
|
|
80736
|
+
} catch (err) {
|
|
80737
|
+
if (config2 && !envKey) {
|
|
80738
|
+
const payload = authIdentityPayload("stored", {}, config2, true);
|
|
80739
|
+
if (options.json)
|
|
80740
|
+
console.log(JSON.stringify(payload, null, 2));
|
|
80741
|
+
else
|
|
80742
|
+
printWhoami(payload);
|
|
80743
|
+
return;
|
|
80448
80744
|
}
|
|
80449
|
-
|
|
80450
|
-
console.log(source_default.dim("(offline \u2014 showing cached info)"));
|
|
80745
|
+
writeCommandError(err, "Failed to fetch current account", options.json);
|
|
80451
80746
|
}
|
|
80452
80747
|
});
|
|
80453
80748
|
auth.command("status").description("Show hosted billing status").option("--json", "Output as JSON", false).action(handleBillingStatus);
|
package/bin/mcp.js
CHANGED
|
@@ -21819,7 +21819,7 @@ class StdioServerTransport {
|
|
|
21819
21819
|
// package.json
|
|
21820
21820
|
var package_default = {
|
|
21821
21821
|
name: "@hasna/skills",
|
|
21822
|
-
version: "0.1.
|
|
21822
|
+
version: "0.1.58",
|
|
21823
21823
|
description: "Skills library for AI coding agents",
|
|
21824
21824
|
type: "module",
|
|
21825
21825
|
bin: {
|
|
@@ -33056,6 +33056,16 @@ var pricingSchema = objectSchema({
|
|
|
33056
33056
|
quoteDependsOnInput: { type: "boolean", description: "Whether input affects the quote." },
|
|
33057
33057
|
quoteRequired: { type: "boolean", description: "Whether callers should quote before running." }
|
|
33058
33058
|
}, [], "Public pricing metadata.");
|
|
33059
|
+
var skillAvailabilitySchema = objectSchema({
|
|
33060
|
+
status: {
|
|
33061
|
+
type: "string",
|
|
33062
|
+
enum: ["available", "unavailable"],
|
|
33063
|
+
description: "Whether hosted execution is currently available for this skill."
|
|
33064
|
+
},
|
|
33065
|
+
code: stringSchema("Optional stable unavailability code."),
|
|
33066
|
+
message: stringSchema("Optional human-readable availability message."),
|
|
33067
|
+
details: stringArraySchema("Optional availability details.")
|
|
33068
|
+
}, ["status"], "Hosted skill availability metadata.");
|
|
33059
33069
|
var skillSummarySchema = objectSchema({
|
|
33060
33070
|
name: stringSchema("Canonical skill slug."),
|
|
33061
33071
|
category: stringSchema("Skill category."),
|
|
@@ -33411,7 +33421,14 @@ var toolContracts = [
|
|
|
33411
33421
|
sideEffects: "none",
|
|
33412
33422
|
stable: true,
|
|
33413
33423
|
inputSchema: objectSchema({ name: skillNameInput, input: runInputSchema, args: runArgsSchema }, ["name"]),
|
|
33414
|
-
outputSchema: objectSchema({
|
|
33424
|
+
outputSchema: objectSchema({
|
|
33425
|
+
skill: stringSchema("Skill slug."),
|
|
33426
|
+
pricing: pricingSchema,
|
|
33427
|
+
availability: skillAvailabilitySchema,
|
|
33428
|
+
error: stringSchema("Optional error message when the quote cannot be used to run."),
|
|
33429
|
+
code: stringSchema("Optional stable error code."),
|
|
33430
|
+
details: stringArraySchema("Optional error details.")
|
|
33431
|
+
}, ["skill", "pricing", "availability"])
|
|
33415
33432
|
},
|
|
33416
33433
|
{
|
|
33417
33434
|
name: "run_skill",
|
|
@@ -34829,6 +34846,45 @@ function mimeForPath(path) {
|
|
|
34829
34846
|
return "application/octet-stream";
|
|
34830
34847
|
}
|
|
34831
34848
|
}
|
|
34849
|
+
// src/lib/hosted-availability.ts
|
|
34850
|
+
init_skill_aliases();
|
|
34851
|
+
var UNAVAILABLE_HOSTED_PROVIDER_SKILLS = new Set([
|
|
34852
|
+
"audio",
|
|
34853
|
+
"brand-photo-shoot",
|
|
34854
|
+
"browse",
|
|
34855
|
+
"deepresearch",
|
|
34856
|
+
"generate-book-cover",
|
|
34857
|
+
"icon-pack",
|
|
34858
|
+
"image",
|
|
34859
|
+
"music",
|
|
34860
|
+
"music-album",
|
|
34861
|
+
"pdf-read",
|
|
34862
|
+
"photo-album",
|
|
34863
|
+
"playlist-maker",
|
|
34864
|
+
"read-pdf",
|
|
34865
|
+
"remove-background",
|
|
34866
|
+
"short-video-pack",
|
|
34867
|
+
"transcript",
|
|
34868
|
+
"video",
|
|
34869
|
+
"voiceover-jingle-pack",
|
|
34870
|
+
"webcrawling"
|
|
34871
|
+
]);
|
|
34872
|
+
function getHostedRunAvailability(slug) {
|
|
34873
|
+
const canonicalSlug = resolveSkillAlias(slug);
|
|
34874
|
+
if (!UNAVAILABLE_HOSTED_PROVIDER_SKILLS.has(canonicalSlug)) {
|
|
34875
|
+
return { ok: true };
|
|
34876
|
+
}
|
|
34877
|
+
return {
|
|
34878
|
+
ok: false,
|
|
34879
|
+
status: 503,
|
|
34880
|
+
code: "HOSTED_PROVIDER_UNAVAILABLE",
|
|
34881
|
+
message: "hosted execution is temporarily unavailable for this skill",
|
|
34882
|
+
details: [
|
|
34883
|
+
"This skill requires a platform-managed execution path that is not enabled for live hosted runs yet.",
|
|
34884
|
+
"No balance was charged."
|
|
34885
|
+
]
|
|
34886
|
+
};
|
|
34887
|
+
}
|
|
34832
34888
|
|
|
34833
34889
|
// src/mcp/operation-tools.ts
|
|
34834
34890
|
function registerOperationTools(server) {
|
|
@@ -35045,9 +35101,33 @@ function registerOperationTools(server) {
|
|
|
35045
35101
|
return mcpError("INVALID_BLOG_ARTICLE_OPTIONS", validation.errors.join(" "));
|
|
35046
35102
|
}
|
|
35047
35103
|
}
|
|
35104
|
+
const pricing = getPublicSkillPricing2(skill.name, runInput, runArgs);
|
|
35105
|
+
const hostedAvailability = getHostedRunAvailability(skill.name);
|
|
35106
|
+
if (!hostedAvailability.ok) {
|
|
35107
|
+
return {
|
|
35108
|
+
content: [{
|
|
35109
|
+
type: "text",
|
|
35110
|
+
text: JSON.stringify({
|
|
35111
|
+
skill: skill.name,
|
|
35112
|
+
pricing,
|
|
35113
|
+
error: hostedAvailability.message,
|
|
35114
|
+
code: hostedAvailability.code,
|
|
35115
|
+
details: hostedAvailability.details,
|
|
35116
|
+
availability: {
|
|
35117
|
+
status: "unavailable",
|
|
35118
|
+
code: hostedAvailability.code,
|
|
35119
|
+
message: hostedAvailability.message,
|
|
35120
|
+
details: hostedAvailability.details
|
|
35121
|
+
}
|
|
35122
|
+
})
|
|
35123
|
+
}],
|
|
35124
|
+
isError: true
|
|
35125
|
+
};
|
|
35126
|
+
}
|
|
35048
35127
|
return mcpJson({
|
|
35049
35128
|
skill: skill.name,
|
|
35050
|
-
pricing
|
|
35129
|
+
pricing,
|
|
35130
|
+
availability: { status: "available" }
|
|
35051
35131
|
});
|
|
35052
35132
|
});
|
|
35053
35133
|
server.registerTool("run_skill", {
|
|
@@ -35090,6 +35170,18 @@ function registerOperationTools(server) {
|
|
|
35090
35170
|
remote: isPremiumSkill2(skillName),
|
|
35091
35171
|
costCents
|
|
35092
35172
|
});
|
|
35173
|
+
if (isPremiumSkill2(skillName)) {
|
|
35174
|
+
const hostedAvailability = getHostedRunAvailability(skillName);
|
|
35175
|
+
if (!hostedAvailability.ok) {
|
|
35176
|
+
const error48 = `${hostedAvailability.code}: ${hostedAvailability.message}`;
|
|
35177
|
+
writeRunLogs(runContext, "", `${error48}
|
|
35178
|
+
${hostedAvailability.details.join(`
|
|
35179
|
+
`)}
|
|
35180
|
+
`);
|
|
35181
|
+
const run = completeSkillRun(runContext, { status: "failed", error: error48, costCents });
|
|
35182
|
+
return mcpError(hostedAvailability.code, `${hostedAvailability.message}. ${hostedAvailability.details.join(" ")} Local run metadata: ${run.paths.runDir}/run.json`);
|
|
35183
|
+
}
|
|
35184
|
+
}
|
|
35093
35185
|
if (isPremiumSkill2(skillName) && !apiKey) {
|
|
35094
35186
|
const cost = formatCost2(costCents ?? 0);
|
|
35095
35187
|
const error48 = `${skillName} is a hosted skill (${cost}). Run: skills setup --mode hosted && skills auth login`;
|
package/dist/index.js
CHANGED
|
@@ -18159,7 +18159,193 @@ function getApiUrl() {
|
|
|
18159
18159
|
return normalizeSkillsApiOrigin(process.env.SKILLS_API_URL || loadConfig().apiUrl || "https://skills.md");
|
|
18160
18160
|
}
|
|
18161
18161
|
|
|
18162
|
+
// src/lib/discovery.ts
|
|
18163
|
+
var VENDOR_TERMS = [
|
|
18164
|
+
"Google Gemini",
|
|
18165
|
+
"OpenAI Sora",
|
|
18166
|
+
"MiniMax Hailuo",
|
|
18167
|
+
"Claude Code",
|
|
18168
|
+
"Claude Vision",
|
|
18169
|
+
"DALL-E 3",
|
|
18170
|
+
"GPT-4o Mini",
|
|
18171
|
+
"Cerebras",
|
|
18172
|
+
"OpenRouter",
|
|
18173
|
+
"Firecrawl",
|
|
18174
|
+
"ElevenLabs",
|
|
18175
|
+
"Anthropic",
|
|
18176
|
+
"OpenAI",
|
|
18177
|
+
"Minimax",
|
|
18178
|
+
"MiniMax",
|
|
18179
|
+
"Gemini",
|
|
18180
|
+
"Claude",
|
|
18181
|
+
"Whisper",
|
|
18182
|
+
"Seedance",
|
|
18183
|
+
"Lyria",
|
|
18184
|
+
"Sora",
|
|
18185
|
+
"Veo",
|
|
18186
|
+
"Exa.ai",
|
|
18187
|
+
"Exa",
|
|
18188
|
+
"XAI",
|
|
18189
|
+
"xAI"
|
|
18190
|
+
];
|
|
18191
|
+
var VENDOR_TAGS = new Set([
|
|
18192
|
+
"anthropic",
|
|
18193
|
+
"cerebras",
|
|
18194
|
+
"claude",
|
|
18195
|
+
"exa",
|
|
18196
|
+
"firecrawl",
|
|
18197
|
+
"gemini",
|
|
18198
|
+
"google",
|
|
18199
|
+
"minimax",
|
|
18200
|
+
"openai",
|
|
18201
|
+
"openrouter",
|
|
18202
|
+
"seedance",
|
|
18203
|
+
"whisper",
|
|
18204
|
+
"xai"
|
|
18205
|
+
]);
|
|
18206
|
+
var VENDOR_ENV_PREFIXES = [
|
|
18207
|
+
"ANTHROPIC_",
|
|
18208
|
+
"CEREBRAS_",
|
|
18209
|
+
"EXA_",
|
|
18210
|
+
"FIRECRAWL_",
|
|
18211
|
+
"GEMINI_",
|
|
18212
|
+
"GOOGLE_",
|
|
18213
|
+
"MINIMAX_",
|
|
18214
|
+
"OPENAI_",
|
|
18215
|
+
"OPENROUTER_",
|
|
18216
|
+
"XAI_"
|
|
18217
|
+
];
|
|
18218
|
+
var VENDOR_PACKAGE_PATTERNS = [
|
|
18219
|
+
/anthropic/i,
|
|
18220
|
+
/cerebras/i,
|
|
18221
|
+
/exa/i,
|
|
18222
|
+
/firecrawl/i,
|
|
18223
|
+
/gemini/i,
|
|
18224
|
+
/minimax/i,
|
|
18225
|
+
/openai/i,
|
|
18226
|
+
/openrouter/i,
|
|
18227
|
+
/xai/i
|
|
18228
|
+
];
|
|
18229
|
+
var vendorPattern = new RegExp(`\\b(${VENDOR_TERMS.map(escapeRegExp).join("|")})\\b`, "gi");
|
|
18230
|
+
function getCompactSkillDiscovery(skill) {
|
|
18231
|
+
return {
|
|
18232
|
+
name: skill.name,
|
|
18233
|
+
category: skill.category,
|
|
18234
|
+
pricing: resolveDiscoveryPricing(skill)
|
|
18235
|
+
};
|
|
18236
|
+
}
|
|
18237
|
+
function getPublicSkillDiscovery(skill) {
|
|
18238
|
+
return {
|
|
18239
|
+
...skill,
|
|
18240
|
+
description: sanitizePublicDiscoveryText(skill.description),
|
|
18241
|
+
tags: publicDiscoveryTags(skill.tags),
|
|
18242
|
+
pricing: resolveDiscoveryPricing(skill)
|
|
18243
|
+
};
|
|
18244
|
+
}
|
|
18245
|
+
function publicDiscoveryPriceLabel(skill) {
|
|
18246
|
+
return (skill.pricing ?? getPublicSkillPricing(skill.name)).formattedCost;
|
|
18247
|
+
}
|
|
18248
|
+
function publicDiscoveryTags(tags) {
|
|
18249
|
+
return tags.filter((tag) => !VENDOR_TAGS.has(tag.toLowerCase()));
|
|
18250
|
+
}
|
|
18251
|
+
function sanitizePublicDiscoveryText(text) {
|
|
18252
|
+
let sanitized = text.replace(vendorPattern, "hosted AI").replace(/\bLLM\b/g, "AI").replace(/\s{2,}/g, " ");
|
|
18253
|
+
let previous;
|
|
18254
|
+
do {
|
|
18255
|
+
previous = sanitized;
|
|
18256
|
+
sanitized = sanitized.replace(/\bhosted AI(?: providers)?\s*,\s*hosted AI(?: providers)?\b/gi, "hosted AI providers").replace(/\bhosted AI(?: providers)?\s*,?\s*and\s*hosted AI(?: providers)?\b/gi, "hosted AI providers").replace(/\bhosted AI(?: providers)?\s+or\s+hosted AI(?: providers)?\b/gi, "hosted AI providers").replace(/\bhosted AI providers\s+hosted AI\b/gi, "hosted AI providers").replace(/\bhosted AI providers\s+providers\b/gi, "hosted AI providers");
|
|
18257
|
+
} while (sanitized !== previous);
|
|
18258
|
+
return sanitized.trim();
|
|
18259
|
+
}
|
|
18260
|
+
function publicDiscoveryEnvVars(skillName, envVars) {
|
|
18261
|
+
if (!isPremiumSkill(skillName))
|
|
18262
|
+
return envVars;
|
|
18263
|
+
const filtered = envVars.filter((envVar) => envVar !== "SKILL_API_KEY" && !VENDOR_ENV_PREFIXES.some((prefix) => envVar.startsWith(prefix)));
|
|
18264
|
+
return filtered.includes("SKILLS_API_KEY") ? filtered : ["SKILLS_API_KEY", ...filtered];
|
|
18265
|
+
}
|
|
18266
|
+
function publicDiscoveryDependencies(skillName, dependencies) {
|
|
18267
|
+
if (!isPremiumSkill(skillName))
|
|
18268
|
+
return dependencies;
|
|
18269
|
+
return Object.fromEntries(Object.entries(dependencies).filter(([name]) => !VENDOR_PACKAGE_PATTERNS.some((pattern) => pattern.test(name))));
|
|
18270
|
+
}
|
|
18271
|
+
function publicDiscoveryDocumentation(skill, documentation) {
|
|
18272
|
+
if (!documentation)
|
|
18273
|
+
return documentation;
|
|
18274
|
+
if (!isPremiumSkill(skill.name))
|
|
18275
|
+
return documentation;
|
|
18276
|
+
return [
|
|
18277
|
+
`# ${skill.displayName || skill.name}`,
|
|
18278
|
+
sanitizePublicDiscoveryText(skill.description),
|
|
18279
|
+
`Pricing: ${getPublicSkillPricing(skill.name).formattedCost}.`,
|
|
18280
|
+
"Set `SKILLS_API_KEY` or run `skills auth login` for hosted runtime execution. Runtime routing and model selection are managed by the hosted Skills runtime."
|
|
18281
|
+
].join(`
|
|
18282
|
+
|
|
18283
|
+
`);
|
|
18284
|
+
}
|
|
18285
|
+
function escapeRegExp(value) {
|
|
18286
|
+
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
18287
|
+
}
|
|
18288
|
+
function resolveDiscoveryPricing(skill) {
|
|
18289
|
+
return skill.pricing && typeof skill.pricing.formattedCost === "string" ? skill.pricing : getPublicSkillPricing(skill.name);
|
|
18290
|
+
}
|
|
18291
|
+
|
|
18292
|
+
// src/lib/hosted-availability.ts
|
|
18293
|
+
var UNAVAILABLE_HOSTED_PROVIDER_SKILLS = new Set([
|
|
18294
|
+
"audio",
|
|
18295
|
+
"brand-photo-shoot",
|
|
18296
|
+
"browse",
|
|
18297
|
+
"deepresearch",
|
|
18298
|
+
"generate-book-cover",
|
|
18299
|
+
"icon-pack",
|
|
18300
|
+
"image",
|
|
18301
|
+
"music",
|
|
18302
|
+
"music-album",
|
|
18303
|
+
"pdf-read",
|
|
18304
|
+
"photo-album",
|
|
18305
|
+
"playlist-maker",
|
|
18306
|
+
"read-pdf",
|
|
18307
|
+
"remove-background",
|
|
18308
|
+
"short-video-pack",
|
|
18309
|
+
"transcript",
|
|
18310
|
+
"video",
|
|
18311
|
+
"voiceover-jingle-pack",
|
|
18312
|
+
"webcrawling"
|
|
18313
|
+
]);
|
|
18314
|
+
function getHostedRunAvailability(slug) {
|
|
18315
|
+
const canonicalSlug = resolveSkillAlias(slug);
|
|
18316
|
+
if (!UNAVAILABLE_HOSTED_PROVIDER_SKILLS.has(canonicalSlug)) {
|
|
18317
|
+
return { ok: true };
|
|
18318
|
+
}
|
|
18319
|
+
return {
|
|
18320
|
+
ok: false,
|
|
18321
|
+
status: 503,
|
|
18322
|
+
code: "HOSTED_PROVIDER_UNAVAILABLE",
|
|
18323
|
+
message: "hosted execution is temporarily unavailable for this skill",
|
|
18324
|
+
details: [
|
|
18325
|
+
"This skill requires a platform-managed execution path that is not enabled for live hosted runs yet.",
|
|
18326
|
+
"No balance was charged."
|
|
18327
|
+
]
|
|
18328
|
+
};
|
|
18329
|
+
}
|
|
18330
|
+
function getHostedAvailabilityMetadata(slug) {
|
|
18331
|
+
const availability = getHostedRunAvailability(slug);
|
|
18332
|
+
if (availability.ok)
|
|
18333
|
+
return { status: "available" };
|
|
18334
|
+
return {
|
|
18335
|
+
status: "unavailable",
|
|
18336
|
+
code: availability.code,
|
|
18337
|
+
message: availability.message,
|
|
18338
|
+
details: availability.details
|
|
18339
|
+
};
|
|
18340
|
+
}
|
|
18341
|
+
|
|
18162
18342
|
// src/lib/remote-registry.ts
|
|
18343
|
+
var remoteAvailabilitySchema = exports_external.object({
|
|
18344
|
+
status: exports_external.enum(["available", "unavailable"]),
|
|
18345
|
+
code: exports_external.string().optional(),
|
|
18346
|
+
message: exports_external.string().optional(),
|
|
18347
|
+
details: exports_external.array(exports_external.string()).optional()
|
|
18348
|
+
}).passthrough();
|
|
18163
18349
|
var remotePricingSchema = exports_external.object({
|
|
18164
18350
|
formattedCost: exports_external.string(),
|
|
18165
18351
|
tier: exports_external.string().optional(),
|
|
@@ -18181,10 +18367,22 @@ var remoteSkillSchema = exports_external.object({
|
|
|
18181
18367
|
tags: exports_external.array(exports_external.string()).optional(),
|
|
18182
18368
|
dependencies: exports_external.array(exports_external.string()).optional(),
|
|
18183
18369
|
version: exports_external.string().optional(),
|
|
18184
|
-
pricing: remotePricingSchema.optional()
|
|
18370
|
+
pricing: remotePricingSchema.optional(),
|
|
18371
|
+
availability: remoteAvailabilitySchema.optional()
|
|
18185
18372
|
}).passthrough().refine((skill) => skill.name || skill.slug, {
|
|
18186
18373
|
message: "Remote skill requires name or slug"
|
|
18187
18374
|
});
|
|
18375
|
+
var secretValuePatterns = [
|
|
18376
|
+
/\bsk-[A-Za-z0-9_-]{8,}\b/g,
|
|
18377
|
+
/\bgh[opsur]_[A-Za-z0-9_]{8,}\b/g,
|
|
18378
|
+
/\bgithub_pat_[A-Za-z0-9_]{8,}\b/g,
|
|
18379
|
+
/\bnpm_[A-Za-z0-9_]{8,}\b/g,
|
|
18380
|
+
/\bAKIA[A-Z0-9]{12,}\b/g,
|
|
18381
|
+
/\bAIza[A-Za-z0-9_-]{10,}\b/g,
|
|
18382
|
+
new RegExp("\\bsecret" + "-token:\\s*[A-Za-z0-9._-]+", "gi"),
|
|
18383
|
+
/\bctx7sk\-[A-Za-z0-9_-]{8,}\b/g,
|
|
18384
|
+
/\bxai\-[A-Za-z0-9_-]{8,}\b/g
|
|
18385
|
+
];
|
|
18188
18386
|
var remoteSkillDetailSchema = exports_external.union([
|
|
18189
18387
|
remoteSkillSchema,
|
|
18190
18388
|
exports_external.object({ skill: remoteSkillSchema }),
|
|
@@ -18235,9 +18433,30 @@ function normalizeRemoteSkill(skill) {
|
|
|
18235
18433
|
dependencies: skill.dependencies,
|
|
18236
18434
|
...skill.version ? { version: skill.version } : {},
|
|
18237
18435
|
...skill.pricing ? { pricing: skill.pricing } : {},
|
|
18436
|
+
availability: normalizeRemoteAvailability(name, skill.availability),
|
|
18238
18437
|
source: "remote"
|
|
18239
18438
|
};
|
|
18240
18439
|
}
|
|
18440
|
+
function normalizeRemoteAvailability(name, availability) {
|
|
18441
|
+
if (!availability)
|
|
18442
|
+
return getHostedAvailabilityMetadata(name);
|
|
18443
|
+
if (availability.status === "available")
|
|
18444
|
+
return { status: "available" };
|
|
18445
|
+
return {
|
|
18446
|
+
status: availability.status,
|
|
18447
|
+
...safeAvailabilityCode(availability.code) ? { code: safeAvailabilityCode(availability.code) } : {},
|
|
18448
|
+
...availability.message ? { message: sanitizeAvailabilityText(availability.message) } : {},
|
|
18449
|
+
...availability.details ? { details: availability.details.map(sanitizeAvailabilityText).filter(Boolean) } : {}
|
|
18450
|
+
};
|
|
18451
|
+
}
|
|
18452
|
+
function safeAvailabilityCode(code) {
|
|
18453
|
+
if (!code)
|
|
18454
|
+
return;
|
|
18455
|
+
return /^[A-Z0-9_]+$/.test(code) ? code : undefined;
|
|
18456
|
+
}
|
|
18457
|
+
function sanitizeAvailabilityText(text) {
|
|
18458
|
+
return secretValuePatterns.reduce((value, pattern) => value.replace(pattern, "credential"), sanitizePublicDiscoveryText(text).replace(/\b[A-Z0-9_]*(?:API_KEY|SECRET|TOKEN|CREDENTIAL)[A-Z0-9_]*\b/g, "credential")).replace(/\s{2,}/g, " ").trim();
|
|
18459
|
+
}
|
|
18241
18460
|
function parseRemoteRegistryPayload(payload) {
|
|
18242
18461
|
const parsed = parseRemoteContract(remoteRegistrySchema, payload, "Remote registry payload did not match the expected skills contract");
|
|
18243
18462
|
const rawSkills = Array.isArray(parsed) ? parsed : ("skills" in parsed) ? parsed.skills : parsed.data;
|
|
@@ -18299,135 +18518,6 @@ async function loadRemoteSkill(name, options = {}) {
|
|
|
18299
18518
|
const url2 = buildSkillsApiUrl(apiUrl, options.endpoint ?? `/skills/${slug}`);
|
|
18300
18519
|
return parseRemoteSkillPayload(await fetchRemoteJson(url2, options));
|
|
18301
18520
|
}
|
|
18302
|
-
// src/lib/discovery.ts
|
|
18303
|
-
var VENDOR_TERMS = [
|
|
18304
|
-
"Google Gemini",
|
|
18305
|
-
"OpenAI Sora",
|
|
18306
|
-
"MiniMax Hailuo",
|
|
18307
|
-
"Claude Code",
|
|
18308
|
-
"Claude Vision",
|
|
18309
|
-
"DALL-E 3",
|
|
18310
|
-
"GPT-4o Mini",
|
|
18311
|
-
"Cerebras",
|
|
18312
|
-
"OpenRouter",
|
|
18313
|
-
"Firecrawl",
|
|
18314
|
-
"ElevenLabs",
|
|
18315
|
-
"Anthropic",
|
|
18316
|
-
"OpenAI",
|
|
18317
|
-
"Minimax",
|
|
18318
|
-
"MiniMax",
|
|
18319
|
-
"Gemini",
|
|
18320
|
-
"Claude",
|
|
18321
|
-
"Whisper",
|
|
18322
|
-
"Seedance",
|
|
18323
|
-
"Lyria",
|
|
18324
|
-
"Sora",
|
|
18325
|
-
"Veo",
|
|
18326
|
-
"Exa.ai",
|
|
18327
|
-
"Exa",
|
|
18328
|
-
"XAI",
|
|
18329
|
-
"xAI"
|
|
18330
|
-
];
|
|
18331
|
-
var VENDOR_TAGS = new Set([
|
|
18332
|
-
"anthropic",
|
|
18333
|
-
"cerebras",
|
|
18334
|
-
"claude",
|
|
18335
|
-
"exa",
|
|
18336
|
-
"firecrawl",
|
|
18337
|
-
"gemini",
|
|
18338
|
-
"google",
|
|
18339
|
-
"minimax",
|
|
18340
|
-
"openai",
|
|
18341
|
-
"openrouter",
|
|
18342
|
-
"seedance",
|
|
18343
|
-
"whisper",
|
|
18344
|
-
"xai"
|
|
18345
|
-
]);
|
|
18346
|
-
var VENDOR_ENV_PREFIXES = [
|
|
18347
|
-
"ANTHROPIC_",
|
|
18348
|
-
"CEREBRAS_",
|
|
18349
|
-
"EXA_",
|
|
18350
|
-
"FIRECRAWL_",
|
|
18351
|
-
"GEMINI_",
|
|
18352
|
-
"GOOGLE_",
|
|
18353
|
-
"MINIMAX_",
|
|
18354
|
-
"OPENAI_",
|
|
18355
|
-
"OPENROUTER_",
|
|
18356
|
-
"XAI_"
|
|
18357
|
-
];
|
|
18358
|
-
var VENDOR_PACKAGE_PATTERNS = [
|
|
18359
|
-
/anthropic/i,
|
|
18360
|
-
/cerebras/i,
|
|
18361
|
-
/exa/i,
|
|
18362
|
-
/firecrawl/i,
|
|
18363
|
-
/gemini/i,
|
|
18364
|
-
/minimax/i,
|
|
18365
|
-
/openai/i,
|
|
18366
|
-
/openrouter/i,
|
|
18367
|
-
/xai/i
|
|
18368
|
-
];
|
|
18369
|
-
var vendorPattern = new RegExp(`\\b(${VENDOR_TERMS.map(escapeRegExp).join("|")})\\b`, "gi");
|
|
18370
|
-
function getCompactSkillDiscovery(skill) {
|
|
18371
|
-
return {
|
|
18372
|
-
name: skill.name,
|
|
18373
|
-
category: skill.category,
|
|
18374
|
-
pricing: resolveDiscoveryPricing(skill)
|
|
18375
|
-
};
|
|
18376
|
-
}
|
|
18377
|
-
function getPublicSkillDiscovery(skill) {
|
|
18378
|
-
return {
|
|
18379
|
-
...skill,
|
|
18380
|
-
description: sanitizePublicDiscoveryText(skill.description),
|
|
18381
|
-
tags: publicDiscoveryTags(skill.tags),
|
|
18382
|
-
pricing: resolveDiscoveryPricing(skill)
|
|
18383
|
-
};
|
|
18384
|
-
}
|
|
18385
|
-
function publicDiscoveryPriceLabel(skill) {
|
|
18386
|
-
return (skill.pricing ?? getPublicSkillPricing(skill.name)).formattedCost;
|
|
18387
|
-
}
|
|
18388
|
-
function publicDiscoveryTags(tags) {
|
|
18389
|
-
return tags.filter((tag) => !VENDOR_TAGS.has(tag.toLowerCase()));
|
|
18390
|
-
}
|
|
18391
|
-
function sanitizePublicDiscoveryText(text) {
|
|
18392
|
-
let sanitized = text.replace(vendorPattern, "hosted AI").replace(/\bLLM\b/g, "AI").replace(/\s{2,}/g, " ");
|
|
18393
|
-
let previous;
|
|
18394
|
-
do {
|
|
18395
|
-
previous = sanitized;
|
|
18396
|
-
sanitized = sanitized.replace(/\bhosted AI(?: providers)?\s*,\s*hosted AI(?: providers)?\b/gi, "hosted AI providers").replace(/\bhosted AI(?: providers)?\s*,?\s*and\s*hosted AI(?: providers)?\b/gi, "hosted AI providers").replace(/\bhosted AI(?: providers)?\s+or\s+hosted AI(?: providers)?\b/gi, "hosted AI providers").replace(/\bhosted AI providers\s+hosted AI\b/gi, "hosted AI providers").replace(/\bhosted AI providers\s+providers\b/gi, "hosted AI providers");
|
|
18397
|
-
} while (sanitized !== previous);
|
|
18398
|
-
return sanitized.trim();
|
|
18399
|
-
}
|
|
18400
|
-
function publicDiscoveryEnvVars(skillName, envVars) {
|
|
18401
|
-
if (!isPremiumSkill(skillName))
|
|
18402
|
-
return envVars;
|
|
18403
|
-
const filtered = envVars.filter((envVar) => envVar !== "SKILL_API_KEY" && !VENDOR_ENV_PREFIXES.some((prefix) => envVar.startsWith(prefix)));
|
|
18404
|
-
return filtered.includes("SKILLS_API_KEY") ? filtered : ["SKILLS_API_KEY", ...filtered];
|
|
18405
|
-
}
|
|
18406
|
-
function publicDiscoveryDependencies(skillName, dependencies) {
|
|
18407
|
-
if (!isPremiumSkill(skillName))
|
|
18408
|
-
return dependencies;
|
|
18409
|
-
return Object.fromEntries(Object.entries(dependencies).filter(([name]) => !VENDOR_PACKAGE_PATTERNS.some((pattern) => pattern.test(name))));
|
|
18410
|
-
}
|
|
18411
|
-
function publicDiscoveryDocumentation(skill, documentation) {
|
|
18412
|
-
if (!documentation)
|
|
18413
|
-
return documentation;
|
|
18414
|
-
if (!isPremiumSkill(skill.name))
|
|
18415
|
-
return documentation;
|
|
18416
|
-
return [
|
|
18417
|
-
`# ${skill.displayName || skill.name}`,
|
|
18418
|
-
sanitizePublicDiscoveryText(skill.description),
|
|
18419
|
-
`Pricing: ${getPublicSkillPricing(skill.name).formattedCost}.`,
|
|
18420
|
-
"Set `SKILLS_API_KEY` or run `skills auth login` for hosted runtime execution. Runtime routing and model selection are managed by the hosted Skills runtime."
|
|
18421
|
-
].join(`
|
|
18422
|
-
|
|
18423
|
-
`);
|
|
18424
|
-
}
|
|
18425
|
-
function escapeRegExp(value) {
|
|
18426
|
-
return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
18427
|
-
}
|
|
18428
|
-
function resolveDiscoveryPricing(skill) {
|
|
18429
|
-
return skill.pricing && typeof skill.pricing.formattedCost === "string" ? skill.pricing : getPublicSkillPricing(skill.name);
|
|
18430
|
-
}
|
|
18431
18521
|
// src/lib/tool-primitives.ts
|
|
18432
18522
|
var TOOL_PRIMITIVE_SCHEMA_VERSION = 1;
|
|
18433
18523
|
var TOOL_PRIMITIVES = [
|
|
@@ -19265,7 +19355,7 @@ import { dirname as dirname4, relative as relative3 } from "path";
|
|
|
19265
19355
|
// package.json
|
|
19266
19356
|
var package_default = {
|
|
19267
19357
|
name: "@hasna/skills",
|
|
19268
|
-
version: "0.1.
|
|
19358
|
+
version: "0.1.58",
|
|
19269
19359
|
description: "Skills library for AI coding agents",
|
|
19270
19360
|
type: "module",
|
|
19271
19361
|
bin: {
|
|
@@ -19491,6 +19581,16 @@ var pricingSchema = objectSchema({
|
|
|
19491
19581
|
quoteDependsOnInput: { type: "boolean", description: "Whether input affects the quote." },
|
|
19492
19582
|
quoteRequired: { type: "boolean", description: "Whether callers should quote before running." }
|
|
19493
19583
|
}, [], "Public pricing metadata.");
|
|
19584
|
+
var skillAvailabilitySchema = objectSchema({
|
|
19585
|
+
status: {
|
|
19586
|
+
type: "string",
|
|
19587
|
+
enum: ["available", "unavailable"],
|
|
19588
|
+
description: "Whether hosted execution is currently available for this skill."
|
|
19589
|
+
},
|
|
19590
|
+
code: stringSchema("Optional stable unavailability code."),
|
|
19591
|
+
message: stringSchema("Optional human-readable availability message."),
|
|
19592
|
+
details: stringArraySchema("Optional availability details.")
|
|
19593
|
+
}, ["status"], "Hosted skill availability metadata.");
|
|
19494
19594
|
var skillSummarySchema = objectSchema({
|
|
19495
19595
|
name: stringSchema("Canonical skill slug."),
|
|
19496
19596
|
category: stringSchema("Skill category."),
|
|
@@ -19846,7 +19946,14 @@ var toolContracts = [
|
|
|
19846
19946
|
sideEffects: "none",
|
|
19847
19947
|
stable: true,
|
|
19848
19948
|
inputSchema: objectSchema({ name: skillNameInput, input: runInputSchema, args: runArgsSchema }, ["name"]),
|
|
19849
|
-
outputSchema: objectSchema({
|
|
19949
|
+
outputSchema: objectSchema({
|
|
19950
|
+
skill: stringSchema("Skill slug."),
|
|
19951
|
+
pricing: pricingSchema,
|
|
19952
|
+
availability: skillAvailabilitySchema,
|
|
19953
|
+
error: stringSchema("Optional error message when the quote cannot be used to run."),
|
|
19954
|
+
code: stringSchema("Optional stable error code."),
|
|
19955
|
+
details: stringArraySchema("Optional error details.")
|
|
19956
|
+
}, ["skill", "pricing", "availability"])
|
|
19850
19957
|
},
|
|
19851
19958
|
{
|
|
19852
19959
|
name: "run_skill",
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { SkillAvailabilityMetadata } from "./registry-types.js";
|
|
2
|
+
export interface HostedRunUnavailable {
|
|
3
|
+
ok: false;
|
|
4
|
+
status: 503;
|
|
5
|
+
code: "HOSTED_PROVIDER_UNAVAILABLE";
|
|
6
|
+
message: string;
|
|
7
|
+
details: string[];
|
|
8
|
+
}
|
|
9
|
+
export type HostedRunAvailability = {
|
|
10
|
+
ok: true;
|
|
11
|
+
} | HostedRunUnavailable;
|
|
12
|
+
export declare function getHostedRunAvailability(slug: string): HostedRunAvailability;
|
|
13
|
+
export declare function getHostedAvailabilityMetadata(slug: string): SkillAvailabilityMetadata;
|
|
@@ -7,6 +7,7 @@ export interface SkillMeta {
|
|
|
7
7
|
dependencies?: string[];
|
|
8
8
|
version?: string;
|
|
9
9
|
pricing?: SkillPricingMetadata;
|
|
10
|
+
availability?: SkillAvailabilityMetadata;
|
|
10
11
|
source?: "official" | "custom" | "remote";
|
|
11
12
|
}
|
|
12
13
|
export interface SkillPricingMetadata {
|
|
@@ -21,6 +22,12 @@ export interface SkillPricingMetadata {
|
|
|
21
22
|
quoteRequired?: boolean;
|
|
22
23
|
description?: string;
|
|
23
24
|
}
|
|
25
|
+
export interface SkillAvailabilityMetadata {
|
|
26
|
+
status: "available" | "unavailable";
|
|
27
|
+
code?: string;
|
|
28
|
+
message?: string;
|
|
29
|
+
details?: string[];
|
|
30
|
+
}
|
|
24
31
|
export declare const CATEGORIES: readonly ["Development Tools", "Business & Marketing", "Productivity & Organization", "Project Management", "Content Generation", "Finance & Compliance", "Data & Analysis", "Media Processing", "Design & Branding", "Web & Browser", "Research & Writing", "Science & Academic", "Education & Learning", "Communication", "Health & Wellness", "Travel & Lifestyle", "Event Management"];
|
|
25
32
|
export type Category = (typeof CATEGORIES)[number];
|
|
26
33
|
export declare const BASIC_SKILL_NAMES: readonly ["image", "video", "audio", "music", "transcript", "audio-extract", "read-image", "read-pdf", "pdf-read", "pdf-to-markdown", "doc-read", "pdf-generate", "doc-generate", "read-csv", "read-excel", "excel", "convert"];
|