@skillbase/compiler 0.2.4 → 0.2.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/dist/index.cjs CHANGED
@@ -30,17 +30,22 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
30
30
  // src/index.ts
31
31
  var index_exports = {};
32
32
  __export(index_exports, {
33
+ SECTION_ORDER: () => SECTION_ORDER,
34
+ SECTION_TYPE_LABELS: () => SECTION_TYPE_LABELS,
33
35
  SkillParseError: () => SkillParseError,
34
36
  SoulParseError: () => SoulParseError,
37
+ autoFixSections: () => autoFixSections,
35
38
  buildLegacyBody: () => buildLegacyBody,
36
39
  canonicalToParsedSkill: () => canonicalToParsedSkill,
37
40
  canonicalToParsedSoul: () => canonicalToParsedSoul,
38
41
  compile: () => compile,
39
42
  convertVercelToSpm: () => convertVercelToSpm,
43
+ denormalizeCanonical: () => denormalizeCanonical,
40
44
  detectFormat: () => detectFormat,
41
45
  getCompiler: () => getCompiler,
42
46
  getImporter: () => getImporter,
43
47
  importFromFormat: () => importFromFormat,
48
+ inferSectionType: () => inferSectionType,
44
49
  inferTags: () => inferTags,
45
50
  isVercelFormat: () => isVercelFormat,
46
51
  legacyPersonaToSoul: () => legacyPersonaToSoul,
@@ -51,9 +56,12 @@ __export(index_exports, {
51
56
  parseSoul: () => parseSoul,
52
57
  parsedSkillToCanonical: () => parsedSkillToCanonical,
53
58
  parsedSoulToCanonical: () => parsedSoulToCanonical,
59
+ reorderSections: () => reorderSections,
54
60
  resolveContextSlots: () => resolveContextSlots,
55
61
  serializeSkill: () => serializeSkill,
56
62
  serializeSoul: () => serializeSoul,
63
+ validateCanonicalOrder: () => validateCanonicalOrder,
64
+ validateSectionOrder: () => validateSectionOrder,
57
65
  validateSkillFrontmatter: () => validateSkillFrontmatter,
58
66
  validateSoulFrontmatter: () => validateSoulFrontmatter
59
67
  });
@@ -85,6 +93,91 @@ ${yamlStr}
85
93
  ${content}`;
86
94
  }
87
95
 
96
+ // src/section-order.ts
97
+ var SECTION_ORDER = {
98
+ context: 0,
99
+ instructions: 1,
100
+ guidelines: 2,
101
+ verification: 3,
102
+ examples: 4,
103
+ custom: 5
104
+ };
105
+ var SECTION_TYPE_LABELS = {
106
+ context: "Context",
107
+ instructions: "Instructions",
108
+ guidelines: "Guidelines",
109
+ verification: "Verification",
110
+ examples: "Examples",
111
+ custom: "Custom"
112
+ };
113
+ var TYPE_PATTERNS = [
114
+ {
115
+ type: "context",
116
+ keywords: /\b(context|background|overview|about|introduction|who you are|role|persona)\b/i
117
+ },
118
+ {
119
+ type: "examples",
120
+ keywords: /\b(example|sample|demo|few.?shot|illustration|showcase)\b/i
121
+ },
122
+ {
123
+ type: "guidelines",
124
+ keywords: /\b(guideline|style|convention|best.?practice|approach|principle|standard|rule|format|tone)\b/i
125
+ },
126
+ {
127
+ type: "verification",
128
+ keywords: /\b(verif|check|valid|review|self.?check|quality|assert|ensure|confirm|output.?requirement)\b/i
129
+ },
130
+ {
131
+ type: "instructions",
132
+ keywords: /\b(instruct|task|step|procedure|workflow|process|how to|implement|action|do)\b/i
133
+ }
134
+ ];
135
+ function inferSectionType(label) {
136
+ if (!label) return "instructions";
137
+ for (const { type, keywords } of TYPE_PATTERNS) {
138
+ if (keywords.test(label)) return type;
139
+ }
140
+ return "custom";
141
+ }
142
+ function validateSectionOrder(sections) {
143
+ if (sections.length <= 1) return [];
144
+ const reordered = reorderSections(sections);
145
+ const issues = [];
146
+ for (let i = 0; i < sections.length; i++) {
147
+ const current = sections[i];
148
+ const expectedIdx = reordered.indexOf(current);
149
+ if (expectedIdx !== i) {
150
+ const typeLabel = SECTION_TYPE_LABELS[current.type] ?? current.type;
151
+ issues.push({
152
+ index: i,
153
+ section: current,
154
+ expectedIndex: expectedIdx,
155
+ message: `"${current.label || typeLabel}" is at position ${i + 1}, expected ${expectedIdx + 1}`
156
+ });
157
+ }
158
+ }
159
+ return issues;
160
+ }
161
+ function reorderSections(sections) {
162
+ return [...sections].sort((a, b) => {
163
+ const orderA = SECTION_ORDER[a.type] ?? SECTION_ORDER.custom;
164
+ const orderB = SECTION_ORDER[b.type] ?? SECTION_ORDER.custom;
165
+ return orderA - orderB;
166
+ });
167
+ }
168
+ function autoFixSections(sections) {
169
+ const typed = sections.map((s) => {
170
+ if (s.type !== "custom") return s;
171
+ return { ...s, type: inferSectionType(s.label ?? "") };
172
+ });
173
+ return reorderSections(typed);
174
+ }
175
+ function validateCanonicalOrder(canonical) {
176
+ const sections = canonical.instructions.sections;
177
+ if (!sections || sections.length <= 1) return [];
178
+ return validateSectionOrder(sections);
179
+ }
180
+
88
181
  // src/parse/skill-parser.ts
89
182
  var REQUIRED_FIELDS = [
90
183
  "schema_version",
@@ -158,26 +251,46 @@ function splitBodyIntoSections(body) {
158
251
  return { sections };
159
252
  }
160
253
  function normalizeCanonical(canonical) {
161
- const { content, sections } = canonical.instructions;
162
- if (sections && sections.length > 0) return canonical;
163
- if (!content) return canonical;
164
- const { sections: parsed } = splitBodyIntoSections(content);
165
- if (parsed.length === 0) return canonical;
254
+ const flat = denormalizeCanonical(canonical);
255
+ const fullContent = flat.instructions.content;
256
+ if (!fullContent) return canonical;
257
+ const { sections } = splitBodyIntoSections(fullContent);
258
+ if (sections.length === 0) return canonical;
166
259
  return {
167
260
  ...canonical,
168
261
  instructions: {
169
262
  content: "",
170
- sections: parsed.map((s) => ({
171
- type: "custom",
263
+ sections: sections.map((s) => ({
264
+ type: inferSectionType(s.label),
172
265
  label: s.label,
173
266
  content: s.content
174
267
  }))
175
268
  }
176
269
  };
177
270
  }
271
+ function denormalizeCanonical(canonical) {
272
+ const sections = canonical.instructions.sections ?? [];
273
+ if (sections.length === 0) return canonical;
274
+ const parts = [];
275
+ if (canonical.instructions.content) {
276
+ parts.push(canonical.instructions.content);
277
+ }
278
+ for (const s of sections) {
279
+ if (s.label) {
280
+ parts.push(`## ${s.label}
281
+
282
+ ${s.content}`);
283
+ } else if (s.content) {
284
+ parts.push(s.content);
285
+ }
286
+ }
287
+ return {
288
+ ...canonical,
289
+ instructions: { content: parts.join("\n\n") }
290
+ };
291
+ }
178
292
  function parsedSkillToCanonical(skill) {
179
293
  const fm = skill.frontmatter;
180
- const { sections } = splitBodyIntoSections(skill.body);
181
294
  const canonical = {
182
295
  meta: {
183
296
  name: fm.name,
@@ -191,12 +304,7 @@ function parsedSkillToCanonical(skill) {
191
304
  confidence: 1
192
305
  },
193
306
  instructions: {
194
- content: "",
195
- sections: sections.map((s) => ({
196
- type: "custom",
197
- label: s.label,
198
- content: s.content
199
- }))
307
+ content: skill.body
200
308
  },
201
309
  rawBody: skill.body,
202
310
  sourceFormat: "skill-md"
@@ -1267,7 +1375,21 @@ function buildFlatBody(canonical, options) {
1267
1375
  parts.push(`Tone: ${canonical.identity.tone}`, "");
1268
1376
  }
1269
1377
  }
1270
- parts.push(canonical.rawBody ?? canonical.instructions.content);
1378
+ const sections = canonical.instructions.sections;
1379
+ if (sections && sections.length > 0) {
1380
+ const sorted = reorderSections(sections);
1381
+ for (const s of sorted) {
1382
+ if (s.label) {
1383
+ parts.push(`## ${s.label}
1384
+
1385
+ ${s.content}`);
1386
+ } else if (s.content) {
1387
+ parts.push(s.content);
1388
+ }
1389
+ }
1390
+ } else {
1391
+ parts.push(canonical.rawBody ?? canonical.instructions.content);
1392
+ }
1271
1393
  if (canonical.constraints) {
1272
1394
  if (canonical.constraints.always && canonical.constraints.always.length > 0) {
1273
1395
  parts.push(
@@ -1307,7 +1429,7 @@ function buildBody(canonical) {
1307
1429
  if (canonical.instructions.content) {
1308
1430
  parts.push(canonical.instructions.content);
1309
1431
  }
1310
- const sections = canonical.instructions.sections ?? [];
1432
+ const sections = reorderSections(canonical.instructions.sections ?? []);
1311
1433
  for (const s of sections) {
1312
1434
  if (s.label || s.content) {
1313
1435
  if (s.label) {
@@ -1767,17 +1889,22 @@ function getCompiler(target) {
1767
1889
  }
1768
1890
  // Annotate the CommonJS export names for ESM import in node:
1769
1891
  0 && (module.exports = {
1892
+ SECTION_ORDER,
1893
+ SECTION_TYPE_LABELS,
1770
1894
  SkillParseError,
1771
1895
  SoulParseError,
1896
+ autoFixSections,
1772
1897
  buildLegacyBody,
1773
1898
  canonicalToParsedSkill,
1774
1899
  canonicalToParsedSoul,
1775
1900
  compile,
1776
1901
  convertVercelToSpm,
1902
+ denormalizeCanonical,
1777
1903
  detectFormat,
1778
1904
  getCompiler,
1779
1905
  getImporter,
1780
1906
  importFromFormat,
1907
+ inferSectionType,
1781
1908
  inferTags,
1782
1909
  isVercelFormat,
1783
1910
  legacyPersonaToSoul,
@@ -1788,9 +1915,12 @@ function getCompiler(target) {
1788
1915
  parseSoul,
1789
1916
  parsedSkillToCanonical,
1790
1917
  parsedSoulToCanonical,
1918
+ reorderSections,
1791
1919
  resolveContextSlots,
1792
1920
  serializeSkill,
1793
1921
  serializeSoul,
1922
+ validateCanonicalOrder,
1923
+ validateSectionOrder,
1794
1924
  validateSkillFrontmatter,
1795
1925
  validateSoulFrontmatter
1796
1926
  });