@hasna/skills 0.1.57 → 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 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.57",
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 }),
@@ -60253,53 +60353,6 @@ var init_diagnostic = __esm(() => {
60253
60353
  init_installer();
60254
60354
  });
60255
60355
 
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
-
60303
60356
  // src/lib/remote-run-contract.ts
60304
60357
  function normalizeRemoteSkillRunContract(payload, fallbackSkill) {
60305
60358
  const record2 = isRecord2(payload) ? payload : {};
@@ -80345,6 +80398,54 @@ function writeCommandError(err, fallback, json2) {
80345
80398
  console.error(source_default.red(String(payload.detail || payload.error || fallback)));
80346
80399
  process.exitCode = 1;
80347
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
+ }
80348
80449
  function sleep(ms) {
80349
80450
  return new Promise((resolve) => setTimeout(resolve, ms));
80350
80451
  }
@@ -80609,26 +80710,39 @@ function registerAuth(parent) {
80609
80710
  clearAuthConfig();
80610
80711
  console.log(source_default.green(`\u2713 Signed out (was ${existing.email})`));
80611
80712
  });
80612
- 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();
80613
80715
  const config2 = getAuthConfig();
80614
- if (!config2) {
80615
- console.log(source_default.dim("Not signed in. Run: skills auth login"));
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));
80616
80723
  return;
80617
80724
  }
80618
- console.log(source_default.bold("Email: ") + config2.email);
80619
- console.log(source_default.bold("Org: ") + config2.orgSlug);
80725
+ const authSource = envKey ? "env" : "stored";
80620
80726
  try {
80621
80727
  const res = await apiRequest("/api/auth/whoami", {
80622
- headers: { Authorization: `Bearer ${config2.apiKey}` }
80728
+ headers: { Authorization: `Bearer ${apiKey}` }
80623
80729
  });
80624
- if (res.user) {
80625
- console.log(source_default.bold("Role: ") + res.user.role);
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);
80626
80735
  }
80627
- if (res.organization) {
80628
- console.log(source_default.bold("Name: ") + res.organization.name);
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;
80629
80744
  }
80630
- } catch {
80631
- console.log(source_default.dim("(offline \u2014 showing cached info)"));
80745
+ writeCommandError(err, "Failed to fetch current account", options.json);
80632
80746
  }
80633
80747
  });
80634
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.57",
21822
+ version: "0.1.58",
21823
21823
  description: "Skills library for AI coding agents",
21824
21824
  type: "module",
21825
21825
  bin: {
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.57",
19358
+ version: "0.1.58",
19269
19359
  description: "Skills library for AI coding agents",
19270
19360
  type: "module",
19271
19361
  bin: {
@@ -1,3 +1,4 @@
1
+ import type { SkillAvailabilityMetadata } from "./registry-types.js";
1
2
  export interface HostedRunUnavailable {
2
3
  ok: false;
3
4
  status: 503;
@@ -9,3 +10,4 @@ export type HostedRunAvailability = {
9
10
  ok: true;
10
11
  } | HostedRunUnavailable;
11
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"];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/skills",
3
- "version": "0.1.57",
3
+ "version": "0.1.58",
4
4
  "description": "Skills library for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {