load-skills 0.2.0 → 0.2.2

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/README.md CHANGED
@@ -58,5 +58,4 @@ These warnings appear on `report.invalidSkills[*].warnings`.
58
58
  - `invalid_meta_name`: `name` is present but not a non-empty string.
59
59
  - `invalid_meta_description`: `description` is present but not a non-empty string.
60
60
  - `skill_md_content_size_limit_exceeded`: `SKILL.md` body exceeds 500 lines.
61
- - `reference_large_without_toc`: A `references/` file exceeds 300 lines without a table-of-contents marker.
62
61
  - `resource_read_error`: A resource file or directory could not be read during scanning.
package/dist/discovery.js CHANGED
@@ -60,10 +60,15 @@ async function discoverNonRecursive(rootPath) {
60
60
  const entries = await readdir(rootPath, { withFileTypes: true });
61
61
  const paths = [];
62
62
  for (const entry of entries.sort((a, b) => a.name.localeCompare(b.name))) {
63
- if (!entry.isDirectory()) {
63
+ if (!entry.isDirectory() && !entry.isSymbolicLink()) {
64
64
  continue;
65
65
  }
66
- const candidate = path.join(rootPath, entry.name, "SKILL.md");
66
+ const candidateDir = path.join(rootPath, entry.name);
67
+ const candidateDirStat = await stat(candidateDir).catch(() => null);
68
+ if (!candidateDirStat?.isDirectory()) {
69
+ continue;
70
+ }
71
+ const candidate = path.join(candidateDir, "SKILL.md");
67
72
  if (await isReadableFile(candidate)) {
68
73
  paths.push(candidate);
69
74
  }
@@ -80,7 +85,11 @@ async function discoverRecursive(rootPath) {
80
85
  paths.push(fullPath);
81
86
  continue;
82
87
  }
83
- if (entry.isDirectory()) {
88
+ if (entry.isDirectory() || entry.isSymbolicLink()) {
89
+ const directoryStat = await stat(fullPath).catch(() => null);
90
+ if (!directoryStat?.isDirectory()) {
91
+ continue;
92
+ }
84
93
  await walk(fullPath);
85
94
  }
86
95
  }
@@ -1 +1 @@
1
- {"version":3,"file":"loadSkills.d.ts","sourceRoot":"","sources":["../src/loadSkills.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,gBAAgB,EAChB,gBAAgB,EAKjB,MAAM,YAAY,CAAC;AAOpB,wBAAsB,UAAU,CAC9B,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,gBAAgB,CAAC,CAgH3B"}
1
+ {"version":3,"file":"loadSkills.d.ts","sourceRoot":"","sources":["../src/loadSkills.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAGV,gBAAgB,EAChB,gBAAgB,EAKjB,MAAM,YAAY,CAAC;AAIpB,wBAAsB,UAAU,CAC9B,MAAM,CAAC,EAAE,gBAAgB,GACxB,OAAO,CAAC,gBAAgB,CAAC,CA2G3B"}
@@ -4,7 +4,7 @@ import path from "node:path";
4
4
  import { discoverSkillFiles } from "./discovery.js";
5
5
  import { parseSkillDocument } from "./parseSkill.js";
6
6
  import { getErrorMessage, pathExists } from "./utils.js";
7
- import { applyValidationRules, validateLargeReferences, } from "./validateSkill.js";
7
+ import { applyValidationRules } from "./validateSkill.js";
8
8
  export async function loadSkills(config) {
9
9
  const resolvedConfig = config ?? {};
10
10
  const discovery = await discoverSkillFiles(resolvedConfig);
@@ -22,8 +22,6 @@ export async function loadSkills(config) {
22
22
  skillWarnings.push(...parsed.warnings);
23
23
  const resourceScan = await collectResources(skillPath);
24
24
  skillWarnings.push(...resourceScan.warnings);
25
- const largeReferenceWarnings = validateLargeReferences(resourceScan.referenceContents);
26
- skillWarnings.push(...largeReferenceWarnings);
27
25
  const validated = applyValidationRules({
28
26
  meta: parsed.meta,
29
27
  content: parsed.content,
@@ -101,15 +99,9 @@ async function collectResources(skillPath) {
101
99
  const warnings = [];
102
100
  const referenceFiles = await listFilesRecursively(referencesRoot, warnings);
103
101
  const scriptFiles = await listFilesRecursively(scriptsRoot, warnings);
104
- const referenceContents = [];
105
102
  for (const filePath of referenceFiles) {
106
103
  try {
107
- const content = await readFile(filePath, "utf8");
108
- referenceContents.push({
109
- path: filePath,
110
- content,
111
- lineCount: content.length === 0 ? 0 : content.split(/\r?\n/).length,
112
- });
104
+ await readFile(filePath, "utf8");
113
105
  }
114
106
  catch (error) {
115
107
  warnings.push({
@@ -127,7 +119,6 @@ async function collectResources(skillPath) {
127
119
  }
128
120
  return {
129
121
  references: referenceFiles.sort((a, b) => a.localeCompare(b)),
130
- referenceContents,
131
122
  scripts: scripts.sort((a, b) => a.path.localeCompare(b.path)),
132
123
  warnings,
133
124
  };
package/dist/types.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  export type SkillScriptType = "javascript" | "typescript" | "python" | "shell" | "ruby" | "other";
2
- export type SkillWarningCode = "missing_frontmatter" | "invalid_yaml_frontmatter" | "missing_required_meta_name" | "missing_required_meta_description" | "invalid_meta_name" | "invalid_meta_description" | "skill_md_content_size_limit_exceeded" | "reference_large_without_toc" | "resource_read_error";
2
+ export type SkillWarningCode = "missing_frontmatter" | "invalid_yaml_frontmatter" | "missing_required_meta_name" | "missing_required_meta_description" | "invalid_meta_name" | "invalid_meta_description" | "skill_md_content_size_limit_exceeded" | "resource_read_error";
3
3
  export interface SkillWarning {
4
4
  code: SkillWarningCode;
5
5
  message: string;
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,YAAY,GACZ,YAAY,GACZ,QAAQ,GACR,OAAO,GACP,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,MAAM,gBAAgB,GACxB,qBAAqB,GACrB,0BAA0B,GAC1B,4BAA4B,GAC5B,mCAAmC,GACnC,mBAAmB,GACnB,0BAA0B,GAC1B,sCAAsC,GACtC,6BAA6B,GAC7B,qBAAqB,CAAC;AAE1B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG,oBAAoB,CAAC;AAE1E,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,mBAAmB,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC;IAC3D,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9B,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,eAAe,GACvB,YAAY,GACZ,YAAY,GACZ,QAAQ,GACR,OAAO,GACP,MAAM,GACN,OAAO,CAAC;AAEZ,MAAM,MAAM,gBAAgB,GACxB,qBAAqB,GACrB,0BAA0B,GAC1B,4BAA4B,GAC5B,mCAAmC,GACnC,mBAAmB,GACnB,0BAA0B,GAC1B,sCAAsC,GACtC,qBAAqB,CAAC;AAE1B,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,gBAAgB,CAAC;IACvB,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,eAAe,CAAC;CACvB;AAED,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAChD,IAAI,EAAE,MAAM,CAAC;IACb,WAAW,EAAE,MAAM,CAAC;CACrB,CAAC;AAEF,MAAM,WAAW,KAAK;IACpB,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,WAAW,EAAE,CAAC;IACvB,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,SAAS,EAAE,MAAM,CAAC;IAClB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,CAAC,EAAE,MAAM,EAAE,CAAC;IACjB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG,oBAAoB,CAAC;AAE1E,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,KAAK,CAAC,EAAE,mBAAmB,CAAC;CAC7B;AAED,MAAM,WAAW,qBAAqB;IACpC,SAAS,EAAE,MAAM,CAAC;IAClB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,gBAAgB,EAAE,MAAM,CAAC;IACzB,oBAAoB,EAAE,MAAM,CAAC;IAC7B,oBAAoB,EAAE,MAAM,CAAC;IAC7B,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,MAAM,CAAC;CAC3B;AAED,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,oBAAoB,EAAE,CAAC;IAC9B,iBAAiB,EAAE,MAAM,CAAC,MAAM,EAAE,qBAAqB,EAAE,CAAC,CAAC;IAC3D,aAAa,EAAE,YAAY,EAAE,CAAC;CAC/B;AAED,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;IAC9B,MAAM,EAAE,gBAAgB,CAAC;CAC1B;AAED,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B"}
@@ -8,9 +8,4 @@ export declare function applyValidationRules(input: {
8
8
  isValid: boolean;
9
9
  meta?: SkillMeta;
10
10
  };
11
- export declare function validateLargeReferences(references: Array<{
12
- path: string;
13
- content: string;
14
- lineCount: number;
15
- }>): SkillWarning[];
16
11
  //# sourceMappingURL=validateSkill.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"validateSkill.d.ts","sourceRoot":"","sources":["../src/validateSkill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAc1D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B,GAAG;IACF,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,CAoDA;AAED,wBAAgB,uBAAuB,CACrC,UAAU,EAAE,KAAK,CAAC;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,CAAC,GACtE,YAAY,EAAE,CAqBhB"}
1
+ {"version":3,"file":"validateSkill.d.ts","sourceRoot":"","sources":["../src/validateSkill.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,YAAY,EAAE,MAAM,YAAY,CAAC;AAa1D,wBAAgB,oBAAoB,CAAC,KAAK,EAAE;IAC1C,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC;IAChB,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B,GAAG;IACF,QAAQ,EAAE,YAAY,EAAE,CAAC;IACzB,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,CAAC,EAAE,SAAS,CAAC;CAClB,CAoDA"}
@@ -6,7 +6,6 @@ const INVALID_WARNING_CODES = new Set([
6
6
  "invalid_meta_name",
7
7
  "invalid_meta_description",
8
8
  "skill_md_content_size_limit_exceeded",
9
- "reference_large_without_toc",
10
9
  "resource_read_error",
11
10
  ]);
12
11
  export function applyValidationRules(input) {
@@ -50,23 +49,6 @@ export function applyValidationRules(input) {
50
49
  isValid: false,
51
50
  };
52
51
  }
53
- export function validateLargeReferences(references) {
54
- const warnings = [];
55
- for (const reference of references) {
56
- if (reference.lineCount <= 300) {
57
- continue;
58
- }
59
- const normalized = reference.content.toLowerCase();
60
- const hasTocMarker = normalized.includes("table of contents") || normalized.includes("[toc]");
61
- if (!hasTocMarker) {
62
- warnings.push({
63
- code: "reference_large_without_toc",
64
- message: `Large reference file is missing a table of contents hint: ${reference.path}`,
65
- });
66
- }
67
- }
68
- return warnings;
69
- }
70
52
  function dedupeWarnings(warnings) {
71
53
  const keys = new Set();
72
54
  const deduped = [];
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "load-skills",
3
- "version": "0.2.0",
3
+ "version": "0.2.2",
4
4
  "description": "Load and validate agent skills from configurable paths.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",