@matimo/core 0.1.0 → 0.1.3
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/approval/approval-handler.js +1 -1
- package/dist/approval/approval-handler.js.map +1 -1
- package/dist/auth/oauth2-handler.d.ts +2 -2
- package/dist/auth/oauth2-handler.d.ts.map +1 -1
- package/dist/auth/oauth2-handler.js +2 -2
- package/dist/auth/oauth2-handler.js.map +1 -1
- package/dist/auth/oauth2-provider-loader.d.ts +2 -2
- package/dist/auth/oauth2-provider-loader.d.ts.map +1 -1
- package/dist/auth/oauth2-provider-loader.js +2 -2
- package/dist/auth/oauth2-provider-loader.js.map +1 -1
- package/dist/core/schema.d.ts +1 -1
- package/dist/core/schema.js +2 -2
- package/dist/core/schema.js.map +1 -1
- package/dist/core/skill-loader.d.ts +1 -1
- package/dist/core/skill-loader.d.ts.map +1 -1
- package/dist/core/skill-loader.js +4 -3
- package/dist/core/skill-loader.js.map +1 -1
- package/dist/core/skill-registry.d.ts +1 -1
- package/dist/core/skill-registry.d.ts.map +1 -1
- package/dist/core/skill-registry.js +4 -4
- package/dist/core/skill-registry.js.map +1 -1
- package/dist/core/tfidf-embedding.d.ts +1 -1
- package/dist/core/tfidf-embedding.d.ts.map +1 -1
- package/dist/core/tool-loader.d.ts +1 -1
- package/dist/core/tool-loader.d.ts.map +1 -1
- package/dist/core/tool-loader.js +2 -2
- package/dist/core/tool-loader.js.map +1 -1
- package/dist/core/tool-registry.d.ts +1 -1
- package/dist/core/tool-registry.d.ts.map +1 -1
- package/dist/core/tool-registry.js +1 -1
- package/dist/core/tool-registry.js.map +1 -1
- package/dist/core/types.d.ts +1 -1
- package/dist/core/types.d.ts.map +1 -1
- package/dist/decorators/index.d.ts +1 -1
- package/dist/decorators/index.d.ts.map +1 -1
- package/dist/decorators/index.js +1 -1
- package/dist/decorators/index.js.map +1 -1
- package/dist/decorators/tool-decorator.js +1 -1
- package/dist/decorators/tool-decorator.js.map +1 -1
- package/dist/encodings/parameter-encoding.js +1 -1
- package/dist/encodings/parameter-encoding.js.map +1 -1
- package/dist/executors/command-executor.d.ts +1 -1
- package/dist/executors/command-executor.d.ts.map +1 -1
- package/dist/executors/command-executor.js +1 -1
- package/dist/executors/command-executor.js.map +1 -1
- package/dist/executors/function-executor.d.ts +1 -1
- package/dist/executors/function-executor.d.ts.map +1 -1
- package/dist/executors/function-executor.js +2 -2
- package/dist/executors/function-executor.js.map +1 -1
- package/dist/executors/http-executor.d.ts +1 -1
- package/dist/executors/http-executor.d.ts.map +1 -1
- package/dist/executors/http-executor.js +2 -2
- package/dist/executors/http-executor.js.map +1 -1
- package/dist/index.d.ts +45 -45
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +31 -31
- package/dist/index.js.map +1 -1
- package/dist/integrations/langchain.d.ts +2 -2
- package/dist/integrations/langchain.d.ts.map +1 -1
- package/dist/matimo-instance.d.ts +9 -9
- package/dist/matimo-instance.d.ts.map +1 -1
- package/dist/matimo-instance.js +14 -14
- package/dist/matimo-instance.js.map +1 -1
- package/dist/mcp/index.d.ts +4 -4
- package/dist/mcp/index.d.ts.map +1 -1
- package/dist/mcp/index.js +3 -3
- package/dist/mcp/index.js.map +1 -1
- package/dist/mcp/mcp-server.d.ts +2 -2
- package/dist/mcp/mcp-server.d.ts.map +1 -1
- package/dist/mcp/mcp-server.js +6 -6
- package/dist/mcp/mcp-server.js.map +1 -1
- package/dist/mcp/secrets/aws-resolver.d.ts +1 -1
- package/dist/mcp/secrets/aws-resolver.d.ts.map +1 -1
- package/dist/mcp/secrets/aws-resolver.js +2 -2
- package/dist/mcp/secrets/aws-resolver.js.map +1 -1
- package/dist/mcp/secrets/dotenv-resolver.d.ts +1 -1
- package/dist/mcp/secrets/dotenv-resolver.d.ts.map +1 -1
- package/dist/mcp/secrets/dotenv-resolver.js +1 -1
- package/dist/mcp/secrets/dotenv-resolver.js.map +1 -1
- package/dist/mcp/secrets/env-resolver.d.ts +1 -1
- package/dist/mcp/secrets/env-resolver.d.ts.map +1 -1
- package/dist/mcp/secrets/index.d.ts +8 -8
- package/dist/mcp/secrets/index.d.ts.map +1 -1
- package/dist/mcp/secrets/index.js +5 -5
- package/dist/mcp/secrets/index.js.map +1 -1
- package/dist/mcp/secrets/resolver-chain.d.ts +1 -1
- package/dist/mcp/secrets/resolver-chain.d.ts.map +1 -1
- package/dist/mcp/secrets/resolver-chain.js +5 -5
- package/dist/mcp/secrets/resolver-chain.js.map +1 -1
- package/dist/mcp/secrets/vault-resolver.d.ts +1 -1
- package/dist/mcp/secrets/vault-resolver.d.ts.map +1 -1
- package/dist/mcp/secrets/vault-resolver.js +2 -2
- package/dist/mcp/secrets/vault-resolver.js.map +1 -1
- package/dist/mcp/tool-converter.d.ts +2 -2
- package/dist/mcp/tool-converter.d.ts.map +1 -1
- package/dist/policy/approval-manifest.js +2 -2
- package/dist/policy/approval-manifest.js.map +1 -1
- package/dist/policy/content-validator.d.ts +2 -2
- package/dist/policy/content-validator.d.ts.map +1 -1
- package/dist/policy/content-validator.js +1 -1
- package/dist/policy/content-validator.js.map +1 -1
- package/dist/policy/default-policy.d.ts +2 -2
- package/dist/policy/default-policy.d.ts.map +1 -1
- package/dist/policy/default-policy.js +3 -3
- package/dist/policy/default-policy.js.map +1 -1
- package/dist/policy/events.d.ts +2 -2
- package/dist/policy/events.d.ts.map +1 -1
- package/dist/policy/index.d.ts +9 -9
- package/dist/policy/index.d.ts.map +1 -1
- package/dist/policy/index.js +5 -5
- package/dist/policy/index.js.map +1 -1
- package/dist/policy/policy-loader.d.ts +1 -1
- package/dist/policy/policy-loader.d.ts.map +1 -1
- package/dist/policy/policy-loader.js +2 -2
- package/dist/policy/policy-loader.js.map +1 -1
- package/dist/policy/risk-classifier.d.ts +2 -2
- package/dist/policy/risk-classifier.d.ts.map +1 -1
- package/dist/policy/types.d.ts +1 -1
- package/dist/policy/types.d.ts.map +1 -1
- package/dist/runtime/index.d.ts +10 -0
- package/dist/runtime/index.d.ts.map +1 -0
- package/dist/runtime/index.js +10 -0
- package/dist/runtime/index.js.map +1 -0
- package/package.json +5 -1
- package/tools/calculator/calculator.ts +1 -2
- package/tools/execute/execute.ts +6 -3
- package/tools/matimo_create_skill/matimo_create_skill.ts +1 -1
- package/tools/matimo_get_skill/matimo_get_skill.ts +8 -1
- package/tools/matimo_validate_skill/matimo_validate_skill.ts +14 -3
- package/tools/search/search.ts +14 -4
- package/tools/shared/skill-validation.js +240 -0
- package/tools/web/web.ts +2 -2
|
@@ -0,0 +1,240 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Shared validation utilities for Agent Skills — aligned with the official
|
|
3
|
+
* Agent Skills specification (https://agentskills.io/specification).
|
|
4
|
+
*
|
|
5
|
+
* Covers: name rules, description rules, frontmatter parsing/validation,
|
|
6
|
+
* and bundled resource discovery.
|
|
7
|
+
*/
|
|
8
|
+
import fs from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
11
|
+
// Name validation
|
|
12
|
+
const VALID_NAME_PATTERN = /^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/;
|
|
13
|
+
const CONSECUTIVE_HYPHENS = /--/;
|
|
14
|
+
const MAX_NAME_LENGTH = 64;
|
|
15
|
+
const MAX_DESCRIPTION_LENGTH = 1024;
|
|
16
|
+
const MAX_COMPATIBILITY_LENGTH = 500;
|
|
17
|
+
const UNSAFE_NAME_PATTERN = /[/\\]|\.\.|[\x00-\x1f]/;
|
|
18
|
+
|
|
19
|
+
export function validateSkillName(name) {
|
|
20
|
+
if (!name || name.trim().length === 0) {
|
|
21
|
+
return { valid: false, error: 'Skill name is required' };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (UNSAFE_NAME_PATTERN.test(name)) {
|
|
25
|
+
return { valid: false, error: 'Skill name contains invalid characters' };
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (name.length > MAX_NAME_LENGTH) {
|
|
29
|
+
return {
|
|
30
|
+
valid: false,
|
|
31
|
+
error: `Skill name must be at most ${MAX_NAME_LENGTH} characters (got ${name.length})`,
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
if (!VALID_NAME_PATTERN.test(name)) {
|
|
36
|
+
return {
|
|
37
|
+
valid: false,
|
|
38
|
+
error:
|
|
39
|
+
'Skill name must contain only lowercase letters, numbers, and hyphens, and must not start or end with a hyphen',
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (CONSECUTIVE_HYPHENS.test(name)) {
|
|
44
|
+
return { valid: false, error: 'Skill name must not contain consecutive hyphens (--)' };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return { valid: true };
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export function parseSkillContent(content) {
|
|
51
|
+
if (!content || !content.startsWith('---')) {
|
|
52
|
+
return { success: false, error: 'Skill content must start with YAML frontmatter (---)' };
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
const endIndex = content.indexOf('---', 3);
|
|
56
|
+
if (endIndex === -1) {
|
|
57
|
+
return { success: false, error: 'Skill content must have closing YAML frontmatter (---)' };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
const frontmatterBlock = content.substring(3, endIndex).trim();
|
|
61
|
+
const body = content.substring(endIndex + 3).trim();
|
|
62
|
+
|
|
63
|
+
const fields = {};
|
|
64
|
+
let currentMetadata = null;
|
|
65
|
+
let currentArray = null;
|
|
66
|
+
let currentArrayKey = null;
|
|
67
|
+
|
|
68
|
+
for (const line of frontmatterBlock.split('\n')) {
|
|
69
|
+
if (currentArray !== null && /^\s*- /.test(line)) {
|
|
70
|
+
const item = line.trim().substring(2).trim();
|
|
71
|
+
if (item) {
|
|
72
|
+
currentArray.push(item.replace(/^["']|["']$/g, ''));
|
|
73
|
+
}
|
|
74
|
+
continue;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
if (currentMetadata !== null && /^\s+\S/.test(line)) {
|
|
78
|
+
const colonIndex = line.indexOf(':');
|
|
79
|
+
if (colonIndex !== -1) {
|
|
80
|
+
const key = line.substring(0, colonIndex).trim();
|
|
81
|
+
const value = line.substring(colonIndex + 1).trim();
|
|
82
|
+
if (key && value) {
|
|
83
|
+
currentMetadata[key] = value.replace(/^["']|["']$/g, '');
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
continue;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (currentArray !== null && currentArrayKey) {
|
|
90
|
+
fields[currentArrayKey] = currentArray;
|
|
91
|
+
}
|
|
92
|
+
if (currentMetadata !== null) {
|
|
93
|
+
fields.metadata = currentMetadata;
|
|
94
|
+
}
|
|
95
|
+
currentMetadata = null;
|
|
96
|
+
currentArray = null;
|
|
97
|
+
currentArrayKey = null;
|
|
98
|
+
const colonIndex = line.indexOf(':');
|
|
99
|
+
if (colonIndex === -1) continue;
|
|
100
|
+
|
|
101
|
+
const key = line.substring(0, colonIndex).trim();
|
|
102
|
+
const value = line.substring(colonIndex + 1).trim();
|
|
103
|
+
|
|
104
|
+
if (key === 'metadata' && !value) {
|
|
105
|
+
currentMetadata = {};
|
|
106
|
+
fields.metadata = currentMetadata;
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
if (key === 'allowed-tools' && !value) {
|
|
111
|
+
currentArray = [];
|
|
112
|
+
currentArrayKey = 'allowed-tools';
|
|
113
|
+
continue;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
if (key && value) {
|
|
117
|
+
fields[key] = value.replace(/^["']|["']$/g, '');
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
if (currentArray !== null && currentArrayKey) {
|
|
122
|
+
fields[currentArrayKey] = currentArray;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const frontmatter = {
|
|
126
|
+
name: fields.name || '',
|
|
127
|
+
description: fields.description || '',
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
if (fields.license) frontmatter.license = fields.license;
|
|
131
|
+
if (fields.compatibility) frontmatter.compatibility = fields.compatibility;
|
|
132
|
+
if (fields['allowed-tools']) {
|
|
133
|
+
frontmatter['allowed-tools'] = Array.isArray(fields['allowed-tools'])
|
|
134
|
+
? fields['allowed-tools']
|
|
135
|
+
: fields['allowed-tools'];
|
|
136
|
+
}
|
|
137
|
+
if (currentMetadata && Object.keys(currentMetadata).length > 0) {
|
|
138
|
+
frontmatter.metadata = currentMetadata;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return {
|
|
142
|
+
success: true,
|
|
143
|
+
parsed: { frontmatter, body, raw: content },
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export function validateFrontmatter(frontmatter, directoryName) {
|
|
148
|
+
const issues = [];
|
|
149
|
+
|
|
150
|
+
if (!frontmatter.name) {
|
|
151
|
+
issues.push({
|
|
152
|
+
field: 'name',
|
|
153
|
+
message: 'YAML frontmatter must include a "name" field',
|
|
154
|
+
severity: 'error',
|
|
155
|
+
});
|
|
156
|
+
} else {
|
|
157
|
+
const nameResult = validateSkillName(frontmatter.name);
|
|
158
|
+
if (!nameResult.valid) {
|
|
159
|
+
issues.push({ field: 'name', message: nameResult.error, severity: 'error' });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
if (!frontmatter.description) {
|
|
164
|
+
issues.push({
|
|
165
|
+
field: 'description',
|
|
166
|
+
message: 'YAML frontmatter must include a "description" field',
|
|
167
|
+
severity: 'error',
|
|
168
|
+
});
|
|
169
|
+
} else if (frontmatter.description.length > MAX_DESCRIPTION_LENGTH) {
|
|
170
|
+
issues.push({
|
|
171
|
+
field: 'description',
|
|
172
|
+
message: `Description must be at most ${MAX_DESCRIPTION_LENGTH} characters (got ${frontmatter.description.length})`,
|
|
173
|
+
severity: 'error',
|
|
174
|
+
});
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
if (frontmatter.compatibility && frontmatter.compatibility.length > MAX_COMPATIBILITY_LENGTH) {
|
|
178
|
+
issues.push({
|
|
179
|
+
field: 'compatibility',
|
|
180
|
+
message: `Compatibility must be at most ${MAX_COMPATIBILITY_LENGTH} characters (got ${frontmatter.compatibility.length})`,
|
|
181
|
+
severity: 'error',
|
|
182
|
+
});
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
if (directoryName && frontmatter.name && frontmatter.name !== directoryName) {
|
|
186
|
+
issues.push({
|
|
187
|
+
field: 'name',
|
|
188
|
+
message: `Skill name "${frontmatter.name}" must match its directory name "${directoryName}"`,
|
|
189
|
+
severity: 'error',
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return {
|
|
194
|
+
valid: issues.filter((i) => i.severity === 'error').length === 0,
|
|
195
|
+
issues,
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
export function listBundledResources(skillDir) {
|
|
200
|
+
const resources = {
|
|
201
|
+
scripts: [],
|
|
202
|
+
references: [],
|
|
203
|
+
assets: [],
|
|
204
|
+
other: [],
|
|
205
|
+
};
|
|
206
|
+
|
|
207
|
+
if (!fs.existsSync(skillDir)) return resources;
|
|
208
|
+
|
|
209
|
+
const KNOWN_DIRS = {
|
|
210
|
+
scripts: 'scripts',
|
|
211
|
+
references: 'references',
|
|
212
|
+
assets: 'assets',
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
const entries = fs.readdirSync(skillDir, { withFileTypes: true });
|
|
216
|
+
for (const entry of entries) {
|
|
217
|
+
if (entry.name === 'SKILL.md') continue;
|
|
218
|
+
|
|
219
|
+
if (entry.isDirectory()) {
|
|
220
|
+
const category = KNOWN_DIRS[entry.name];
|
|
221
|
+
if (category) {
|
|
222
|
+
const subDir = path.join(skillDir, entry.name);
|
|
223
|
+
const subEntries = fs.readdirSync(subDir);
|
|
224
|
+
for (const sub of subEntries) {
|
|
225
|
+
resources[category].push(`${entry.name}/${sub}`);
|
|
226
|
+
}
|
|
227
|
+
} else {
|
|
228
|
+
const subDir = path.join(skillDir, entry.name);
|
|
229
|
+
const subEntries = fs.readdirSync(subDir);
|
|
230
|
+
for (const sub of subEntries) {
|
|
231
|
+
resources.other.push(`${entry.name}/${sub}`);
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
} else {
|
|
235
|
+
resources.other.push(entry.name);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
return resources;
|
|
240
|
+
}
|
package/tools/web/web.ts
CHANGED
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
7
|
import axios, { AxiosRequestConfig, AxiosError } from 'axios';
|
|
8
|
-
import { MatimoError, ErrorCode } from '
|
|
8
|
+
import { MatimoError, ErrorCode } from '@matimo/core/runtime';
|
|
9
9
|
|
|
10
10
|
interface WebParams {
|
|
11
11
|
url: string;
|
|
@@ -74,7 +74,7 @@ export default async function webTool(params: WebParams): Promise<WebResult> {
|
|
|
74
74
|
headers: {
|
|
75
75
|
'User-Agent': 'Matimo/1.0 (AI Agent Tool SDK)',
|
|
76
76
|
Accept: 'application/json, text/plain, text/html, */*',
|
|
77
|
-
...headers,
|
|
77
|
+
...(headers || {}),
|
|
78
78
|
},
|
|
79
79
|
validateStatus: () => true, // Don't throw on any status code
|
|
80
80
|
};
|