@matimo/core 0.1.0-alpha.12 → 0.1.0-alpha.13
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 +169 -8
- package/dist/approval/approval-handler.d.ts +5 -1
- package/dist/approval/approval-handler.d.ts.map +1 -1
- package/dist/approval/approval-handler.js +6 -0
- package/dist/approval/approval-handler.js.map +1 -1
- package/dist/core/schema.d.ts +29 -8
- package/dist/core/schema.d.ts.map +1 -1
- package/dist/core/schema.js +10 -3
- package/dist/core/schema.js.map +1 -1
- package/dist/core/skill-content-parser.d.ts +91 -0
- package/dist/core/skill-content-parser.d.ts.map +1 -0
- package/dist/core/skill-content-parser.js +248 -0
- package/dist/core/skill-content-parser.js.map +1 -0
- package/dist/core/skill-loader.d.ts +46 -0
- package/dist/core/skill-loader.d.ts.map +1 -0
- package/dist/core/skill-loader.js +310 -0
- package/dist/core/skill-loader.js.map +1 -0
- package/dist/core/skill-registry.d.ts +131 -0
- package/dist/core/skill-registry.d.ts.map +1 -0
- package/dist/core/skill-registry.js +316 -0
- package/dist/core/skill-registry.js.map +1 -0
- package/dist/core/tfidf-embedding.d.ts +45 -0
- package/dist/core/tfidf-embedding.d.ts.map +1 -0
- package/dist/core/tfidf-embedding.js +199 -0
- package/dist/core/tfidf-embedding.js.map +1 -0
- package/dist/core/types.d.ts +192 -6
- package/dist/core/types.d.ts.map +1 -1
- package/dist/encodings/parameter-encoding.d.ts.map +1 -1
- package/dist/encodings/parameter-encoding.js +6 -2
- package/dist/encodings/parameter-encoding.js.map +1 -1
- package/dist/errors/matimo-error.d.ts +3 -1
- package/dist/errors/matimo-error.d.ts.map +1 -1
- package/dist/errors/matimo-error.js +2 -0
- package/dist/errors/matimo-error.js.map +1 -1
- package/dist/executors/command-executor.d.ts +9 -2
- package/dist/executors/command-executor.d.ts.map +1 -1
- package/dist/executors/command-executor.js +14 -2
- package/dist/executors/command-executor.js.map +1 -1
- package/dist/executors/function-executor.d.ts +10 -3
- package/dist/executors/function-executor.d.ts.map +1 -1
- package/dist/executors/function-executor.js +11 -4
- package/dist/executors/function-executor.js.map +1 -1
- package/dist/executors/http-executor.d.ts +16 -2
- package/dist/executors/http-executor.d.ts.map +1 -1
- package/dist/executors/http-executor.js +22 -6
- package/dist/executors/http-executor.js.map +1 -1
- package/dist/index.d.ts +20 -3
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/dist/integrations/langchain.d.ts +55 -0
- package/dist/integrations/langchain.d.ts.map +1 -1
- package/dist/integrations/langchain.js +66 -0
- package/dist/integrations/langchain.js.map +1 -1
- package/dist/logging/winston-logger.d.ts.map +1 -1
- package/dist/logging/winston-logger.js +9 -1
- package/dist/logging/winston-logger.js.map +1 -1
- package/dist/matimo-instance.d.ts +210 -18
- package/dist/matimo-instance.d.ts.map +1 -1
- package/dist/matimo-instance.js +704 -40
- package/dist/matimo-instance.js.map +1 -1
- package/dist/mcp/mcp-server.d.ts +23 -0
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +119 -8
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/tool-converter.d.ts.map +1 -1
- package/dist/mcp/tool-converter.js +10 -1
- package/dist/mcp/tool-converter.js.map +1 -1
- package/dist/policy/approval-manifest.d.ts +74 -0
- package/dist/policy/approval-manifest.d.ts.map +1 -0
- package/dist/policy/approval-manifest.js +178 -0
- package/dist/policy/approval-manifest.js.map +1 -0
- package/dist/policy/content-validator.d.ts +19 -0
- package/dist/policy/content-validator.d.ts.map +1 -0
- package/dist/policy/content-validator.js +196 -0
- package/dist/policy/content-validator.js.map +1 -0
- package/dist/policy/default-policy.d.ts +46 -0
- package/dist/policy/default-policy.d.ts.map +1 -0
- package/dist/policy/default-policy.js +241 -0
- package/dist/policy/default-policy.js.map +1 -0
- package/dist/policy/events.d.ts +71 -0
- package/dist/policy/events.d.ts.map +1 -0
- package/dist/policy/events.js +8 -0
- package/dist/policy/events.js.map +1 -0
- package/dist/policy/index.d.ts +13 -0
- package/dist/policy/index.d.ts.map +1 -0
- package/dist/policy/index.js +9 -0
- package/dist/policy/index.js.map +1 -0
- package/dist/policy/integrity-tracker.d.ts +62 -0
- package/dist/policy/integrity-tracker.d.ts.map +1 -0
- package/dist/policy/integrity-tracker.js +79 -0
- package/dist/policy/integrity-tracker.js.map +1 -0
- package/dist/policy/policy-loader.d.ts +58 -0
- package/dist/policy/policy-loader.d.ts.map +1 -0
- package/dist/policy/policy-loader.js +153 -0
- package/dist/policy/policy-loader.js.map +1 -0
- package/dist/policy/risk-classifier.d.ts +18 -0
- package/dist/policy/risk-classifier.d.ts.map +1 -0
- package/dist/policy/risk-classifier.js +43 -0
- package/dist/policy/risk-classifier.js.map +1 -0
- package/dist/policy/types.d.ts +126 -0
- package/dist/policy/types.d.ts.map +1 -0
- package/dist/policy/types.js +8 -0
- package/dist/policy/types.js.map +1 -0
- package/package.json +2 -2
- package/tools/matimo_approve_tool/definition.yaml +36 -0
- package/tools/matimo_approve_tool/matimo_approve_tool.ts +90 -0
- package/tools/matimo_create_skill/definition.yaml +46 -0
- package/tools/matimo_create_skill/matimo_create_skill.ts +75 -0
- package/tools/matimo_create_tool/definition.yaml +48 -0
- package/tools/matimo_create_tool/matimo_create_tool.ts +137 -0
- package/tools/matimo_get_skill/definition.yaml +60 -0
- package/tools/matimo_get_skill/matimo_get_skill.ts +182 -0
- package/tools/matimo_get_tool_status/definition.yaml +42 -0
- package/tools/matimo_get_tool_status/matimo_get_tool_status.ts +101 -0
- package/tools/matimo_list_skills/definition.yaml +52 -0
- package/tools/matimo_list_skills/matimo_list_skills.ts +138 -0
- package/tools/matimo_list_user_tools/definition.yaml +32 -0
- package/tools/matimo_list_user_tools/matimo_list_user_tools.ts +74 -0
- package/tools/matimo_reload_tools/definition.yaml +35 -0
- package/tools/matimo_reload_tools/matimo_reload_tools.ts +29 -0
- package/tools/matimo_validate_skill/definition.yaml +43 -0
- package/tools/matimo_validate_skill/matimo_validate_skill.ts +137 -0
- package/tools/matimo_validate_tool/definition.yaml +34 -0
- package/tools/matimo_validate_tool/matimo_validate_tool.ts +168 -0
- package/tools/shared/skill-validation.ts +335 -0
|
@@ -0,0 +1,248 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Content Parser — Markdown AST-based section chunking
|
|
3
|
+
*
|
|
4
|
+
* Breaks skill bodies into structured sections so agents load only the parts
|
|
5
|
+
* they need instead of dumping the entire SKILL.md into context.
|
|
6
|
+
*
|
|
7
|
+
* Uses lightweight heading-based parsing (no external Markdown AST library
|
|
8
|
+
* needed) to produce a tree of sections with token-count estimates.
|
|
9
|
+
*/
|
|
10
|
+
// ─── Helper: Check if line is a Markdown heading using safe string operations ─────────
|
|
11
|
+
// Avoids regex to prevent ReDoS on malicious input with many spaces
|
|
12
|
+
function parseHeading(line) {
|
|
13
|
+
if (!line.startsWith('#'))
|
|
14
|
+
return null;
|
|
15
|
+
let level = 0;
|
|
16
|
+
for (let i = 0; i < Math.min(6, line.length); i++) {
|
|
17
|
+
if (line[i] === '#')
|
|
18
|
+
level++;
|
|
19
|
+
else
|
|
20
|
+
break;
|
|
21
|
+
}
|
|
22
|
+
if (level === 0 || level > 6)
|
|
23
|
+
return null;
|
|
24
|
+
// Check that after the hashes, there's whitespace
|
|
25
|
+
if (level >= line.length || !/\s/.test(line[level]))
|
|
26
|
+
return null;
|
|
27
|
+
// Extract heading text after the hashes and skip leading whitespace
|
|
28
|
+
const heading = line.substring(level).trimStart();
|
|
29
|
+
return { level, heading };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Estimate token count from text.
|
|
33
|
+
* Rough heuristic: 1 token ≈ 0.75 words for English text.
|
|
34
|
+
* Conservative to avoid under-counting.
|
|
35
|
+
*/
|
|
36
|
+
function estimateTokens(text) {
|
|
37
|
+
if (!text)
|
|
38
|
+
return 0;
|
|
39
|
+
const wordCount = text.split(/\s+/).filter(Boolean).length;
|
|
40
|
+
return Math.ceil(wordCount / 0.75);
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Parse a Markdown skill body into a tree of sections.
|
|
44
|
+
*
|
|
45
|
+
* This is a lightweight parser that splits on ATX headings (lines starting
|
|
46
|
+
* with #). It does NOT handle:
|
|
47
|
+
* - Setext headings (underline style)
|
|
48
|
+
* - Headings inside code blocks (these are treated as content)
|
|
49
|
+
*
|
|
50
|
+
* For SKILL.md files (which follow a consistent format), this is sufficient.
|
|
51
|
+
*/
|
|
52
|
+
export function parseSkillSections(body) {
|
|
53
|
+
if (!body || body.trim().length === 0) {
|
|
54
|
+
return {
|
|
55
|
+
preamble: '',
|
|
56
|
+
preambleTokens: 0,
|
|
57
|
+
sections: [],
|
|
58
|
+
totalTokens: 0,
|
|
59
|
+
index: new Map(),
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const lines = body.split('\n');
|
|
63
|
+
const index = new Map();
|
|
64
|
+
const segments = [];
|
|
65
|
+
let currentSegment = null;
|
|
66
|
+
const preambleLines = [];
|
|
67
|
+
let inCodeBlock = false;
|
|
68
|
+
for (const line of lines) {
|
|
69
|
+
// Track fenced code blocks to avoid treating # inside them as headings
|
|
70
|
+
if (line.trimStart().startsWith('```')) {
|
|
71
|
+
inCodeBlock = !inCodeBlock;
|
|
72
|
+
}
|
|
73
|
+
if (!inCodeBlock) {
|
|
74
|
+
const headingMatch = parseHeading(line);
|
|
75
|
+
if (headingMatch) {
|
|
76
|
+
// Flush previous segment
|
|
77
|
+
if (currentSegment) {
|
|
78
|
+
segments.push(currentSegment);
|
|
79
|
+
}
|
|
80
|
+
currentSegment = {
|
|
81
|
+
heading: headingMatch.heading,
|
|
82
|
+
level: headingMatch.level,
|
|
83
|
+
contentLines: [],
|
|
84
|
+
};
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (currentSegment) {
|
|
89
|
+
currentSegment.contentLines.push(line);
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
preambleLines.push(line);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
// Flush last segment
|
|
96
|
+
if (currentSegment) {
|
|
97
|
+
segments.push(currentSegment);
|
|
98
|
+
}
|
|
99
|
+
const preamble = preambleLines.join('\n').trim();
|
|
100
|
+
const preambleTokens = estimateTokens(preamble);
|
|
101
|
+
// Build tree from flat list of segments using a stack
|
|
102
|
+
const topSections = [];
|
|
103
|
+
const stack = [];
|
|
104
|
+
for (const seg of segments) {
|
|
105
|
+
const content = seg.contentLines.join('\n').trim();
|
|
106
|
+
const section = {
|
|
107
|
+
heading: seg.heading,
|
|
108
|
+
level: seg.level,
|
|
109
|
+
content,
|
|
110
|
+
tokenEstimate: estimateTokens(content) + estimateTokens(seg.heading),
|
|
111
|
+
children: [],
|
|
112
|
+
path: seg.heading,
|
|
113
|
+
};
|
|
114
|
+
// Pop stack until we find a parent with a lower level
|
|
115
|
+
while (stack.length > 0 && stack[stack.length - 1].level >= seg.level) {
|
|
116
|
+
stack.pop();
|
|
117
|
+
}
|
|
118
|
+
if (stack.length > 0) {
|
|
119
|
+
const parent = stack[stack.length - 1];
|
|
120
|
+
section.path = `${parent.path}.${seg.heading}`;
|
|
121
|
+
parent.children.push(section);
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
topSections.push(section);
|
|
125
|
+
}
|
|
126
|
+
index.set(section.path.toLowerCase(), section);
|
|
127
|
+
stack.push(section);
|
|
128
|
+
}
|
|
129
|
+
// Calculate total tokens (recursive)
|
|
130
|
+
function totalTokensOf(section) {
|
|
131
|
+
return section.tokenEstimate + section.children.reduce((sum, c) => sum + totalTokensOf(c), 0);
|
|
132
|
+
}
|
|
133
|
+
const totalTokens = preambleTokens + topSections.reduce((sum, s) => sum + totalTokensOf(s), 0);
|
|
134
|
+
return {
|
|
135
|
+
preamble,
|
|
136
|
+
preambleTokens,
|
|
137
|
+
sections: topSections,
|
|
138
|
+
totalTokens,
|
|
139
|
+
index,
|
|
140
|
+
};
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Selectively extract content from a parsed skill body.
|
|
144
|
+
*
|
|
145
|
+
* This is the key function for context management — instead of dumping the
|
|
146
|
+
* entire SKILL.md into the LLM's context window, agents call this to get
|
|
147
|
+
* only the sections they need.
|
|
148
|
+
*
|
|
149
|
+
* @example
|
|
150
|
+
* // Get only the error handling section
|
|
151
|
+
* extractSkillContent(parsed, { sections: ['Error Handling'] })
|
|
152
|
+
*
|
|
153
|
+
* @example
|
|
154
|
+
* // Get top-level overview only (no sub-sections), max 500 tokens
|
|
155
|
+
* extractSkillContent(parsed, { maxDepth: 1, maxTokens: 500 })
|
|
156
|
+
*/
|
|
157
|
+
export function extractSkillContent(parsed, options = {}) {
|
|
158
|
+
const { sections: requestedSections, maxTokens, includePreamble = true, maxDepth } = options;
|
|
159
|
+
const parts = [];
|
|
160
|
+
let currentTokens = 0;
|
|
161
|
+
// Helper: check if we've exceeded the token budget
|
|
162
|
+
function withinBudget(additional) {
|
|
163
|
+
if (maxTokens === undefined)
|
|
164
|
+
return true;
|
|
165
|
+
return currentTokens + additional <= maxTokens;
|
|
166
|
+
}
|
|
167
|
+
// Helper: render a section to Markdown
|
|
168
|
+
function renderSection(section, depth) {
|
|
169
|
+
const hashes = '#'.repeat(section.level);
|
|
170
|
+
let result = `${hashes} ${section.heading}\n\n${section.content}`;
|
|
171
|
+
if (maxDepth === undefined || depth < maxDepth) {
|
|
172
|
+
for (const child of section.children) {
|
|
173
|
+
result += '\n\n' + renderSection(child, depth + 1);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
return result;
|
|
177
|
+
}
|
|
178
|
+
// Add preamble
|
|
179
|
+
if (includePreamble && parsed.preamble) {
|
|
180
|
+
const tokens = parsed.preambleTokens;
|
|
181
|
+
if (withinBudget(tokens)) {
|
|
182
|
+
parts.push(parsed.preamble);
|
|
183
|
+
currentTokens += tokens;
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// If specific sections requested, find and include only those
|
|
187
|
+
if (requestedSections && requestedSections.length > 0) {
|
|
188
|
+
for (const requested of requestedSections) {
|
|
189
|
+
const lower = requested.toLowerCase();
|
|
190
|
+
// Try exact match first, then partial match
|
|
191
|
+
let found = parsed.index.get(lower);
|
|
192
|
+
if (!found) {
|
|
193
|
+
// Partial match: find first section whose path contains the query
|
|
194
|
+
for (const [key, section] of parsed.index) {
|
|
195
|
+
if (key.includes(lower)) {
|
|
196
|
+
found = section;
|
|
197
|
+
break;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
if (found) {
|
|
202
|
+
const rendered = renderSection(found, 1);
|
|
203
|
+
const tokens = estimateTokens(rendered);
|
|
204
|
+
if (withinBudget(tokens)) {
|
|
205
|
+
parts.push(rendered);
|
|
206
|
+
currentTokens += tokens;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
else {
|
|
212
|
+
// Include all sections (respecting maxDepth and maxTokens)
|
|
213
|
+
for (const section of parsed.sections) {
|
|
214
|
+
const rendered = renderSection(section, 1);
|
|
215
|
+
const tokens = estimateTokens(rendered);
|
|
216
|
+
if (withinBudget(tokens)) {
|
|
217
|
+
parts.push(rendered);
|
|
218
|
+
currentTokens += tokens;
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
break; // Stop adding sections once we exceed budget
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
return parts.join('\n\n');
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Get a flat list of all section headings with their token costs.
|
|
229
|
+
* Useful for agents to decide which sections to load.
|
|
230
|
+
*/
|
|
231
|
+
export function listSkillSections(parsed) {
|
|
232
|
+
const result = [];
|
|
233
|
+
function walk(section) {
|
|
234
|
+
result.push({
|
|
235
|
+
path: section.path,
|
|
236
|
+
level: section.level,
|
|
237
|
+
tokenEstimate: section.tokenEstimate,
|
|
238
|
+
});
|
|
239
|
+
for (const child of section.children) {
|
|
240
|
+
walk(child);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
for (const section of parsed.sections) {
|
|
244
|
+
walk(section);
|
|
245
|
+
}
|
|
246
|
+
return result;
|
|
247
|
+
}
|
|
248
|
+
//# sourceMappingURL=skill-content-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-content-parser.js","sourceRoot":"","sources":["../../src/core/skill-content-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Loader — loads and validates skills from multiple sources
|
|
3
|
+
*
|
|
4
|
+
* Implements agentskills.io specification with proper YAML parsing and Zod validation.
|
|
5
|
+
*
|
|
6
|
+
* @see https://agentskills.io/specification
|
|
7
|
+
*/
|
|
8
|
+
import { SkillDefinition, ParsedSkill, SkillSummary } from './types';
|
|
9
|
+
/**
|
|
10
|
+
* Parse YAML frontmatter from SKILL.md content
|
|
11
|
+
*/
|
|
12
|
+
export declare function parseSkillContent(content: string): ParsedSkill & {
|
|
13
|
+
error?: string;
|
|
14
|
+
};
|
|
15
|
+
/**
|
|
16
|
+
* Extract ONLY metadata from SKILL.md without parsing body/sections.
|
|
17
|
+
*
|
|
18
|
+
* Optimized for matimo_list_skills — reads YAML frontmatter only.
|
|
19
|
+
* This avoids the overhead of parsing sections and body content.
|
|
20
|
+
*
|
|
21
|
+
* Returns SkillSummary: name, description, version, license, metadata, source.
|
|
22
|
+
*/
|
|
23
|
+
export declare function extractSkillMetadata(content: string, source?: 'builtin' | 'user' | 'catalog'): {
|
|
24
|
+
success: boolean;
|
|
25
|
+
metadata?: SkillSummary;
|
|
26
|
+
error?: string;
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* SkillLoader reads and validates skills from directories
|
|
30
|
+
*/
|
|
31
|
+
export declare class SkillLoader {
|
|
32
|
+
private logger;
|
|
33
|
+
/**
|
|
34
|
+
* Load all skills from a directory
|
|
35
|
+
*/
|
|
36
|
+
loadSkillsFromDirectory(skillsDir: string, source?: 'builtin' | 'user' | 'catalog'): SkillDefinition[];
|
|
37
|
+
/**
|
|
38
|
+
* Load a single skill by name
|
|
39
|
+
*/
|
|
40
|
+
loadSkill(name: string, skillsDir: string, source?: 'builtin' | 'user' | 'catalog'): SkillDefinition | null;
|
|
41
|
+
/**
|
|
42
|
+
* Load a skill resource file (scripts/, references/, assets/)
|
|
43
|
+
*/
|
|
44
|
+
loadSkillResource(skillName: string, skillsDir: string, resourcePath: string): string;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=skill-loader.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-loader.d.ts","sourceRoot":"","sources":["../../src/core/skill-loader.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAMH,OAAO,EACL,eAAe,EAEf,WAAW,EAEX,YAAY,EACb,MAAM,SAAS,CAAC;AA4GjB;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,OAAO,EAAE,MAAM,GAAG,WAAW,GAAG;IAAE,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAsBnF;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,EAAE,MAAM,EACf,MAAM,GAAE,SAAS,GAAG,MAAM,GAAG,SAAkB,GAC9C;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,EAAE,YAAY,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,CAmB/D;AAiDD;;GAEG;AACH,qBAAa,WAAW;IACtB,OAAO,CAAC,MAAM,CAA2B;IAEzC;;OAEG;IACH,uBAAuB,CACrB,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,SAAS,GAAG,MAAM,GAAG,SAAkB,GAC9C,eAAe,EAAE;IA2CpB;;OAEG;IACH,SAAS,CACP,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,MAAM,EACjB,MAAM,GAAE,SAAS,GAAG,MAAM,GAAG,SAAkB,GAC9C,eAAe,GAAG,IAAI;IAuDzB;;OAEG;IACH,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,MAAM;CAgCtF"}
|
|
@@ -0,0 +1,310 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Skill Loader — loads and validates skills from multiple sources
|
|
3
|
+
*
|
|
4
|
+
* Implements agentskills.io specification with proper YAML parsing and Zod validation.
|
|
5
|
+
*
|
|
6
|
+
* @see https://agentskills.io/specification
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
import YAML from 'js-yaml';
|
|
11
|
+
import { z } from 'zod';
|
|
12
|
+
import { parseSkillSections } from './skill-content-parser';
|
|
13
|
+
import { getGlobalMatimoLogger } from '../logging';
|
|
14
|
+
import { MatimoError, ErrorCode } from '../errors/matimo-error';
|
|
15
|
+
// ─── Name Validation ─────────────────────────────────────────────────────────
|
|
16
|
+
const VALID_NAME_PATTERN = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
17
|
+
const CONSECUTIVE_HYPHENS = /--/;
|
|
18
|
+
const MAX_NAME_LENGTH = 64;
|
|
19
|
+
function validateSkillName(name) {
|
|
20
|
+
if (!name || name.trim().length === 0) {
|
|
21
|
+
return { valid: false, error: 'Skill name is required' };
|
|
22
|
+
}
|
|
23
|
+
if (name.length > MAX_NAME_LENGTH) {
|
|
24
|
+
return {
|
|
25
|
+
valid: false,
|
|
26
|
+
error: `Skill name must be at most ${MAX_NAME_LENGTH} characters`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if (!VALID_NAME_PATTERN.test(name)) {
|
|
30
|
+
return {
|
|
31
|
+
valid: false,
|
|
32
|
+
error: 'Skill name must contain only lowercase letters, numbers, and hyphens, and must not start or end with a hyphen',
|
|
33
|
+
};
|
|
34
|
+
}
|
|
35
|
+
if (CONSECUTIVE_HYPHENS.test(name)) {
|
|
36
|
+
return { valid: false, error: 'Skill name must not contain consecutive hyphens' };
|
|
37
|
+
}
|
|
38
|
+
return { valid: true };
|
|
39
|
+
}
|
|
40
|
+
// ─── YAML Parser & Validation ──────────────────────────────────────────────
|
|
41
|
+
/**
|
|
42
|
+
* Parser schema for skill frontmatter (using Zod for runtime validation)
|
|
43
|
+
*/
|
|
44
|
+
const FrontmatterSchema = z.object({
|
|
45
|
+
name: z.string().min(1, 'name is required'),
|
|
46
|
+
description: z.string().min(1, 'description is required').max(1024),
|
|
47
|
+
version: z.string().optional(),
|
|
48
|
+
license: z.string().optional(),
|
|
49
|
+
compatibility: z.string().max(500).optional(),
|
|
50
|
+
'allowed-tools': z.union([z.string(), z.array(z.string())]).optional(),
|
|
51
|
+
metadata: z.record(z.string(), z.string()).optional(),
|
|
52
|
+
});
|
|
53
|
+
/**
|
|
54
|
+
* Helper: Extract and validate YAML frontmatter
|
|
55
|
+
* @returns { frontmatter, body, error }
|
|
56
|
+
*/
|
|
57
|
+
function extractFrontmatter(content) {
|
|
58
|
+
if (!content?.startsWith('---')) {
|
|
59
|
+
return { error: 'Skill content must start with YAML frontmatter (---)' };
|
|
60
|
+
}
|
|
61
|
+
const endIndex = content.indexOf('---', 3);
|
|
62
|
+
if (endIndex === -1) {
|
|
63
|
+
return { error: 'Skill content must have closing YAML frontmatter (---)' };
|
|
64
|
+
}
|
|
65
|
+
const frontmatterBlock = content.substring(3, endIndex).trim();
|
|
66
|
+
const body = content.substring(endIndex + 3).trim();
|
|
67
|
+
let parsed;
|
|
68
|
+
try {
|
|
69
|
+
parsed = YAML.load(frontmatterBlock) || {};
|
|
70
|
+
}
|
|
71
|
+
catch (e) {
|
|
72
|
+
return { error: `Failed to parse YAML frontmatter: ${e.message}` };
|
|
73
|
+
}
|
|
74
|
+
// Normalize allowed-tools: convert space-delimited string to array
|
|
75
|
+
if (parsed['allowed-tools'] && typeof parsed['allowed-tools'] === 'string') {
|
|
76
|
+
parsed['allowed-tools'] = parsed['allowed-tools'].split(/\s+/);
|
|
77
|
+
}
|
|
78
|
+
// Validate with Zod
|
|
79
|
+
const validationResult = FrontmatterSchema.safeParse(parsed);
|
|
80
|
+
if (!validationResult.success) {
|
|
81
|
+
const errors = validationResult.error.issues
|
|
82
|
+
.map((e) => `${e.path.join('.')}: ${e.message}`)
|
|
83
|
+
.join('; ');
|
|
84
|
+
return { error: `Frontmatter validation failed: ${errors}` };
|
|
85
|
+
}
|
|
86
|
+
const frontmatter = {
|
|
87
|
+
name: validationResult.data.name,
|
|
88
|
+
description: validationResult.data.description,
|
|
89
|
+
version: validationResult.data.version,
|
|
90
|
+
license: validationResult.data.license,
|
|
91
|
+
compatibility: validationResult.data.compatibility,
|
|
92
|
+
'allowed-tools': validationResult.data['allowed-tools'],
|
|
93
|
+
metadata: validationResult.data.metadata,
|
|
94
|
+
};
|
|
95
|
+
return { frontmatter, body };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Parse YAML frontmatter from SKILL.md content
|
|
99
|
+
*/
|
|
100
|
+
export function parseSkillContent(content) {
|
|
101
|
+
const { frontmatter, body, error } = extractFrontmatter(content);
|
|
102
|
+
if (error) {
|
|
103
|
+
return {
|
|
104
|
+
error,
|
|
105
|
+
frontmatter: { name: '', description: '' },
|
|
106
|
+
body: content.substring(content.indexOf('---', 3) + 3).trim() || '',
|
|
107
|
+
raw: content,
|
|
108
|
+
};
|
|
109
|
+
}
|
|
110
|
+
// Parse body into structured sections for selective context loading
|
|
111
|
+
const parsedContent = parseSkillSections(body);
|
|
112
|
+
return {
|
|
113
|
+
frontmatter: frontmatter,
|
|
114
|
+
body: body,
|
|
115
|
+
raw: content,
|
|
116
|
+
sections: parsedContent.sections,
|
|
117
|
+
totalTokens: parsedContent.totalTokens,
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Extract ONLY metadata from SKILL.md without parsing body/sections.
|
|
122
|
+
*
|
|
123
|
+
* Optimized for matimo_list_skills — reads YAML frontmatter only.
|
|
124
|
+
* This avoids the overhead of parsing sections and body content.
|
|
125
|
+
*
|
|
126
|
+
* Returns SkillSummary: name, description, version, license, metadata, source.
|
|
127
|
+
*/
|
|
128
|
+
export function extractSkillMetadata(content, source = 'user') {
|
|
129
|
+
const { frontmatter, error } = extractFrontmatter(content);
|
|
130
|
+
if (error) {
|
|
131
|
+
return { success: false, error };
|
|
132
|
+
}
|
|
133
|
+
// Return only metadata fields (no body, sections, or body content)
|
|
134
|
+
return {
|
|
135
|
+
success: true,
|
|
136
|
+
metadata: {
|
|
137
|
+
name: frontmatter.name,
|
|
138
|
+
description: frontmatter.description,
|
|
139
|
+
version: frontmatter.version,
|
|
140
|
+
license: frontmatter.license,
|
|
141
|
+
metadata: frontmatter.metadata,
|
|
142
|
+
source,
|
|
143
|
+
},
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
// ─── Bundled Resources Discovery ───────────────────────────────────────────
|
|
147
|
+
function listBundledResources(skillDir) {
|
|
148
|
+
const resources = {
|
|
149
|
+
scripts: [],
|
|
150
|
+
references: [],
|
|
151
|
+
assets: [],
|
|
152
|
+
other: [],
|
|
153
|
+
};
|
|
154
|
+
if (!fs.existsSync(skillDir))
|
|
155
|
+
return resources;
|
|
156
|
+
const KNOWN_DIRS = {
|
|
157
|
+
scripts: 'scripts',
|
|
158
|
+
references: 'references',
|
|
159
|
+
assets: 'assets',
|
|
160
|
+
};
|
|
161
|
+
const entries = fs.readdirSync(skillDir, { withFileTypes: true });
|
|
162
|
+
for (const entry of entries) {
|
|
163
|
+
if (entry.name === 'SKILL.md')
|
|
164
|
+
continue;
|
|
165
|
+
if (entry.isDirectory()) {
|
|
166
|
+
const category = KNOWN_DIRS[entry.name];
|
|
167
|
+
if (category) {
|
|
168
|
+
const subDir = path.join(skillDir, entry.name);
|
|
169
|
+
const subEntries = fs.readdirSync(subDir);
|
|
170
|
+
for (const sub of subEntries) {
|
|
171
|
+
resources[category].push(`${entry.name}/${sub}`);
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
else {
|
|
175
|
+
const subDir = path.join(skillDir, entry.name);
|
|
176
|
+
const subEntries = fs.readdirSync(subDir);
|
|
177
|
+
for (const sub of subEntries) {
|
|
178
|
+
resources.other.push(`${entry.name}/${sub}`);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
else {
|
|
183
|
+
resources.other.push(entry.name);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return resources;
|
|
187
|
+
}
|
|
188
|
+
// ─── SkillLoader ──────────────────────────────────────────────────────────
|
|
189
|
+
/**
|
|
190
|
+
* SkillLoader reads and validates skills from directories
|
|
191
|
+
*/
|
|
192
|
+
export class SkillLoader {
|
|
193
|
+
constructor() {
|
|
194
|
+
this.logger = getGlobalMatimoLogger();
|
|
195
|
+
}
|
|
196
|
+
/**
|
|
197
|
+
* Load all skills from a directory
|
|
198
|
+
*/
|
|
199
|
+
loadSkillsFromDirectory(skillsDir, source = 'user') {
|
|
200
|
+
const skills = [];
|
|
201
|
+
if (!fs.existsSync(skillsDir)) {
|
|
202
|
+
return skills;
|
|
203
|
+
}
|
|
204
|
+
const entries = fs.readdirSync(skillsDir, { withFileTypes: true });
|
|
205
|
+
for (const entry of entries) {
|
|
206
|
+
if (!entry.isDirectory())
|
|
207
|
+
continue;
|
|
208
|
+
const skillPath = path.join(skillsDir, entry.name, 'SKILL.md');
|
|
209
|
+
if (!fs.existsSync(skillPath))
|
|
210
|
+
continue;
|
|
211
|
+
try {
|
|
212
|
+
this.logger.debug('SkillLoader: attempting to load skill', {
|
|
213
|
+
name: entry.name,
|
|
214
|
+
skillPath,
|
|
215
|
+
});
|
|
216
|
+
const skill = this.loadSkill(entry.name, skillsDir, source);
|
|
217
|
+
if (skill) {
|
|
218
|
+
skills.push(skill);
|
|
219
|
+
this.logger.debug('SkillLoader: successfully loaded skill', {
|
|
220
|
+
name: skill.name,
|
|
221
|
+
});
|
|
222
|
+
}
|
|
223
|
+
else {
|
|
224
|
+
this.logger.warn('SkillLoader: loadSkill returned null', {
|
|
225
|
+
name: entry.name,
|
|
226
|
+
});
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
catch (err) {
|
|
230
|
+
this.logger.error('SkillLoader: failed to load skill', {
|
|
231
|
+
dir: entry.name,
|
|
232
|
+
error: err.message,
|
|
233
|
+
stack: err.stack,
|
|
234
|
+
skillsDir,
|
|
235
|
+
});
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
return skills;
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Load a single skill by name
|
|
242
|
+
*/
|
|
243
|
+
loadSkill(name, skillsDir, source = 'user') {
|
|
244
|
+
// Validate name
|
|
245
|
+
const nameValidation = validateSkillName(name);
|
|
246
|
+
if (!nameValidation.valid) {
|
|
247
|
+
throw new MatimoError(`Invalid skill name: ${nameValidation.error}`, ErrorCode.INVALID_SCHEMA);
|
|
248
|
+
}
|
|
249
|
+
const skillDir = path.join(skillsDir, name);
|
|
250
|
+
const skillPath = path.join(skillDir, 'SKILL.md');
|
|
251
|
+
if (!fs.existsSync(skillPath)) {
|
|
252
|
+
throw new MatimoError(`Skill not found: ${skillPath}`, ErrorCode.TOOL_NOT_FOUND);
|
|
253
|
+
}
|
|
254
|
+
const content = fs.readFileSync(skillPath, 'utf-8');
|
|
255
|
+
const parsed = parseSkillContent(content);
|
|
256
|
+
if (parsed.error) {
|
|
257
|
+
throw new MatimoError(`Failed to parse skill: ${parsed.error}`, ErrorCode.INVALID_SCHEMA);
|
|
258
|
+
}
|
|
259
|
+
const { frontmatter } = parsed;
|
|
260
|
+
// Verify frontmatter name matches directory name
|
|
261
|
+
if (frontmatter.name !== name) {
|
|
262
|
+
throw new MatimoError(`Skill name "${frontmatter.name}" must match directory name "${name}"`, ErrorCode.INVALID_SCHEMA);
|
|
263
|
+
}
|
|
264
|
+
const resources = listBundledResources(skillDir);
|
|
265
|
+
const skill = {
|
|
266
|
+
name: frontmatter.name,
|
|
267
|
+
description: frontmatter.description,
|
|
268
|
+
version: frontmatter.version,
|
|
269
|
+
license: frontmatter.license,
|
|
270
|
+
compatibility: frontmatter.compatibility,
|
|
271
|
+
allowedTools: frontmatter['allowed-tools'],
|
|
272
|
+
metadata: frontmatter.metadata,
|
|
273
|
+
body: parsed.body,
|
|
274
|
+
sections: parsed.sections,
|
|
275
|
+
totalTokens: parsed.totalTokens,
|
|
276
|
+
resources,
|
|
277
|
+
source,
|
|
278
|
+
_path: skillDir,
|
|
279
|
+
};
|
|
280
|
+
return skill;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Load a skill resource file (scripts/, references/, assets/)
|
|
284
|
+
*/
|
|
285
|
+
loadSkillResource(skillName, skillsDir, resourcePath) {
|
|
286
|
+
// Validate resource path (prevent traversal)
|
|
287
|
+
if (/\.\.|\\/u.test(resourcePath) || /[\x00-\x1f]/.test(resourcePath)) {
|
|
288
|
+
throw new MatimoError('Resource path contains invalid characters', ErrorCode.INVALID_SCHEMA);
|
|
289
|
+
}
|
|
290
|
+
const skillDir = path.join(skillsDir, skillName);
|
|
291
|
+
const resourceFullPath = path.join(skillDir, resourcePath);
|
|
292
|
+
// Verify path stays within skill directory
|
|
293
|
+
const resolvedPath = path.resolve(resourceFullPath);
|
|
294
|
+
const resolvedSkillDir = path.resolve(skillDir);
|
|
295
|
+
if (!resolvedPath.startsWith(resolvedSkillDir + path.sep) &&
|
|
296
|
+
resolvedPath !== resolvedSkillDir) {
|
|
297
|
+
throw new MatimoError('Resource path escapes the skill directory', ErrorCode.INVALID_SCHEMA);
|
|
298
|
+
}
|
|
299
|
+
if (!fs.existsSync(resourceFullPath)) {
|
|
300
|
+
throw new MatimoError(`Resource file not found: ${resourcePath}`, ErrorCode.TOOL_NOT_FOUND);
|
|
301
|
+
}
|
|
302
|
+
try {
|
|
303
|
+
return fs.readFileSync(resourceFullPath, 'utf-8');
|
|
304
|
+
}
|
|
305
|
+
catch (err) {
|
|
306
|
+
throw new MatimoError(`Failed to read resource file: ${err.message}`, ErrorCode.EXECUTION_FAILED);
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
//# sourceMappingURL=skill-loader.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"skill-loader.js","sourceRoot":"","sources":["../../src/core/skill-loader.ts"],"names":[],"mappings":"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"}
|