sis-tools 0.1.0
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 +1531 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +869 -0
- package/dist/index.d.ts +869 -0
- package/dist/index.js +1476 -0
- package/dist/index.js.map +1 -0
- package/package.json +86 -0
- package/src/embeddings/base.ts +47 -0
- package/src/embeddings/cohere.ts +79 -0
- package/src/embeddings/google.ts +67 -0
- package/src/embeddings/index.ts +43 -0
- package/src/embeddings/openai.ts +87 -0
- package/src/formatters.ts +249 -0
- package/src/hooks.ts +341 -0
- package/src/index.ts +104 -0
- package/src/optional-peer-deps.d.ts +17 -0
- package/src/scoring.ts +198 -0
- package/src/sis.ts +572 -0
- package/src/store.ts +134 -0
- package/src/types.ts +136 -0
- package/src/validators.ts +484 -0
package/src/types.ts
ADDED
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type definitions for SIS
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
export interface ToolParameter {
|
|
6
|
+
type: string;
|
|
7
|
+
description?: string;
|
|
8
|
+
required?: boolean;
|
|
9
|
+
default?: unknown;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
export interface ToolParameters {
|
|
13
|
+
[key: string]: ToolParameter;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export interface ToolExample {
|
|
17
|
+
query: string;
|
|
18
|
+
input?: Record<string, unknown>;
|
|
19
|
+
output?: unknown;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export interface ToolMetadata {
|
|
23
|
+
version?: string;
|
|
24
|
+
author?: string;
|
|
25
|
+
tags?: string[];
|
|
26
|
+
priority?: number;
|
|
27
|
+
[key: string]: unknown;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface Tool {
|
|
31
|
+
name: string;
|
|
32
|
+
description: string;
|
|
33
|
+
parameters: ToolParameters;
|
|
34
|
+
returns?: Record<string, unknown>;
|
|
35
|
+
semanticHints: string[];
|
|
36
|
+
examples: ToolExample[];
|
|
37
|
+
handler?: ToolHandler;
|
|
38
|
+
metadata: ToolMetadata;
|
|
39
|
+
embedding?: number[];
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export type ToolHandler = (
|
|
43
|
+
params: Record<string, unknown>
|
|
44
|
+
) => unknown | Promise<unknown>;
|
|
45
|
+
|
|
46
|
+
export interface ToolMatch {
|
|
47
|
+
tool: Tool;
|
|
48
|
+
score: number;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export interface ResolvedTool {
|
|
52
|
+
name: string;
|
|
53
|
+
schema: ToolSchema;
|
|
54
|
+
score: number;
|
|
55
|
+
handler?: ToolHandler;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
export interface ToolSchema {
|
|
59
|
+
name: string;
|
|
60
|
+
description: string;
|
|
61
|
+
parameters: {
|
|
62
|
+
type: "object";
|
|
63
|
+
properties: Record<string, unknown>;
|
|
64
|
+
required: string[];
|
|
65
|
+
};
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export interface OpenAIToolSchema {
|
|
69
|
+
type: "function";
|
|
70
|
+
function: ToolSchema;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
export interface AnthropicToolSchema {
|
|
74
|
+
name: string;
|
|
75
|
+
description: string;
|
|
76
|
+
input_schema: {
|
|
77
|
+
type: "object";
|
|
78
|
+
properties: Record<string, unknown>;
|
|
79
|
+
required: string[];
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Convert a Tool to its JSON schema representation
|
|
85
|
+
*/
|
|
86
|
+
export function toSchema(tool: Tool): ToolSchema {
|
|
87
|
+
const required = Object.entries(tool.parameters)
|
|
88
|
+
.filter(([, v]) => v.required !== false)
|
|
89
|
+
.map(([k]) => k);
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
name: tool.name,
|
|
93
|
+
description: tool.description,
|
|
94
|
+
parameters: {
|
|
95
|
+
type: "object",
|
|
96
|
+
properties: tool.parameters,
|
|
97
|
+
required,
|
|
98
|
+
},
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Convert a Tool to OpenAI function calling format
|
|
104
|
+
*/
|
|
105
|
+
export function toOpenAISchema(tool: Tool): OpenAIToolSchema {
|
|
106
|
+
return {
|
|
107
|
+
type: "function",
|
|
108
|
+
function: toSchema(tool),
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* Convert a Tool to Anthropic tool use format
|
|
114
|
+
*/
|
|
115
|
+
export function toAnthropicSchema(tool: Tool): AnthropicToolSchema {
|
|
116
|
+
const schema = toSchema(tool);
|
|
117
|
+
return {
|
|
118
|
+
name: schema.name,
|
|
119
|
+
description: schema.description,
|
|
120
|
+
input_schema: schema.parameters,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
export interface RemoteToolSchema {
|
|
125
|
+
name: string;
|
|
126
|
+
schema: ToolSchema;
|
|
127
|
+
score: number;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
export interface RemoteResolveResponse {
|
|
131
|
+
results: RemoteToolSchema[];
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export interface RemoteListResponse {
|
|
135
|
+
tools: string[];
|
|
136
|
+
}
|
|
@@ -0,0 +1,484 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation system for SIS tools and parameters
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
import type { Tool, ToolParameters } from "./types";
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Result of a validation operation
|
|
9
|
+
*/
|
|
10
|
+
export interface ValidationResult {
|
|
11
|
+
valid: boolean;
|
|
12
|
+
errors: string[];
|
|
13
|
+
warnings: string[];
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Create a validation result
|
|
18
|
+
*/
|
|
19
|
+
export function createValidationResult(
|
|
20
|
+
valid: boolean,
|
|
21
|
+
errors: string[] = [],
|
|
22
|
+
warnings: string[] = []
|
|
23
|
+
): ValidationResult {
|
|
24
|
+
return { valid, errors, warnings };
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Merge two validation results
|
|
29
|
+
*/
|
|
30
|
+
export function mergeValidationResults(
|
|
31
|
+
a: ValidationResult,
|
|
32
|
+
b: ValidationResult
|
|
33
|
+
): ValidationResult {
|
|
34
|
+
return {
|
|
35
|
+
valid: a.valid && b.valid,
|
|
36
|
+
errors: [...a.errors, ...b.errors],
|
|
37
|
+
warnings: [...a.warnings, ...b.warnings],
|
|
38
|
+
};
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Interface for validators
|
|
43
|
+
*/
|
|
44
|
+
export interface Validator<T = unknown> {
|
|
45
|
+
validate(data: T): ValidationResult;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Validation error
|
|
50
|
+
*/
|
|
51
|
+
export class ValidationError extends Error {
|
|
52
|
+
result: ValidationResult;
|
|
53
|
+
|
|
54
|
+
constructor(result: ValidationResult) {
|
|
55
|
+
super(`Validation failed: ${result.errors.join(", ")}`);
|
|
56
|
+
this.name = "ValidationError";
|
|
57
|
+
this.result = result;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* Allowed JSON Schema types
|
|
63
|
+
*/
|
|
64
|
+
const ALLOWED_TYPES = new Set([
|
|
65
|
+
"string",
|
|
66
|
+
"integer",
|
|
67
|
+
"number",
|
|
68
|
+
"boolean",
|
|
69
|
+
"array",
|
|
70
|
+
"object",
|
|
71
|
+
"null",
|
|
72
|
+
]);
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Options for ToolSchemaValidator
|
|
76
|
+
*/
|
|
77
|
+
export interface ToolSchemaValidatorOptions {
|
|
78
|
+
requireDescription?: boolean;
|
|
79
|
+
requireParameters?: boolean;
|
|
80
|
+
minDescriptionLength?: number;
|
|
81
|
+
maxDescriptionLength?: number;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Validates tool definitions
|
|
86
|
+
*/
|
|
87
|
+
export class ToolSchemaValidator implements Validator<Tool> {
|
|
88
|
+
private options: Required<ToolSchemaValidatorOptions>;
|
|
89
|
+
|
|
90
|
+
constructor(options: ToolSchemaValidatorOptions = {}) {
|
|
91
|
+
this.options = {
|
|
92
|
+
requireDescription: options.requireDescription ?? true,
|
|
93
|
+
requireParameters: options.requireParameters ?? false,
|
|
94
|
+
minDescriptionLength: options.minDescriptionLength ?? 0,
|
|
95
|
+
maxDescriptionLength: options.maxDescriptionLength ?? 1000,
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
validate(tool: Tool): ValidationResult {
|
|
100
|
+
const errors: string[] = [];
|
|
101
|
+
const warnings: string[] = [];
|
|
102
|
+
|
|
103
|
+
// Validate name
|
|
104
|
+
if (!tool.name) {
|
|
105
|
+
errors.push("Tool name is required");
|
|
106
|
+
} else if (!/^[\w-]+$/.test(tool.name)) {
|
|
107
|
+
warnings.push(`Tool name '${tool.name}' contains special characters`);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
// Validate description
|
|
111
|
+
if (this.options.requireDescription && !tool.description) {
|
|
112
|
+
errors.push("Tool description is required");
|
|
113
|
+
} else if (tool.description) {
|
|
114
|
+
if (tool.description.length < this.options.minDescriptionLength) {
|
|
115
|
+
errors.push(
|
|
116
|
+
`Description must be at least ${this.options.minDescriptionLength} characters`
|
|
117
|
+
);
|
|
118
|
+
}
|
|
119
|
+
if (tool.description.length > this.options.maxDescriptionLength) {
|
|
120
|
+
errors.push(
|
|
121
|
+
`Description must be at most ${this.options.maxDescriptionLength} characters`
|
|
122
|
+
);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
// Validate parameters
|
|
127
|
+
if (this.options.requireParameters && Object.keys(tool.parameters).length === 0) {
|
|
128
|
+
errors.push("Tool parameters are required");
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Validate parameter types
|
|
132
|
+
for (const [name, param] of Object.entries(tool.parameters)) {
|
|
133
|
+
if (param.type && !ALLOWED_TYPES.has(param.type)) {
|
|
134
|
+
errors.push(`Parameter '${name}' has invalid type '${param.type}'`);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return createValidationResult(errors.length === 0, errors, warnings);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* Options for ParameterValidator
|
|
144
|
+
*/
|
|
145
|
+
export interface ParameterValidatorOptions {
|
|
146
|
+
strict?: boolean;
|
|
147
|
+
allowExtra?: boolean;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* Validates execution parameters against tool schema
|
|
152
|
+
*/
|
|
153
|
+
export class ParameterValidator implements Validator<{ tool: Tool; params: Record<string, unknown> }> {
|
|
154
|
+
private options: Required<ParameterValidatorOptions>;
|
|
155
|
+
|
|
156
|
+
constructor(options: ParameterValidatorOptions = {}) {
|
|
157
|
+
this.options = {
|
|
158
|
+
strict: options.strict ?? false,
|
|
159
|
+
allowExtra: options.allowExtra ?? true,
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
validate(data: { tool: Tool; params: Record<string, unknown> }): ValidationResult {
|
|
164
|
+
const { tool, params } = data;
|
|
165
|
+
const errors: string[] = [];
|
|
166
|
+
const warnings: string[] = [];
|
|
167
|
+
|
|
168
|
+
if (!tool) {
|
|
169
|
+
errors.push("Tool is required for parameter validation");
|
|
170
|
+
return createValidationResult(false, errors, warnings);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
const properties = tool.parameters;
|
|
174
|
+
|
|
175
|
+
// Check required parameters in strict mode
|
|
176
|
+
if (this.options.strict) {
|
|
177
|
+
for (const [name, param] of Object.entries(properties)) {
|
|
178
|
+
if (param.required !== false && !(name in params)) {
|
|
179
|
+
errors.push(`Missing required parameter: ${name}`);
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Check parameter types
|
|
185
|
+
for (const [name, value] of Object.entries(params)) {
|
|
186
|
+
if (!(name in properties)) {
|
|
187
|
+
if (!this.options.allowExtra) {
|
|
188
|
+
errors.push(`Unknown parameter: ${name}`);
|
|
189
|
+
} else {
|
|
190
|
+
warnings.push(`Extra parameter provided: ${name}`);
|
|
191
|
+
}
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
const param = properties[name];
|
|
196
|
+
const typeError = this.checkType(name, value, param.type);
|
|
197
|
+
if (typeError) {
|
|
198
|
+
errors.push(typeError);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
return createValidationResult(errors.length === 0, errors, warnings);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
private checkType(name: string, value: unknown, expectedType?: string): string | null {
|
|
206
|
+
if (!expectedType) return null;
|
|
207
|
+
|
|
208
|
+
const typeMap: Record<string, (v: unknown) => boolean> = {
|
|
209
|
+
string: (v) => typeof v === "string",
|
|
210
|
+
integer: (v) => Number.isInteger(v),
|
|
211
|
+
number: (v) => typeof v === "number",
|
|
212
|
+
boolean: (v) => typeof v === "boolean",
|
|
213
|
+
array: (v) => Array.isArray(v),
|
|
214
|
+
object: (v) => typeof v === "object" && v !== null && !Array.isArray(v),
|
|
215
|
+
null: (v) => v === null,
|
|
216
|
+
};
|
|
217
|
+
|
|
218
|
+
const checker = typeMap[expectedType];
|
|
219
|
+
if (checker && !checker(value)) {
|
|
220
|
+
return `Parameter '${name}' expected ${expectedType}, got ${typeof value}`;
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Options for ResultValidator
|
|
229
|
+
*/
|
|
230
|
+
export interface ResultValidatorOptions {
|
|
231
|
+
strict?: boolean;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
/**
|
|
235
|
+
* Validates tool execution results
|
|
236
|
+
*/
|
|
237
|
+
export class ResultValidator implements Validator<{ tool: Tool; result: unknown }> {
|
|
238
|
+
private options: Required<ResultValidatorOptions>;
|
|
239
|
+
|
|
240
|
+
constructor(options: ResultValidatorOptions = {}) {
|
|
241
|
+
this.options = {
|
|
242
|
+
strict: options.strict ?? false,
|
|
243
|
+
};
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
validate(data: { tool: Tool; result: unknown }): ValidationResult {
|
|
247
|
+
const { tool, result } = data;
|
|
248
|
+
const errors: string[] = [];
|
|
249
|
+
const warnings: string[] = [];
|
|
250
|
+
|
|
251
|
+
if (!tool) {
|
|
252
|
+
errors.push("Tool is required for result validation");
|
|
253
|
+
return createValidationResult(false, errors, warnings);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// If tool has return schema, validate against it
|
|
257
|
+
if (tool.returns) {
|
|
258
|
+
const expectedType = tool.returns.type as string;
|
|
259
|
+
const typeError = this.checkReturnType(result, expectedType);
|
|
260
|
+
if (typeError) {
|
|
261
|
+
if (this.options.strict) {
|
|
262
|
+
errors.push(typeError);
|
|
263
|
+
} else {
|
|
264
|
+
warnings.push(typeError);
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
return createValidationResult(errors.length === 0, errors, warnings);
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
private checkReturnType(value: unknown, expectedType?: string): string | null {
|
|
273
|
+
if (!expectedType) return null;
|
|
274
|
+
|
|
275
|
+
const typeMap: Record<string, (v: unknown) => boolean> = {
|
|
276
|
+
string: (v) => typeof v === "string",
|
|
277
|
+
integer: (v) => Number.isInteger(v),
|
|
278
|
+
number: (v) => typeof v === "number",
|
|
279
|
+
boolean: (v) => typeof v === "boolean",
|
|
280
|
+
array: (v) => Array.isArray(v),
|
|
281
|
+
object: (v) => typeof v === "object" && v !== null && !Array.isArray(v),
|
|
282
|
+
null: (v) => v === null,
|
|
283
|
+
};
|
|
284
|
+
|
|
285
|
+
const checker = typeMap[expectedType];
|
|
286
|
+
if (checker && !checker(value)) {
|
|
287
|
+
return `Result expected ${expectedType}, got ${typeof value}`;
|
|
288
|
+
}
|
|
289
|
+
|
|
290
|
+
return null;
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
/**
|
|
295
|
+
* Options for EmbeddingValidator
|
|
296
|
+
*/
|
|
297
|
+
export interface EmbeddingValidatorOptions {
|
|
298
|
+
expectedDimensions?: number;
|
|
299
|
+
checkNormalization?: boolean;
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
/**
|
|
303
|
+
* Validates embedding vectors
|
|
304
|
+
*/
|
|
305
|
+
export class EmbeddingValidator implements Validator<number[]> {
|
|
306
|
+
private options: EmbeddingValidatorOptions;
|
|
307
|
+
|
|
308
|
+
constructor(options: EmbeddingValidatorOptions = {}) {
|
|
309
|
+
this.options = options;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
validate(embedding: number[]): ValidationResult {
|
|
313
|
+
const errors: string[] = [];
|
|
314
|
+
const warnings: string[] = [];
|
|
315
|
+
|
|
316
|
+
if (!Array.isArray(embedding)) {
|
|
317
|
+
errors.push("Embedding must be an array");
|
|
318
|
+
return createValidationResult(false, errors, warnings);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
if (embedding.length === 0) {
|
|
322
|
+
errors.push("Embedding cannot be empty");
|
|
323
|
+
return createValidationResult(false, errors, warnings);
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
// Check dimensions
|
|
327
|
+
if (
|
|
328
|
+
this.options.expectedDimensions !== undefined &&
|
|
329
|
+
embedding.length !== this.options.expectedDimensions
|
|
330
|
+
) {
|
|
331
|
+
errors.push(
|
|
332
|
+
`Embedding dimensions mismatch: expected ${this.options.expectedDimensions}, got ${embedding.length}`
|
|
333
|
+
);
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
// Check for non-numeric values
|
|
337
|
+
for (let i = 0; i < embedding.length; i++) {
|
|
338
|
+
if (typeof embedding[i] !== "number") {
|
|
339
|
+
errors.push(`Embedding value at index ${i} is not numeric`);
|
|
340
|
+
break;
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Check normalization
|
|
345
|
+
if (this.options.checkNormalization && errors.length === 0) {
|
|
346
|
+
let sumSquares = 0;
|
|
347
|
+
for (const val of embedding) {
|
|
348
|
+
sumSquares += val * val;
|
|
349
|
+
}
|
|
350
|
+
const norm = Math.sqrt(sumSquares);
|
|
351
|
+
if (Math.abs(norm - 1.0) > 0.01) {
|
|
352
|
+
warnings.push(`Embedding is not normalized (norm=${norm.toFixed(4)})`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
|
|
356
|
+
return createValidationResult(errors.length === 0, errors, warnings);
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Combines multiple validators
|
|
362
|
+
*/
|
|
363
|
+
export class CompositeValidator<T> implements Validator<T> {
|
|
364
|
+
private validators: Validator<T>[];
|
|
365
|
+
|
|
366
|
+
constructor(validators: Validator<T>[]) {
|
|
367
|
+
this.validators = validators;
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
validate(data: T): ValidationResult {
|
|
371
|
+
let result = createValidationResult(true);
|
|
372
|
+
for (const validator of this.validators) {
|
|
373
|
+
const subResult = validator.validate(data);
|
|
374
|
+
result = mergeValidationResults(result, subResult);
|
|
375
|
+
}
|
|
376
|
+
return result;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/**
|
|
381
|
+
* Registry for managing validators
|
|
382
|
+
*/
|
|
383
|
+
export class ValidatorRegistry {
|
|
384
|
+
schemaValidators: ToolSchemaValidator[] = [];
|
|
385
|
+
parameterValidators: ParameterValidator[] = [];
|
|
386
|
+
resultValidators: ResultValidator[] = [];
|
|
387
|
+
embeddingValidators: EmbeddingValidator[] = [];
|
|
388
|
+
|
|
389
|
+
addSchemaValidator(validator: ToolSchemaValidator): void {
|
|
390
|
+
this.schemaValidators.push(validator);
|
|
391
|
+
}
|
|
392
|
+
|
|
393
|
+
addParameterValidator(validator: ParameterValidator): void {
|
|
394
|
+
this.parameterValidators.push(validator);
|
|
395
|
+
}
|
|
396
|
+
|
|
397
|
+
addResultValidator(validator: ResultValidator): void {
|
|
398
|
+
this.resultValidators.push(validator);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
addEmbeddingValidator(validator: EmbeddingValidator): void {
|
|
402
|
+
this.embeddingValidators.push(validator);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
validateTool(tool: Tool): ValidationResult {
|
|
406
|
+
let result = createValidationResult(true);
|
|
407
|
+
for (const validator of this.schemaValidators) {
|
|
408
|
+
const subResult = validator.validate(tool);
|
|
409
|
+
result = mergeValidationResults(result, subResult);
|
|
410
|
+
}
|
|
411
|
+
return result;
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
validateParams(tool: Tool, params: Record<string, unknown>): ValidationResult {
|
|
415
|
+
let result = createValidationResult(true);
|
|
416
|
+
for (const validator of this.parameterValidators) {
|
|
417
|
+
const subResult = validator.validate({ tool, params });
|
|
418
|
+
result = mergeValidationResults(result, subResult);
|
|
419
|
+
}
|
|
420
|
+
return result;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
validateResult(tool: Tool, resultValue: unknown): ValidationResult {
|
|
424
|
+
let result = createValidationResult(true);
|
|
425
|
+
for (const validator of this.resultValidators) {
|
|
426
|
+
const subResult = validator.validate({ tool, result: resultValue });
|
|
427
|
+
result = mergeValidationResults(result, subResult);
|
|
428
|
+
}
|
|
429
|
+
return result;
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
validateEmbedding(embedding: number[]): ValidationResult {
|
|
433
|
+
let result = createValidationResult(true);
|
|
434
|
+
for (const validator of this.embeddingValidators) {
|
|
435
|
+
const subResult = validator.validate(embedding);
|
|
436
|
+
result = mergeValidationResults(result, subResult);
|
|
437
|
+
}
|
|
438
|
+
return result;
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
clear(): void {
|
|
442
|
+
this.schemaValidators = [];
|
|
443
|
+
this.parameterValidators = [];
|
|
444
|
+
this.resultValidators = [];
|
|
445
|
+
this.embeddingValidators = [];
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
/**
|
|
450
|
+
* Create a registry with strict validators
|
|
451
|
+
*/
|
|
452
|
+
export function createStrictValidator(): ValidatorRegistry {
|
|
453
|
+
const registry = new ValidatorRegistry();
|
|
454
|
+
registry.addSchemaValidator(
|
|
455
|
+
new ToolSchemaValidator({
|
|
456
|
+
requireDescription: true,
|
|
457
|
+
minDescriptionLength: 10,
|
|
458
|
+
})
|
|
459
|
+
);
|
|
460
|
+
registry.addParameterValidator(new ParameterValidator({ strict: true }));
|
|
461
|
+
registry.addResultValidator(new ResultValidator({ strict: true }));
|
|
462
|
+
return registry;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
/**
|
|
466
|
+
* Create a registry with lenient validators
|
|
467
|
+
*/
|
|
468
|
+
export function createLenientValidator(): ValidatorRegistry {
|
|
469
|
+
const registry = new ValidatorRegistry();
|
|
470
|
+
registry.addSchemaValidator(
|
|
471
|
+
new ToolSchemaValidator({
|
|
472
|
+
requireDescription: false,
|
|
473
|
+
minDescriptionLength: 0,
|
|
474
|
+
})
|
|
475
|
+
);
|
|
476
|
+
registry.addParameterValidator(
|
|
477
|
+
new ParameterValidator({
|
|
478
|
+
strict: false,
|
|
479
|
+
allowExtra: true,
|
|
480
|
+
})
|
|
481
|
+
);
|
|
482
|
+
registry.addResultValidator(new ResultValidator({ strict: false }));
|
|
483
|
+
return registry;
|
|
484
|
+
}
|