@hasna/skills 0.8.6 → 0.8.7

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
@@ -36868,7 +36868,7 @@ var package_default;
36868
36868
  var init_package = __esm(() => {
36869
36869
  package_default = {
36870
36870
  name: "@hasna/skills",
36871
- version: "0.8.6",
36871
+ version: "0.8.7",
36872
36872
  description: "Skills library for AI coding agents",
36873
36873
  type: "module",
36874
36874
  bin: {
@@ -38212,6 +38212,35 @@ function isSafeRelativePath(value) {
38212
38212
  const normalized = normalize(value).replace(/\\/g, "/");
38213
38213
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
38214
38214
  }
38215
+ function validateRuntimeEntry(skillPath, entrypoint, issues, warnings) {
38216
+ if (typeof entrypoint !== "string" || !isSafeRelativePath(entrypoint) || /^[a-zA-Z]:/.test(entrypoint) || entrypoint.includes("\\") || entrypoint.split("/").some((part) => !part || part === "." || part === "..")) {
38217
+ add2(issues, "skill.runtime_entrypoint_unsafe", "runtime.entrypoint must be a canonical relative file path inside the skill directory");
38218
+ return;
38219
+ }
38220
+ const parts = entrypoint.split("/");
38221
+ let current = skillPath;
38222
+ for (let index = 0;index < parts.length; index++) {
38223
+ current = join8(current, parts[index]);
38224
+ let info;
38225
+ try {
38226
+ info = lstatSync(current);
38227
+ } catch {
38228
+ add2(issues, "skill.runtime_entrypoint_missing", "The declared runtime.entrypoint is missing or inaccessible");
38229
+ return;
38230
+ }
38231
+ if (info.isSymbolicLink()) {
38232
+ add2(issues, "skill.runtime_entrypoint_symlink", "runtime.entrypoint must not traverse symbolic links");
38233
+ return;
38234
+ }
38235
+ if (index < parts.length - 1 ? !info.isDirectory() : !info.isFile()) {
38236
+ add2(issues, "skill.runtime_entrypoint_not_file", "runtime.entrypoint must resolve to a regular file");
38237
+ return;
38238
+ }
38239
+ if (index === parts.length - 1 && info.size < 50) {
38240
+ add2(warnings, "skill.runtime_entrypoint_minimal", `Source entry point is very small (${info.size}B)`);
38241
+ }
38242
+ }
38243
+ }
38215
38244
  function isHostedPackageMetadata(pkg) {
38216
38245
  return isHostedMetadataPackage(pkg);
38217
38246
  }
@@ -38447,10 +38476,22 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
38447
38476
  } else {
38448
38477
  metadata.runtime = hostedMetadata ? "hosted" : "local";
38449
38478
  const srcDir = join8(skillPath, "src");
38479
+ let declaredEntrypoint;
38480
+ const manifestPath = join8(skillPath, "skill.json");
38481
+ if (!hostedMetadata && existsSync8(manifestPath)) {
38482
+ try {
38483
+ const manifest = asRecord(readJsonFile(manifestPath));
38484
+ declaredEntrypoint = asRecord(manifest?.runtime)?.entrypoint;
38485
+ } catch {
38486
+ add2(issues, "skill.manifest_invalid", "skill.json must contain valid JSON");
38487
+ }
38488
+ }
38450
38489
  if (hostedMetadata) {
38451
38490
  if (existsSync8(srcDir)) {
38452
38491
  add2(issues, "skill.hosted_source_forbidden", "Hosted metadata skills must not include local implementation source");
38453
38492
  }
38493
+ } else if (declaredEntrypoint !== undefined && declaredEntrypoint !== null) {
38494
+ validateRuntimeEntry(skillPath, declaredEntrypoint, issues, warnings);
38454
38495
  } else if (!existsSync8(srcDir)) {
38455
38496
  add2(issues, "skill.src_missing", "Missing src/ directory");
38456
38497
  } else if (!existsSync8(join8(srcDir, "index.ts")) && !existsSync8(join8(srcDir, "index.js"))) {
@@ -40028,7 +40069,11 @@ function validatePortableSkillDirectory(name, skillPath) {
40028
40069
  "package.missing",
40029
40070
  "package.bin_missing",
40030
40071
  "skill.src_missing",
40031
- "skill.src_index_missing"
40072
+ "skill.src_index_missing",
40073
+ "skill.runtime_entrypoint_unsafe",
40074
+ "skill.runtime_entrypoint_missing",
40075
+ "skill.runtime_entrypoint_symlink",
40076
+ "skill.runtime_entrypoint_not_file"
40032
40077
  ]);
40033
40078
  for (let i = issues.length - 1;i >= 0; i--) {
40034
40079
  if (executableOnlyCodes.has(issues[i].code))
package/bin/mcp.js CHANGED
@@ -20019,7 +20019,7 @@ var package_default;
20019
20019
  var init_package = __esm(() => {
20020
20020
  package_default = {
20021
20021
  name: "@hasna/skills",
20022
- version: "0.8.6",
20022
+ version: "0.8.7",
20023
20023
  description: "Skills library for AI coding agents",
20024
20024
  type: "module",
20025
20025
  bin: {
@@ -36478,6 +36478,35 @@ function isSafeRelativePath(value) {
36478
36478
  const normalized = normalize(value).replace(/\\/g, "/");
36479
36479
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
36480
36480
  }
36481
+ function validateRuntimeEntry(skillPath, entrypoint, issues, warnings) {
36482
+ if (typeof entrypoint !== "string" || !isSafeRelativePath(entrypoint) || /^[a-zA-Z]:/.test(entrypoint) || entrypoint.includes("\\") || entrypoint.split("/").some((part) => !part || part === "." || part === "..")) {
36483
+ add(issues, "skill.runtime_entrypoint_unsafe", "runtime.entrypoint must be a canonical relative file path inside the skill directory");
36484
+ return;
36485
+ }
36486
+ const parts = entrypoint.split("/");
36487
+ let current = skillPath;
36488
+ for (let index = 0;index < parts.length; index++) {
36489
+ current = join7(current, parts[index]);
36490
+ let info;
36491
+ try {
36492
+ info = lstatSync3(current);
36493
+ } catch {
36494
+ add(issues, "skill.runtime_entrypoint_missing", "The declared runtime.entrypoint is missing or inaccessible");
36495
+ return;
36496
+ }
36497
+ if (info.isSymbolicLink()) {
36498
+ add(issues, "skill.runtime_entrypoint_symlink", "runtime.entrypoint must not traverse symbolic links");
36499
+ return;
36500
+ }
36501
+ if (index < parts.length - 1 ? !info.isDirectory() : !info.isFile()) {
36502
+ add(issues, "skill.runtime_entrypoint_not_file", "runtime.entrypoint must resolve to a regular file");
36503
+ return;
36504
+ }
36505
+ if (index === parts.length - 1 && info.size < 50) {
36506
+ add(warnings, "skill.runtime_entrypoint_minimal", `Source entry point is very small (${info.size}B)`);
36507
+ }
36508
+ }
36509
+ }
36481
36510
  function isHostedPackageMetadata(pkg) {
36482
36511
  return isHostedMetadataPackage(pkg);
36483
36512
  }
@@ -36713,10 +36742,22 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
36713
36742
  } else {
36714
36743
  metadata.runtime = hostedMetadata ? "hosted" : "local";
36715
36744
  const srcDir = join7(skillPath, "src");
36745
+ let declaredEntrypoint;
36746
+ const manifestPath = join7(skillPath, "skill.json");
36747
+ if (!hostedMetadata && existsSync4(manifestPath)) {
36748
+ try {
36749
+ const manifest = asRecord(readJsonFile(manifestPath));
36750
+ declaredEntrypoint = asRecord(manifest?.runtime)?.entrypoint;
36751
+ } catch {
36752
+ add(issues, "skill.manifest_invalid", "skill.json must contain valid JSON");
36753
+ }
36754
+ }
36716
36755
  if (hostedMetadata) {
36717
36756
  if (existsSync4(srcDir)) {
36718
36757
  add(issues, "skill.hosted_source_forbidden", "Hosted metadata skills must not include local implementation source");
36719
36758
  }
36759
+ } else if (declaredEntrypoint !== undefined && declaredEntrypoint !== null) {
36760
+ validateRuntimeEntry(skillPath, declaredEntrypoint, issues, warnings);
36720
36761
  } else if (!existsSync4(srcDir)) {
36721
36762
  add(issues, "skill.src_missing", "Missing src/ directory");
36722
36763
  } else if (!existsSync4(join7(srcDir, "index.ts")) && !existsSync4(join7(srcDir, "index.js"))) {
@@ -38176,7 +38217,11 @@ function validatePortableSkillDirectory(name, skillPath) {
38176
38217
  "package.missing",
38177
38218
  "package.bin_missing",
38178
38219
  "skill.src_missing",
38179
- "skill.src_index_missing"
38220
+ "skill.src_index_missing",
38221
+ "skill.runtime_entrypoint_unsafe",
38222
+ "skill.runtime_entrypoint_missing",
38223
+ "skill.runtime_entrypoint_symlink",
38224
+ "skill.runtime_entrypoint_not_file"
38180
38225
  ]);
38181
38226
  for (let i = issues.length - 1;i >= 0; i--) {
38182
38227
  if (executableOnlyCodes.has(issues[i].code))
package/bin/migrate.js CHANGED
@@ -7,7 +7,7 @@ import { join as join5 } from "path";
7
7
  // package.json
8
8
  var package_default = {
9
9
  name: "@hasna/skills",
10
- version: "0.8.6",
10
+ version: "0.8.7",
11
11
  description: "Skills library for AI coding agents",
12
12
  type: "module",
13
13
  bin: {
package/bin/server.js CHANGED
@@ -83749,7 +83749,7 @@ var require_protocols9 = __commonJS((exports) => {
83749
83749
  // package.json
83750
83750
  var package_default = {
83751
83751
  name: "@hasna/skills",
83752
- version: "0.8.6",
83752
+ version: "0.8.7",
83753
83753
  description: "Skills library for AI coding agents",
83754
83754
  type: "module",
83755
83755
  bin: {
package/bin/worker.js CHANGED
@@ -76168,7 +76168,7 @@ import { randomUUID as randomUUID6 } from "crypto";
76168
76168
  // package.json
76169
76169
  var package_default = {
76170
76170
  name: "@hasna/skills",
76171
- version: "0.8.6",
76171
+ version: "0.8.7",
76172
76172
  description: "Skills library for AI coding agents",
76173
76173
  type: "module",
76174
76174
  bin: {
package/dist/index.js CHANGED
@@ -7376,6 +7376,35 @@ function isSafeRelativePath(value) {
7376
7376
  const normalized = normalize(value).replace(/\\/g, "/");
7377
7377
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
7378
7378
  }
7379
+ function validateRuntimeEntry(skillPath, entrypoint, issues, warnings) {
7380
+ if (typeof entrypoint !== "string" || !isSafeRelativePath(entrypoint) || /^[a-zA-Z]:/.test(entrypoint) || entrypoint.includes("\\") || entrypoint.split("/").some((part) => !part || part === "." || part === "..")) {
7381
+ add(issues, "skill.runtime_entrypoint_unsafe", "runtime.entrypoint must be a canonical relative file path inside the skill directory");
7382
+ return;
7383
+ }
7384
+ const parts = entrypoint.split("/");
7385
+ let current = skillPath;
7386
+ for (let index = 0;index < parts.length; index++) {
7387
+ current = join4(current, parts[index]);
7388
+ let info;
7389
+ try {
7390
+ info = lstatSync(current);
7391
+ } catch {
7392
+ add(issues, "skill.runtime_entrypoint_missing", "The declared runtime.entrypoint is missing or inaccessible");
7393
+ return;
7394
+ }
7395
+ if (info.isSymbolicLink()) {
7396
+ add(issues, "skill.runtime_entrypoint_symlink", "runtime.entrypoint must not traverse symbolic links");
7397
+ return;
7398
+ }
7399
+ if (index < parts.length - 1 ? !info.isDirectory() : !info.isFile()) {
7400
+ add(issues, "skill.runtime_entrypoint_not_file", "runtime.entrypoint must resolve to a regular file");
7401
+ return;
7402
+ }
7403
+ if (index === parts.length - 1 && info.size < 50) {
7404
+ add(warnings, "skill.runtime_entrypoint_minimal", `Source entry point is very small (${info.size}B)`);
7405
+ }
7406
+ }
7407
+ }
7379
7408
  function isHostedPackageMetadata(pkg) {
7380
7409
  return isHostedMetadataPackage(pkg);
7381
7410
  }
@@ -7611,10 +7640,22 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
7611
7640
  } else {
7612
7641
  metadata.runtime = hostedMetadata ? "hosted" : "local";
7613
7642
  const srcDir = join4(skillPath, "src");
7643
+ let declaredEntrypoint;
7644
+ const manifestPath = join4(skillPath, "skill.json");
7645
+ if (!hostedMetadata && existsSync4(manifestPath)) {
7646
+ try {
7647
+ const manifest = asRecord(readJsonFile(manifestPath));
7648
+ declaredEntrypoint = asRecord(manifest?.runtime)?.entrypoint;
7649
+ } catch {
7650
+ add(issues, "skill.manifest_invalid", "skill.json must contain valid JSON");
7651
+ }
7652
+ }
7614
7653
  if (hostedMetadata) {
7615
7654
  if (existsSync4(srcDir)) {
7616
7655
  add(issues, "skill.hosted_source_forbidden", "Hosted metadata skills must not include local implementation source");
7617
7656
  }
7657
+ } else if (declaredEntrypoint !== undefined && declaredEntrypoint !== null) {
7658
+ validateRuntimeEntry(skillPath, declaredEntrypoint, issues, warnings);
7618
7659
  } else if (!existsSync4(srcDir)) {
7619
7660
  add(issues, "skill.src_missing", "Missing src/ directory");
7620
7661
  } else if (!existsSync4(join4(srcDir, "index.ts")) && !existsSync4(join4(srcDir, "index.js"))) {
@@ -9146,7 +9187,11 @@ function validatePortableSkillDirectory(name, skillPath) {
9146
9187
  "package.missing",
9147
9188
  "package.bin_missing",
9148
9189
  "skill.src_missing",
9149
- "skill.src_index_missing"
9190
+ "skill.src_index_missing",
9191
+ "skill.runtime_entrypoint_unsafe",
9192
+ "skill.runtime_entrypoint_missing",
9193
+ "skill.runtime_entrypoint_symlink",
9194
+ "skill.runtime_entrypoint_not_file"
9150
9195
  ]);
9151
9196
  for (let i = issues.length - 1;i >= 0; i--) {
9152
9197
  if (executableOnlyCodes.has(issues[i].code))
@@ -37660,7 +37705,7 @@ import { dirname as dirname14, relative as relative7 } from "path";
37660
37705
  // package.json
37661
37706
  var package_default = {
37662
37707
  name: "@hasna/skills",
37663
- version: "0.8.6",
37708
+ version: "0.8.7",
37664
37709
  description: "Skills library for AI coding agents",
37665
37710
  type: "module",
37666
37711
  bin: {
package/dist/sdk/index.js CHANGED
@@ -96141,7 +96141,7 @@ async function resolveExecutionGrant(input) {
96141
96141
  // package.json
96142
96142
  var package_default = {
96143
96143
  name: "@hasna/skills",
96144
- version: "0.8.6",
96144
+ version: "0.8.7",
96145
96145
  description: "Skills library for AI coding agents",
96146
96146
  type: "module",
96147
96147
  bin: {
@@ -98480,6 +98480,35 @@ function isSafeRelativePath(value) {
98480
98480
  const normalized = normalize(value).replace(/\\/g, "/");
98481
98481
  return normalized !== ".." && !normalized.startsWith("../") && !normalized.includes("/../");
98482
98482
  }
98483
+ function validateRuntimeEntry(skillPath, entrypoint, issues, warnings) {
98484
+ if (typeof entrypoint !== "string" || !isSafeRelativePath(entrypoint) || /^[a-zA-Z]:/.test(entrypoint) || entrypoint.includes("\\") || entrypoint.split("/").some((part) => !part || part === "." || part === "..")) {
98485
+ add(issues, "skill.runtime_entrypoint_unsafe", "runtime.entrypoint must be a canonical relative file path inside the skill directory");
98486
+ return;
98487
+ }
98488
+ const parts = entrypoint.split("/");
98489
+ let current = skillPath;
98490
+ for (let index = 0;index < parts.length; index++) {
98491
+ current = join18(current, parts[index]);
98492
+ let info;
98493
+ try {
98494
+ info = lstatSync13(current);
98495
+ } catch {
98496
+ add(issues, "skill.runtime_entrypoint_missing", "The declared runtime.entrypoint is missing or inaccessible");
98497
+ return;
98498
+ }
98499
+ if (info.isSymbolicLink()) {
98500
+ add(issues, "skill.runtime_entrypoint_symlink", "runtime.entrypoint must not traverse symbolic links");
98501
+ return;
98502
+ }
98503
+ if (index < parts.length - 1 ? !info.isDirectory() : !info.isFile()) {
98504
+ add(issues, "skill.runtime_entrypoint_not_file", "runtime.entrypoint must resolve to a regular file");
98505
+ return;
98506
+ }
98507
+ if (index === parts.length - 1 && info.size < 50) {
98508
+ add(warnings, "skill.runtime_entrypoint_minimal", `Source entry point is very small (${info.size}B)`);
98509
+ }
98510
+ }
98511
+ }
98483
98512
  function isHostedPackageMetadata(pkg) {
98484
98513
  return isHostedMetadataPackage(pkg);
98485
98514
  }
@@ -98715,10 +98744,22 @@ function validateSkillDirectory(name, skillPath, registryMeta) {
98715
98744
  } else {
98716
98745
  metadata.runtime = hostedMetadata ? "hosted" : "local";
98717
98746
  const srcDir = join18(skillPath, "src");
98747
+ let declaredEntrypoint;
98748
+ const manifestPath = join18(skillPath, "skill.json");
98749
+ if (!hostedMetadata && existsSync6(manifestPath)) {
98750
+ try {
98751
+ const manifest = asRecord(readJsonFile(manifestPath));
98752
+ declaredEntrypoint = asRecord(manifest?.runtime)?.entrypoint;
98753
+ } catch {
98754
+ add(issues, "skill.manifest_invalid", "skill.json must contain valid JSON");
98755
+ }
98756
+ }
98718
98757
  if (hostedMetadata) {
98719
98758
  if (existsSync6(srcDir)) {
98720
98759
  add(issues, "skill.hosted_source_forbidden", "Hosted metadata skills must not include local implementation source");
98721
98760
  }
98761
+ } else if (declaredEntrypoint !== undefined && declaredEntrypoint !== null) {
98762
+ validateRuntimeEntry(skillPath, declaredEntrypoint, issues, warnings);
98722
98763
  } else if (!existsSync6(srcDir)) {
98723
98764
  add(issues, "skill.src_missing", "Missing src/ directory");
98724
98765
  } else if (!existsSync6(join18(srcDir, "index.ts")) && !existsSync6(join18(srcDir, "index.js"))) {
@@ -100216,7 +100257,11 @@ function validatePortableSkillDirectory(name, skillPath) {
100216
100257
  "package.missing",
100217
100258
  "package.bin_missing",
100218
100259
  "skill.src_missing",
100219
- "skill.src_index_missing"
100260
+ "skill.src_index_missing",
100261
+ "skill.runtime_entrypoint_unsafe",
100262
+ "skill.runtime_entrypoint_missing",
100263
+ "skill.runtime_entrypoint_symlink",
100264
+ "skill.runtime_entrypoint_not_file"
100220
100265
  ]);
100221
100266
  for (let i = issues.length - 1;i >= 0; i--) {
100222
100267
  if (executableOnlyCodes.has(issues[i].code))
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@hasna/skills",
3
- "version": "0.8.6",
3
+ "version": "0.8.7",
4
4
  "description": "Skills library for AI coding agents",
5
5
  "type": "module",
6
6
  "bin": {