@hasna/skills 0.1.55 → 0.1.57
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 +187 -6
- package/bin/mcp.js +95 -3
- package/dist/index.js +19 -2
- package/dist/lib/hosted-availability.d.ts +11 -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.57",
|
|
36864
36864
|
description: "Skills library for AI coding agents",
|
|
36865
36865
|
type: "module",
|
|
36866
36866
|
bin: {
|
|
@@ -60253,6 +60253,53 @@ var init_diagnostic = __esm(() => {
|
|
|
60253
60253
|
init_installer();
|
|
60254
60254
|
});
|
|
60255
60255
|
|
|
60256
|
+
// src/lib/hosted-availability.ts
|
|
60257
|
+
var exports_hosted_availability = {};
|
|
60258
|
+
__export(exports_hosted_availability, {
|
|
60259
|
+
getHostedRunAvailability: () => getHostedRunAvailability
|
|
60260
|
+
});
|
|
60261
|
+
function getHostedRunAvailability(slug) {
|
|
60262
|
+
const canonicalSlug = resolveSkillAlias(slug);
|
|
60263
|
+
if (!UNAVAILABLE_HOSTED_PROVIDER_SKILLS.has(canonicalSlug)) {
|
|
60264
|
+
return { ok: true };
|
|
60265
|
+
}
|
|
60266
|
+
return {
|
|
60267
|
+
ok: false,
|
|
60268
|
+
status: 503,
|
|
60269
|
+
code: "HOSTED_PROVIDER_UNAVAILABLE",
|
|
60270
|
+
message: "hosted execution is temporarily unavailable for this skill",
|
|
60271
|
+
details: [
|
|
60272
|
+
"This skill requires a platform-managed execution path that is not enabled for live hosted runs yet.",
|
|
60273
|
+
"No balance was charged."
|
|
60274
|
+
]
|
|
60275
|
+
};
|
|
60276
|
+
}
|
|
60277
|
+
var UNAVAILABLE_HOSTED_PROVIDER_SKILLS;
|
|
60278
|
+
var init_hosted_availability = __esm(() => {
|
|
60279
|
+
init_skill_aliases();
|
|
60280
|
+
UNAVAILABLE_HOSTED_PROVIDER_SKILLS = new Set([
|
|
60281
|
+
"audio",
|
|
60282
|
+
"brand-photo-shoot",
|
|
60283
|
+
"browse",
|
|
60284
|
+
"deepresearch",
|
|
60285
|
+
"generate-book-cover",
|
|
60286
|
+
"icon-pack",
|
|
60287
|
+
"image",
|
|
60288
|
+
"music",
|
|
60289
|
+
"music-album",
|
|
60290
|
+
"pdf-read",
|
|
60291
|
+
"photo-album",
|
|
60292
|
+
"playlist-maker",
|
|
60293
|
+
"read-pdf",
|
|
60294
|
+
"remove-background",
|
|
60295
|
+
"short-video-pack",
|
|
60296
|
+
"transcript",
|
|
60297
|
+
"video",
|
|
60298
|
+
"voiceover-jingle-pack",
|
|
60299
|
+
"webcrawling"
|
|
60300
|
+
]);
|
|
60301
|
+
});
|
|
60302
|
+
|
|
60256
60303
|
// src/lib/remote-run-contract.ts
|
|
60257
60304
|
function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
|
|
60258
60305
|
const record2 = isRecord2(payload) ? payload : {};
|
|
@@ -75774,7 +75821,7 @@ var MCP_CONTRACT_SCHEMA_VERSION = 1, stringSchema = (description) => ({
|
|
|
75774
75821
|
type: "array",
|
|
75775
75822
|
items,
|
|
75776
75823
|
...description ? { description } : {}
|
|
75777
|
-
}), skillNameInput, optionalAgentInput, scopeInput, runInputSchema, runArgsSchema, paidRunApprovalSchema, errorSchema, pricingSchema, skillSummarySchema, toolPrimitiveSummarySchema, skillToolDependencySchema, validationMessageSchema, validationOutputSchema, installOutputSchema, runOutputSchema, toolContracts, contracts, resourceContracts;
|
|
75824
|
+
}), skillNameInput, optionalAgentInput, scopeInput, runInputSchema, runArgsSchema, paidRunApprovalSchema, errorSchema, pricingSchema, skillAvailabilitySchema, skillSummarySchema, toolPrimitiveSummarySchema, skillToolDependencySchema, validationMessageSchema, validationOutputSchema, installOutputSchema, runOutputSchema, toolContracts, contracts, resourceContracts;
|
|
75778
75825
|
var init_mcp_contracts = __esm(() => {
|
|
75779
75826
|
skillNameInput = stringSchema("skill name or alias.");
|
|
75780
75827
|
optionalAgentInput = stringSchema("Optional target agent slug. Use MCP registration instead of direct skill-folder installs.");
|
|
@@ -75812,6 +75859,16 @@ var init_mcp_contracts = __esm(() => {
|
|
|
75812
75859
|
quoteDependsOnInput: { type: "boolean", description: "Whether input affects the quote." },
|
|
75813
75860
|
quoteRequired: { type: "boolean", description: "Whether callers should quote before running." }
|
|
75814
75861
|
}, [], "Public pricing metadata.");
|
|
75862
|
+
skillAvailabilitySchema = objectSchema({
|
|
75863
|
+
status: {
|
|
75864
|
+
type: "string",
|
|
75865
|
+
enum: ["available", "unavailable"],
|
|
75866
|
+
description: "Whether hosted execution is currently available for this skill."
|
|
75867
|
+
},
|
|
75868
|
+
code: stringSchema("Optional stable unavailability code."),
|
|
75869
|
+
message: stringSchema("Optional human-readable availability message."),
|
|
75870
|
+
details: stringArraySchema("Optional availability details.")
|
|
75871
|
+
}, ["status"], "Hosted skill availability metadata.");
|
|
75815
75872
|
skillSummarySchema = objectSchema({
|
|
75816
75873
|
name: stringSchema("Canonical skill slug."),
|
|
75817
75874
|
category: stringSchema("Skill category."),
|
|
@@ -76167,7 +76224,14 @@ var init_mcp_contracts = __esm(() => {
|
|
|
76167
76224
|
sideEffects: "none",
|
|
76168
76225
|
stable: true,
|
|
76169
76226
|
inputSchema: objectSchema({ name: skillNameInput, input: runInputSchema, args: runArgsSchema }, ["name"]),
|
|
76170
|
-
outputSchema: objectSchema({
|
|
76227
|
+
outputSchema: objectSchema({
|
|
76228
|
+
skill: stringSchema("Skill slug."),
|
|
76229
|
+
pricing: pricingSchema,
|
|
76230
|
+
availability: skillAvailabilitySchema,
|
|
76231
|
+
error: stringSchema("Optional error message when the quote cannot be used to run."),
|
|
76232
|
+
code: stringSchema("Optional stable error code."),
|
|
76233
|
+
details: stringArraySchema("Optional error details.")
|
|
76234
|
+
}, ["skill", "pricing", "availability"])
|
|
76171
76235
|
},
|
|
76172
76236
|
{
|
|
76173
76237
|
name: "run_skill",
|
|
@@ -77014,9 +77078,33 @@ function registerOperationTools(server) {
|
|
|
77014
77078
|
return mcpError("INVALID_BLOG_ARTICLE_OPTIONS", validation.errors.join(" "));
|
|
77015
77079
|
}
|
|
77016
77080
|
}
|
|
77081
|
+
const pricing = getPublicSkillPricing2(skill.name, runInput, runArgs);
|
|
77082
|
+
const hostedAvailability = getHostedRunAvailability(skill.name);
|
|
77083
|
+
if (!hostedAvailability.ok) {
|
|
77084
|
+
return {
|
|
77085
|
+
content: [{
|
|
77086
|
+
type: "text",
|
|
77087
|
+
text: JSON.stringify({
|
|
77088
|
+
skill: skill.name,
|
|
77089
|
+
pricing,
|
|
77090
|
+
error: hostedAvailability.message,
|
|
77091
|
+
code: hostedAvailability.code,
|
|
77092
|
+
details: hostedAvailability.details,
|
|
77093
|
+
availability: {
|
|
77094
|
+
status: "unavailable",
|
|
77095
|
+
code: hostedAvailability.code,
|
|
77096
|
+
message: hostedAvailability.message,
|
|
77097
|
+
details: hostedAvailability.details
|
|
77098
|
+
}
|
|
77099
|
+
})
|
|
77100
|
+
}],
|
|
77101
|
+
isError: true
|
|
77102
|
+
};
|
|
77103
|
+
}
|
|
77017
77104
|
return mcpJson({
|
|
77018
77105
|
skill: skill.name,
|
|
77019
|
-
pricing
|
|
77106
|
+
pricing,
|
|
77107
|
+
availability: { status: "available" }
|
|
77020
77108
|
});
|
|
77021
77109
|
});
|
|
77022
77110
|
server.registerTool("run_skill", {
|
|
@@ -77059,6 +77147,18 @@ function registerOperationTools(server) {
|
|
|
77059
77147
|
remote: isPremiumSkill2(skillName),
|
|
77060
77148
|
costCents
|
|
77061
77149
|
});
|
|
77150
|
+
if (isPremiumSkill2(skillName)) {
|
|
77151
|
+
const hostedAvailability = getHostedRunAvailability(skillName);
|
|
77152
|
+
if (!hostedAvailability.ok) {
|
|
77153
|
+
const error48 = `${hostedAvailability.code}: ${hostedAvailability.message}`;
|
|
77154
|
+
writeRunLogs(runContext, "", `${error48}
|
|
77155
|
+
${hostedAvailability.details.join(`
|
|
77156
|
+
`)}
|
|
77157
|
+
`);
|
|
77158
|
+
const run = completeSkillRun(runContext, { status: "failed", error: error48, costCents });
|
|
77159
|
+
return mcpError(hostedAvailability.code, `${hostedAvailability.message}. ${hostedAvailability.details.join(" ")} Local run metadata: ${run.paths.runDir}/run.json`);
|
|
77160
|
+
}
|
|
77161
|
+
}
|
|
77062
77162
|
if (isPremiumSkill2(skillName) && !apiKey) {
|
|
77063
77163
|
const cost = formatCost2(costCents ?? 0);
|
|
77064
77164
|
const error48 = `${skillName} is a hosted skill (${cost}). Run: skills setup --mode hosted && skills auth login`;
|
|
@@ -77302,6 +77402,7 @@ var init_operation_tools = __esm(() => {
|
|
|
77302
77402
|
init_run_state();
|
|
77303
77403
|
init_portable_skills();
|
|
77304
77404
|
init_helpers();
|
|
77405
|
+
init_hosted_availability();
|
|
77305
77406
|
});
|
|
77306
77407
|
|
|
77307
77408
|
// src/lib/feedback.ts
|
|
@@ -78710,7 +78811,20 @@ function handleQuote(name, args2, options) {
|
|
|
78710
78811
|
}
|
|
78711
78812
|
}
|
|
78712
78813
|
const pricing = getPublicSkillPricing(skill.name, {}, quoteArgs);
|
|
78713
|
-
const
|
|
78814
|
+
const hostedAvailability = getHostedRunAvailability(skill.name);
|
|
78815
|
+
if (!hostedAvailability.ok) {
|
|
78816
|
+
const payload2 = unavailableHostedPayload(skill.name, pricing, hostedAvailability);
|
|
78817
|
+
if (json2) {
|
|
78818
|
+
console.log(JSON.stringify(payload2, null, 2));
|
|
78819
|
+
} else {
|
|
78820
|
+
console.error(source_default.red(`${skill.name}: ${hostedAvailability.message}`));
|
|
78821
|
+
for (const detail of hostedAvailability.details)
|
|
78822
|
+
console.error(source_default.dim(` ${detail}`));
|
|
78823
|
+
}
|
|
78824
|
+
process.exitCode = 1;
|
|
78825
|
+
return;
|
|
78826
|
+
}
|
|
78827
|
+
const payload = { skill: skill.name, pricing, availability: { status: "available" } };
|
|
78714
78828
|
if (json2) {
|
|
78715
78829
|
console.log(JSON.stringify(payload, null, 2));
|
|
78716
78830
|
return;
|
|
@@ -78760,6 +78874,32 @@ async function handleRun(name, args2, options) {
|
|
|
78760
78874
|
costCents
|
|
78761
78875
|
});
|
|
78762
78876
|
if (isPremium) {
|
|
78877
|
+
const hostedAvailability = getHostedRunAvailability(skill.name);
|
|
78878
|
+
if (!hostedAvailability.ok) {
|
|
78879
|
+
const payload = unavailableHostedPayload(skill.name, publicPricing, hostedAvailability);
|
|
78880
|
+
const error48 = `${hostedAvailability.code}: ${hostedAvailability.message}`;
|
|
78881
|
+
writeRunLogs(runContext, "", `${error48}
|
|
78882
|
+
${hostedAvailability.details.join(`
|
|
78883
|
+
`)}
|
|
78884
|
+
`);
|
|
78885
|
+
const run = completeSkillRun(runContext, { status: "failed", error: error48, costCents });
|
|
78886
|
+
if (options.json) {
|
|
78887
|
+
console.log(JSON.stringify({
|
|
78888
|
+
contractVersion: REMOTE_SKILL_RUN_CONTRACT_VERSION,
|
|
78889
|
+
args: args2,
|
|
78890
|
+
exitCode: 1,
|
|
78891
|
+
remote: true,
|
|
78892
|
+
...payload,
|
|
78893
|
+
run
|
|
78894
|
+
}, null, 2));
|
|
78895
|
+
} else {
|
|
78896
|
+
console.error(source_default.red(`${skill.name}: ${hostedAvailability.message}`));
|
|
78897
|
+
for (const detail of hostedAvailability.details)
|
|
78898
|
+
console.error(source_default.dim(` ${detail}`));
|
|
78899
|
+
}
|
|
78900
|
+
process.exitCode = 1;
|
|
78901
|
+
return;
|
|
78902
|
+
}
|
|
78763
78903
|
const { getApiKey: getApiKey2 } = await Promise.resolve().then(() => (init_auth_store(), exports_auth_store));
|
|
78764
78904
|
const apiKey = getApiKey2();
|
|
78765
78905
|
if (!apiKey) {
|
|
@@ -78912,6 +79052,21 @@ async function handleRun(name, args2, options) {
|
|
|
78912
79052
|
}
|
|
78913
79053
|
process.exitCode = result2.exitCode;
|
|
78914
79054
|
}
|
|
79055
|
+
function unavailableHostedPayload(skill, pricing, availability) {
|
|
79056
|
+
return {
|
|
79057
|
+
skill,
|
|
79058
|
+
pricing,
|
|
79059
|
+
error: availability.message,
|
|
79060
|
+
code: availability.code,
|
|
79061
|
+
details: availability.details,
|
|
79062
|
+
availability: {
|
|
79063
|
+
status: "unavailable",
|
|
79064
|
+
code: availability.code,
|
|
79065
|
+
message: availability.message,
|
|
79066
|
+
details: availability.details
|
|
79067
|
+
}
|
|
79068
|
+
};
|
|
79069
|
+
}
|
|
78915
79070
|
async function approvePaidHostedRun(params) {
|
|
78916
79071
|
if (params.yes)
|
|
78917
79072
|
return { approved: true };
|
|
@@ -79355,6 +79510,7 @@ var init_runtime = __esm(() => {
|
|
|
79355
79510
|
init_skillinfo();
|
|
79356
79511
|
init_pricing();
|
|
79357
79512
|
init_config();
|
|
79513
|
+
init_hosted_availability();
|
|
79358
79514
|
init_run_state();
|
|
79359
79515
|
init_runtime_mcp();
|
|
79360
79516
|
});
|
|
@@ -79822,6 +79978,18 @@ Next: skills schedule list --cursor ${page.nextOffset} --limit ${page.limit}`));
|
|
|
79822
79978
|
return;
|
|
79823
79979
|
}
|
|
79824
79980
|
const dueDetails = await Promise.all(due.map((schedule) => describeDueSchedule(schedule)));
|
|
79981
|
+
const unavailable = dueDetails.filter((schedule) => schedule.availability?.status === "unavailable");
|
|
79982
|
+
if (unavailable.length > 0 && !options.dryRun) {
|
|
79983
|
+
const code = unavailable[0]?.availability?.code ?? "HOSTED_PROVIDER_UNAVAILABLE";
|
|
79984
|
+
const error48 = `Hosted execution is temporarily unavailable for ${unavailable.map((schedule) => schedule.skill).join(", ")}. No balance was charged.`;
|
|
79985
|
+
if (options.json) {
|
|
79986
|
+
console.log(JSON.stringify({ ran: 0, error: error48, code, unavailable, schedules: dueDetails }));
|
|
79987
|
+
} else {
|
|
79988
|
+
console.error(source_default.red(`\u2717 ${error48}`));
|
|
79989
|
+
}
|
|
79990
|
+
process.exitCode = 1;
|
|
79991
|
+
return;
|
|
79992
|
+
}
|
|
79825
79993
|
const paidTotalCents = dueDetails.reduce((total, schedule) => total + (schedule.costCents ?? 0), 0);
|
|
79826
79994
|
if (options.dryRun) {
|
|
79827
79995
|
console.log(options.json ? JSON.stringify({ due: dueDetails, paidTotalCents, paidTotal: formatCost2(paidTotalCents) }) : source_default.bold(`${due.length} schedule(s) due:
|
|
@@ -79907,6 +80075,11 @@ async function executeScheduledSkill(skillName, args2, options) {
|
|
|
79907
80075
|
throw new Error(`Skill '${skillName}' not found`);
|
|
79908
80076
|
const pricing = await Promise.resolve().then(() => (init_pricing(), exports_pricing));
|
|
79909
80077
|
if (pricing.isPremiumSkill(skill.name)) {
|
|
80078
|
+
const { getHostedRunAvailability: getHostedRunAvailability2 } = await Promise.resolve().then(() => (init_hosted_availability(), exports_hosted_availability));
|
|
80079
|
+
const hostedAvailability = getHostedRunAvailability2(skill.name);
|
|
80080
|
+
if (!hostedAvailability.ok) {
|
|
80081
|
+
throw new Error(`${hostedAvailability.code}: ${hostedAvailability.message}. ${hostedAvailability.details.join(" ")}`);
|
|
80082
|
+
}
|
|
79910
80083
|
const publicPricing = pricing.getPublicSkillPricing(skill.name, {}, args2);
|
|
79911
80084
|
if (!options.allowPaid) {
|
|
79912
80085
|
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 +80106,24 @@ async function executeScheduledSkill(skillName, args2, options) {
|
|
|
79933
80106
|
async function describeDueSchedule(schedule) {
|
|
79934
80107
|
const { getSkill: getSkill2 } = await Promise.resolve().then(() => (init_registry(), exports_registry));
|
|
79935
80108
|
const pricing = await Promise.resolve().then(() => (init_pricing(), exports_pricing));
|
|
80109
|
+
const { getHostedRunAvailability: getHostedRunAvailability2 } = await Promise.resolve().then(() => (init_hosted_availability(), exports_hosted_availability));
|
|
79936
80110
|
const skill = getSkill2(schedule.skill);
|
|
79937
80111
|
const paid = Boolean(skill && pricing.isPremiumSkill(skill.name));
|
|
79938
80112
|
const publicPricing = paid && skill ? pricing.getPublicSkillPricing(skill.name, {}, schedule.args ?? []) : null;
|
|
80113
|
+
const availability = skill ? getHostedRunAvailability2(skill.name) : { ok: true };
|
|
79939
80114
|
return {
|
|
79940
80115
|
name: schedule.name,
|
|
79941
80116
|
skill: schedule.skill,
|
|
79942
80117
|
cron: schedule.cron,
|
|
79943
80118
|
paid,
|
|
79944
80119
|
costCents: publicPricing?.costCents,
|
|
79945
|
-
cost: publicPricing?.formattedCost
|
|
80120
|
+
cost: publicPricing?.formattedCost,
|
|
80121
|
+
availability: availability.ok ? { status: "available" } : {
|
|
80122
|
+
status: "unavailable",
|
|
80123
|
+
code: availability.code,
|
|
80124
|
+
message: availability.message,
|
|
80125
|
+
details: availability.details
|
|
80126
|
+
}
|
|
79946
80127
|
};
|
|
79947
80128
|
}
|
|
79948
80129
|
function parseMaxPaidCents(value) {
|
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.57",
|
|
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
|
@@ -19265,7 +19265,7 @@ import { dirname as dirname4, relative as relative3 } from "path";
|
|
|
19265
19265
|
// package.json
|
|
19266
19266
|
var package_default = {
|
|
19267
19267
|
name: "@hasna/skills",
|
|
19268
|
-
version: "0.1.
|
|
19268
|
+
version: "0.1.57",
|
|
19269
19269
|
description: "Skills library for AI coding agents",
|
|
19270
19270
|
type: "module",
|
|
19271
19271
|
bin: {
|
|
@@ -19491,6 +19491,16 @@ var pricingSchema = objectSchema({
|
|
|
19491
19491
|
quoteDependsOnInput: { type: "boolean", description: "Whether input affects the quote." },
|
|
19492
19492
|
quoteRequired: { type: "boolean", description: "Whether callers should quote before running." }
|
|
19493
19493
|
}, [], "Public pricing metadata.");
|
|
19494
|
+
var skillAvailabilitySchema = objectSchema({
|
|
19495
|
+
status: {
|
|
19496
|
+
type: "string",
|
|
19497
|
+
enum: ["available", "unavailable"],
|
|
19498
|
+
description: "Whether hosted execution is currently available for this skill."
|
|
19499
|
+
},
|
|
19500
|
+
code: stringSchema("Optional stable unavailability code."),
|
|
19501
|
+
message: stringSchema("Optional human-readable availability message."),
|
|
19502
|
+
details: stringArraySchema("Optional availability details.")
|
|
19503
|
+
}, ["status"], "Hosted skill availability metadata.");
|
|
19494
19504
|
var skillSummarySchema = objectSchema({
|
|
19495
19505
|
name: stringSchema("Canonical skill slug."),
|
|
19496
19506
|
category: stringSchema("Skill category."),
|
|
@@ -19846,7 +19856,14 @@ var toolContracts = [
|
|
|
19846
19856
|
sideEffects: "none",
|
|
19847
19857
|
stable: true,
|
|
19848
19858
|
inputSchema: objectSchema({ name: skillNameInput, input: runInputSchema, args: runArgsSchema }, ["name"]),
|
|
19849
|
-
outputSchema: objectSchema({
|
|
19859
|
+
outputSchema: objectSchema({
|
|
19860
|
+
skill: stringSchema("Skill slug."),
|
|
19861
|
+
pricing: pricingSchema,
|
|
19862
|
+
availability: skillAvailabilitySchema,
|
|
19863
|
+
error: stringSchema("Optional error message when the quote cannot be used to run."),
|
|
19864
|
+
code: stringSchema("Optional stable error code."),
|
|
19865
|
+
details: stringArraySchema("Optional error details.")
|
|
19866
|
+
}, ["skill", "pricing", "availability"])
|
|
19850
19867
|
},
|
|
19851
19868
|
{
|
|
19852
19869
|
name: "run_skill",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface HostedRunUnavailable {
|
|
2
|
+
ok: false;
|
|
3
|
+
status: 503;
|
|
4
|
+
code: "HOSTED_PROVIDER_UNAVAILABLE";
|
|
5
|
+
message: string;
|
|
6
|
+
details: string[];
|
|
7
|
+
}
|
|
8
|
+
export type HostedRunAvailability = {
|
|
9
|
+
ok: true;
|
|
10
|
+
} | HostedRunUnavailable;
|
|
11
|
+
export declare function getHostedRunAvailability(slug: string): HostedRunAvailability;
|