veto-sdk 1.0.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.
Files changed (146) hide show
  1. package/README.md +209 -0
  2. package/dist/benchmark/cli.d.ts +22 -0
  3. package/dist/benchmark/cli.d.ts.map +1 -0
  4. package/dist/benchmark/cli.js +238 -0
  5. package/dist/benchmark/cli.js.map +1 -0
  6. package/dist/benchmark/index.d.ts +10 -0
  7. package/dist/benchmark/index.d.ts.map +1 -0
  8. package/dist/benchmark/index.js +10 -0
  9. package/dist/benchmark/index.js.map +1 -0
  10. package/dist/benchmark/loader.d.ts +19 -0
  11. package/dist/benchmark/loader.d.ts.map +1 -0
  12. package/dist/benchmark/loader.js +321 -0
  13. package/dist/benchmark/loader.js.map +1 -0
  14. package/dist/benchmark/metrics.d.ts +35 -0
  15. package/dist/benchmark/metrics.d.ts.map +1 -0
  16. package/dist/benchmark/metrics.js +195 -0
  17. package/dist/benchmark/metrics.js.map +1 -0
  18. package/dist/benchmark/runner.d.ts +39 -0
  19. package/dist/benchmark/runner.d.ts.map +1 -0
  20. package/dist/benchmark/runner.js +279 -0
  21. package/dist/benchmark/runner.js.map +1 -0
  22. package/dist/benchmark/types.d.ts +188 -0
  23. package/dist/benchmark/types.d.ts.map +1 -0
  24. package/dist/benchmark/types.js +24 -0
  25. package/dist/benchmark/types.js.map +1 -0
  26. package/dist/cli/bin.d.ts +8 -0
  27. package/dist/cli/bin.d.ts.map +1 -0
  28. package/dist/cli/bin.js +120 -0
  29. package/dist/cli/bin.js.map +1 -0
  30. package/dist/cli/config.d.ts +126 -0
  31. package/dist/cli/config.d.ts.map +1 -0
  32. package/dist/cli/config.js +137 -0
  33. package/dist/cli/config.js.map +1 -0
  34. package/dist/cli/index.d.ts +9 -0
  35. package/dist/cli/index.d.ts.map +1 -0
  36. package/dist/cli/index.js +9 -0
  37. package/dist/cli/index.js.map +1 -0
  38. package/dist/cli/init.d.ts +64 -0
  39. package/dist/cli/init.d.ts.map +1 -0
  40. package/dist/cli/init.js +160 -0
  41. package/dist/cli/init.js.map +1 -0
  42. package/dist/cli/templates.d.ts +22 -0
  43. package/dist/cli/templates.d.ts.map +1 -0
  44. package/dist/cli/templates.js +132 -0
  45. package/dist/cli/templates.js.map +1 -0
  46. package/dist/core/history.d.ts +104 -0
  47. package/dist/core/history.d.ts.map +1 -0
  48. package/dist/core/history.js +148 -0
  49. package/dist/core/history.js.map +1 -0
  50. package/dist/core/index.d.ts +10 -0
  51. package/dist/core/index.d.ts.map +1 -0
  52. package/dist/core/index.js +10 -0
  53. package/dist/core/index.js.map +1 -0
  54. package/dist/core/interceptor.d.ts +96 -0
  55. package/dist/core/interceptor.d.ts.map +1 -0
  56. package/dist/core/interceptor.js +227 -0
  57. package/dist/core/interceptor.js.map +1 -0
  58. package/dist/core/validator.d.ts +107 -0
  59. package/dist/core/validator.d.ts.map +1 -0
  60. package/dist/core/validator.js +263 -0
  61. package/dist/core/validator.js.map +1 -0
  62. package/dist/core/veto.d.ts +265 -0
  63. package/dist/core/veto.d.ts.map +1 -0
  64. package/dist/core/veto.js +681 -0
  65. package/dist/core/veto.js.map +1 -0
  66. package/dist/index.d.ts +43 -0
  67. package/dist/index.d.ts.map +1 -0
  68. package/dist/index.js +40 -0
  69. package/dist/index.js.map +1 -0
  70. package/dist/kernel/client.d.ts +82 -0
  71. package/dist/kernel/client.d.ts.map +1 -0
  72. package/dist/kernel/client.js +162 -0
  73. package/dist/kernel/client.js.map +1 -0
  74. package/dist/kernel/index.d.ts +9 -0
  75. package/dist/kernel/index.d.ts.map +1 -0
  76. package/dist/kernel/index.js +9 -0
  77. package/dist/kernel/index.js.map +1 -0
  78. package/dist/kernel/prompt.d.ts +27 -0
  79. package/dist/kernel/prompt.d.ts.map +1 -0
  80. package/dist/kernel/prompt.js +127 -0
  81. package/dist/kernel/prompt.js.map +1 -0
  82. package/dist/kernel/types.d.ts +85 -0
  83. package/dist/kernel/types.d.ts.map +1 -0
  84. package/dist/kernel/types.js +52 -0
  85. package/dist/kernel/types.js.map +1 -0
  86. package/dist/providers/adapters.d.ts +167 -0
  87. package/dist/providers/adapters.d.ts.map +1 -0
  88. package/dist/providers/adapters.js +244 -0
  89. package/dist/providers/adapters.js.map +1 -0
  90. package/dist/providers/index.d.ts +11 -0
  91. package/dist/providers/index.d.ts.map +1 -0
  92. package/dist/providers/index.js +11 -0
  93. package/dist/providers/index.js.map +1 -0
  94. package/dist/providers/types.d.ts +92 -0
  95. package/dist/providers/types.d.ts.map +1 -0
  96. package/dist/providers/types.js +10 -0
  97. package/dist/providers/types.js.map +1 -0
  98. package/dist/rules/api-client.d.ts +103 -0
  99. package/dist/rules/api-client.d.ts.map +1 -0
  100. package/dist/rules/api-client.js +241 -0
  101. package/dist/rules/api-client.js.map +1 -0
  102. package/dist/rules/index.d.ts +10 -0
  103. package/dist/rules/index.d.ts.map +1 -0
  104. package/dist/rules/index.js +10 -0
  105. package/dist/rules/index.js.map +1 -0
  106. package/dist/rules/loader.d.ts +116 -0
  107. package/dist/rules/loader.d.ts.map +1 -0
  108. package/dist/rules/loader.js +300 -0
  109. package/dist/rules/loader.js.map +1 -0
  110. package/dist/rules/rule-validator.d.ts +135 -0
  111. package/dist/rules/rule-validator.d.ts.map +1 -0
  112. package/dist/rules/rule-validator.js +239 -0
  113. package/dist/rules/rule-validator.js.map +1 -0
  114. package/dist/rules/types.d.ts +162 -0
  115. package/dist/rules/types.d.ts.map +1 -0
  116. package/dist/rules/types.js +16 -0
  117. package/dist/rules/types.js.map +1 -0
  118. package/dist/types/config.d.ts +171 -0
  119. package/dist/types/config.d.ts.map +1 -0
  120. package/dist/types/config.js +31 -0
  121. package/dist/types/config.js.map +1 -0
  122. package/dist/types/index.d.ts +8 -0
  123. package/dist/types/index.d.ts.map +1 -0
  124. package/dist/types/index.js +8 -0
  125. package/dist/types/index.js.map +1 -0
  126. package/dist/types/tool.d.ts +156 -0
  127. package/dist/types/tool.d.ts.map +1 -0
  128. package/dist/types/tool.js +27 -0
  129. package/dist/types/tool.js.map +1 -0
  130. package/dist/utils/glob.d.ts +21 -0
  131. package/dist/utils/glob.d.ts.map +1 -0
  132. package/dist/utils/glob.js +147 -0
  133. package/dist/utils/glob.js.map +1 -0
  134. package/dist/utils/id.d.ts +28 -0
  135. package/dist/utils/id.d.ts.map +1 -0
  136. package/dist/utils/id.js +43 -0
  137. package/dist/utils/id.js.map +1 -0
  138. package/dist/utils/index.d.ts +9 -0
  139. package/dist/utils/index.d.ts.map +1 -0
  140. package/dist/utils/index.js +9 -0
  141. package/dist/utils/index.js.map +1 -0
  142. package/dist/utils/logger.d.ts +97 -0
  143. package/dist/utils/logger.d.ts.map +1 -0
  144. package/dist/utils/logger.js +153 -0
  145. package/dist/utils/logger.js.map +1 -0
  146. package/package.json +90 -0
@@ -0,0 +1,300 @@
1
+ /**
2
+ * YAML rule loader and parser.
3
+ *
4
+ * Loads rules from YAML files and builds an indexed structure for
5
+ * efficient rule lookup during validation.
6
+ *
7
+ * @module rules/loader
8
+ */
9
+ import { readFileSync, readdirSync, statSync, existsSync } from 'node:fs';
10
+ import { join, extname } from 'node:path';
11
+ /**
12
+ * Default YAML parser that throws an error.
13
+ * Users must provide their own parser.
14
+ */
15
+ function defaultYamlParser() {
16
+ throw new Error('No YAML parser provided. Please provide a YAML parser function (e.g., from js-yaml package).');
17
+ }
18
+ /**
19
+ * Loads and manages YAML-based rules.
20
+ */
21
+ export class RuleLoader {
22
+ logger;
23
+ yamlParser = defaultYamlParser;
24
+ loadedRules = {
25
+ ruleSets: [],
26
+ allRules: [],
27
+ rulesByTool: new Map(),
28
+ globalRules: [],
29
+ sourceFiles: [],
30
+ };
31
+ constructor(options) {
32
+ this.logger = options.logger;
33
+ }
34
+ /**
35
+ * Set the YAML parser to use for loading rules.
36
+ *
37
+ * @param parser - YAML parsing function
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * import yaml from 'js-yaml';
42
+ * loader.setYamlParser(yaml.load);
43
+ * ```
44
+ */
45
+ setYamlParser(parser) {
46
+ this.yamlParser = parser;
47
+ this.logger.debug('YAML parser configured');
48
+ }
49
+ /**
50
+ * Load rules from a directory containing YAML files.
51
+ *
52
+ * @param dirPath - Path to the directory
53
+ * @param recursive - Whether to search subdirectories
54
+ * @returns Loaded rules
55
+ */
56
+ loadFromDirectory(dirPath, recursive = true) {
57
+ this.logger.info('Loading rules from directory', { path: dirPath, recursive });
58
+ if (!existsSync(dirPath)) {
59
+ this.logger.warn('Rules directory does not exist', { path: dirPath });
60
+ return this.loadedRules;
61
+ }
62
+ const yamlFiles = this.findYamlFiles(dirPath, recursive);
63
+ this.logger.debug('Found YAML files', { count: yamlFiles.length });
64
+ for (const filePath of yamlFiles) {
65
+ try {
66
+ this.loadFromFile(filePath);
67
+ }
68
+ catch (error) {
69
+ this.logger.error('Failed to load rule file', { path: filePath }, error instanceof Error ? error : new Error(String(error)));
70
+ }
71
+ }
72
+ this.buildIndex();
73
+ return this.loadedRules;
74
+ }
75
+ /**
76
+ * Load rules from a single YAML file.
77
+ *
78
+ * @param filePath - Path to the YAML file
79
+ */
80
+ loadFromFile(filePath) {
81
+ this.logger.debug('Loading rules from file', { path: filePath });
82
+ const content = readFileSync(filePath, 'utf-8');
83
+ const parsed = this.yamlParser(content);
84
+ if (!parsed || typeof parsed !== 'object') {
85
+ this.logger.warn('Invalid YAML content', { path: filePath });
86
+ return;
87
+ }
88
+ const ruleSet = this.parseRuleSet(parsed, filePath);
89
+ if (ruleSet) {
90
+ this.loadedRules.ruleSets.push(ruleSet);
91
+ this.loadedRules.sourceFiles.push(filePath);
92
+ this.logger.info('Loaded rule set', {
93
+ name: ruleSet.name,
94
+ ruleCount: ruleSet.rules.length,
95
+ path: filePath,
96
+ });
97
+ }
98
+ }
99
+ /**
100
+ * Load rules from a YAML string.
101
+ *
102
+ * @param content - YAML content
103
+ * @param sourceName - Name to identify the source
104
+ */
105
+ loadFromString(content, sourceName = 'inline') {
106
+ this.logger.debug('Loading rules from string', { source: sourceName });
107
+ const parsed = this.yamlParser(content);
108
+ if (!parsed || typeof parsed !== 'object') {
109
+ this.logger.warn('Invalid YAML content', { source: sourceName });
110
+ return;
111
+ }
112
+ const ruleSet = this.parseRuleSet(parsed, sourceName);
113
+ if (ruleSet) {
114
+ this.loadedRules.ruleSets.push(ruleSet);
115
+ this.loadedRules.sourceFiles.push(sourceName);
116
+ this.buildIndex();
117
+ }
118
+ }
119
+ /**
120
+ * Add rules directly without YAML parsing.
121
+ *
122
+ * @param rules - Rules to add
123
+ * @param setName - Name for the rule set
124
+ */
125
+ addRules(rules, setName = 'programmatic') {
126
+ const ruleSet = {
127
+ version: '1.0',
128
+ name: setName,
129
+ rules,
130
+ };
131
+ this.loadedRules.ruleSets.push(ruleSet);
132
+ this.buildIndex();
133
+ this.logger.info('Added rules programmatically', {
134
+ name: setName,
135
+ count: rules.length,
136
+ });
137
+ }
138
+ /**
139
+ * Get all loaded rules.
140
+ */
141
+ getRules() {
142
+ return this.loadedRules;
143
+ }
144
+ /**
145
+ * Get rules applicable to a specific tool.
146
+ *
147
+ * @param toolName - Name of the tool
148
+ * @returns Rules that apply to the tool
149
+ */
150
+ getRulesForTool(toolName) {
151
+ const toolSpecific = this.loadedRules.rulesByTool.get(toolName) ?? [];
152
+ return [...this.loadedRules.globalRules, ...toolSpecific].filter((rule) => rule.enabled);
153
+ }
154
+ /**
155
+ * Clear all loaded rules.
156
+ */
157
+ clear() {
158
+ this.loadedRules = {
159
+ ruleSets: [],
160
+ allRules: [],
161
+ rulesByTool: new Map(),
162
+ globalRules: [],
163
+ sourceFiles: [],
164
+ };
165
+ this.logger.debug('Cleared all rules');
166
+ }
167
+ /**
168
+ * Reload rules from previously loaded sources.
169
+ */
170
+ reload() {
171
+ const sources = [...this.loadedRules.sourceFiles];
172
+ this.clear();
173
+ for (const source of sources) {
174
+ if (existsSync(source)) {
175
+ this.loadFromFile(source);
176
+ }
177
+ }
178
+ this.buildIndex();
179
+ this.logger.info('Reloaded rules', { sourceCount: sources.length });
180
+ return this.loadedRules;
181
+ }
182
+ /**
183
+ * Find YAML files in a directory.
184
+ */
185
+ findYamlFiles(dirPath, recursive) {
186
+ const files = [];
187
+ const entries = readdirSync(dirPath);
188
+ for (const entry of entries) {
189
+ const fullPath = join(dirPath, entry);
190
+ const stat = statSync(fullPath);
191
+ if (stat.isDirectory() && recursive) {
192
+ files.push(...this.findYamlFiles(fullPath, recursive));
193
+ }
194
+ else if (stat.isFile()) {
195
+ const ext = extname(entry).toLowerCase();
196
+ if (ext === '.yaml' || ext === '.yml') {
197
+ files.push(fullPath);
198
+ }
199
+ }
200
+ }
201
+ return files;
202
+ }
203
+ /**
204
+ * Parse a rule set from parsed YAML.
205
+ */
206
+ parseRuleSet(data, source) {
207
+ // Check if this is a rule set format or just a list of rules
208
+ if (Array.isArray(data)) {
209
+ // It's just an array of rules
210
+ return {
211
+ version: '1.0',
212
+ name: source,
213
+ rules: data.map((r, i) => this.parseRule(r, `${source}:rule-${i}`)),
214
+ };
215
+ }
216
+ // Check for rules array in the object
217
+ const rules = data.rules;
218
+ if (!rules || !Array.isArray(rules)) {
219
+ // Maybe it's a single rule
220
+ if (data.id && data.name) {
221
+ return {
222
+ version: '1.0',
223
+ name: source,
224
+ rules: [this.parseRule(data, source)],
225
+ };
226
+ }
227
+ this.logger.warn('No rules found in file', { source });
228
+ return null;
229
+ }
230
+ return {
231
+ version: data.version ?? '1.0',
232
+ name: data.name ?? source,
233
+ description: data.description,
234
+ rules: rules.map((r, i) => this.parseRule(r, `${source}:rule-${i}`)),
235
+ settings: data.settings,
236
+ };
237
+ }
238
+ /**
239
+ * Parse a single rule from YAML data.
240
+ */
241
+ parseRule(data, source) {
242
+ if (!data || typeof data !== 'object') {
243
+ throw new Error(`Invalid rule at ${source}`);
244
+ }
245
+ const ruleData = data;
246
+ return {
247
+ id: ruleData.id ?? `auto-${Date.now()}-${Math.random().toString(36).slice(2)}`,
248
+ name: ruleData.name ?? 'Unnamed Rule',
249
+ description: ruleData.description,
250
+ enabled: ruleData.enabled !== false, // Default to true
251
+ severity: ruleData.severity ?? 'medium',
252
+ action: ruleData.action ?? 'block',
253
+ tools: ruleData.tools,
254
+ conditions: ruleData.conditions,
255
+ condition_groups: ruleData.condition_groups,
256
+ tags: ruleData.tags,
257
+ metadata: ruleData.metadata,
258
+ };
259
+ }
260
+ /**
261
+ * Build the rule index for efficient lookup.
262
+ */
263
+ buildIndex() {
264
+ this.loadedRules.allRules = [];
265
+ this.loadedRules.rulesByTool = new Map();
266
+ this.loadedRules.globalRules = [];
267
+ for (const ruleSet of this.loadedRules.ruleSets) {
268
+ for (const rule of ruleSet.rules) {
269
+ this.loadedRules.allRules.push(rule);
270
+ if (!rule.tools || rule.tools.length === 0) {
271
+ // Global rule applies to all tools
272
+ this.loadedRules.globalRules.push(rule);
273
+ }
274
+ else {
275
+ // Tool-specific rule
276
+ for (const toolName of rule.tools) {
277
+ const existing = this.loadedRules.rulesByTool.get(toolName) ?? [];
278
+ existing.push(rule);
279
+ this.loadedRules.rulesByTool.set(toolName, existing);
280
+ }
281
+ }
282
+ }
283
+ }
284
+ this.logger.debug('Built rule index', {
285
+ totalRules: this.loadedRules.allRules.length,
286
+ globalRules: this.loadedRules.globalRules.length,
287
+ toolsWithRules: this.loadedRules.rulesByTool.size,
288
+ });
289
+ }
290
+ }
291
+ /**
292
+ * Create a new rule loader.
293
+ *
294
+ * @param options - Loader options
295
+ * @returns RuleLoader instance
296
+ */
297
+ export function createRuleLoader(options) {
298
+ return new RuleLoader(options);
299
+ }
300
+ //# sourceMappingURL=loader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"loader.js","sourceRoot":"","sources":["../../src/rules/loader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,135 @@
1
+ /**
2
+ * Rule-based validator.
3
+ *
4
+ * This validator loads rules from YAML files and validates tool calls
5
+ * by sending them to an external API.
6
+ *
7
+ * @module rules/rule-validator
8
+ */
9
+ import type { Logger } from '../utils/logger.js';
10
+ import type { ValidationContext, ValidationResult, NamedValidator } from '../types/config.js';
11
+ import type { Rule } from './types.js';
12
+ import { RuleLoader, type YamlParser } from './loader.js';
13
+ import { ValidationAPIClient, type ValidationAPIConfig } from './api-client.js';
14
+ /**
15
+ * Configuration for the rule-based validator.
16
+ */
17
+ export interface RuleValidatorConfig {
18
+ /** API configuration */
19
+ api: ValidationAPIConfig;
20
+ /** Path to directory containing rule YAML files */
21
+ rulesDir?: string;
22
+ /** YAML parser function (e.g., from js-yaml) */
23
+ yamlParser?: YamlParser;
24
+ /** Whether to search subdirectories for rules */
25
+ recursiveRuleSearch?: boolean;
26
+ /** Behavior when API is unavailable */
27
+ failMode?: 'open' | 'closed';
28
+ /** Session ID for tracking */
29
+ sessionId?: string;
30
+ /** Agent ID for tracking */
31
+ agentId?: string;
32
+ }
33
+ /**
34
+ * Options for the rule validator.
35
+ */
36
+ export interface RuleValidatorOptions {
37
+ /** Configuration */
38
+ config: RuleValidatorConfig;
39
+ /** Logger instance */
40
+ logger: Logger;
41
+ }
42
+ /**
43
+ * Rule-based validator that uses an external API for decisions.
44
+ *
45
+ * This validator:
46
+ * 1. Loads rules from YAML files
47
+ * 2. For each tool call, finds applicable rules
48
+ * 3. Sends the context and rules to an API
49
+ * 4. Returns the decision from the API
50
+ */
51
+ export declare class RuleValidator {
52
+ private readonly logger;
53
+ private readonly config;
54
+ private readonly ruleLoader;
55
+ private readonly apiClient;
56
+ private readonly sessionId?;
57
+ private readonly agentId?;
58
+ private isInitialized;
59
+ constructor(options: RuleValidatorOptions);
60
+ /**
61
+ * Initialize the validator by loading rules.
62
+ *
63
+ * Call this before using the validator if rules are loaded from files.
64
+ */
65
+ initialize(): Promise<void>;
66
+ /**
67
+ * Set the YAML parser.
68
+ */
69
+ setYamlParser(parser: YamlParser): void;
70
+ /**
71
+ * Add rules programmatically.
72
+ */
73
+ addRules(rules: Rule[], setName?: string): void;
74
+ /**
75
+ * Load rules from a YAML string.
76
+ */
77
+ loadRulesFromString(yamlContent: string, sourceName?: string): void;
78
+ /**
79
+ * Get the rule loader for direct access.
80
+ */
81
+ getRuleLoader(): RuleLoader;
82
+ /**
83
+ * Get the API client for direct access.
84
+ */
85
+ getAPIClient(): ValidationAPIClient;
86
+ /**
87
+ * Validate a tool call.
88
+ *
89
+ * @param context - Validation context from Veto
90
+ * @returns Validation result
91
+ */
92
+ validate(context: ValidationContext): Promise<ValidationResult>;
93
+ /**
94
+ * Create a NamedValidator for use with Veto.
95
+ *
96
+ * @returns Named validator instance
97
+ */
98
+ toNamedValidator(): NamedValidator;
99
+ /**
100
+ * Build the API context from the validation context.
101
+ */
102
+ private buildToolCallContext;
103
+ /**
104
+ * Build a summary of call history for the API.
105
+ */
106
+ private buildHistorySummary;
107
+ }
108
+ /**
109
+ * Create a rule-based validator.
110
+ *
111
+ * @param options - Validator options
112
+ * @returns RuleValidator instance
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * import yaml from 'js-yaml';
117
+ *
118
+ * const ruleValidator = createRuleValidator({
119
+ * config: {
120
+ * api: { baseUrl: 'http://localhost:8080' },
121
+ * rulesDir: './rules',
122
+ * yamlParser: yaml.load,
123
+ * },
124
+ * logger: createLogger('info'),
125
+ * });
126
+ *
127
+ * await ruleValidator.initialize();
128
+ *
129
+ * const veto = new Veto({
130
+ * validators: [ruleValidator.toNamedValidator()],
131
+ * });
132
+ * ```
133
+ */
134
+ export declare function createRuleValidator(options: RuleValidatorOptions): RuleValidator;
135
+ //# sourceMappingURL=rule-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rule-validator.d.ts","sourceRoot":"","sources":["../../src/rules/rule-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AACjD,OAAO,KAAK,EACV,iBAAiB,EACjB,gBAAgB,EAChB,cAAc,EACf,MAAM,oBAAoB,CAAC;AAE5B,OAAO,KAAK,EAAE,IAAI,EAA2C,MAAM,YAAY,CAAC;AAChF,OAAO,EAAE,UAAU,EAAE,KAAK,UAAU,EAAE,MAAM,aAAa,CAAC;AAC1D,OAAO,EAAE,mBAAmB,EAAE,KAAK,mBAAmB,EAAE,MAAM,iBAAiB,CAAC;AAEhF;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,wBAAwB;IACxB,GAAG,EAAE,mBAAmB,CAAC;IACzB,mDAAmD;IACnD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,gDAAgD;IAChD,UAAU,CAAC,EAAE,UAAU,CAAC;IACxB,iDAAiD;IACjD,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAC9B,uCAAuC;IACvC,QAAQ,CAAC,EAAE,MAAM,GAAG,QAAQ,CAAC;IAC7B,8BAA8B;IAC9B,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,4BAA4B;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;GAEG;AACH,MAAM,WAAW,oBAAoB;IACnC,oBAAoB;IACpB,MAAM,EAAE,mBAAmB,CAAC;IAC5B,sBAAsB;IACtB,MAAM,EAAE,MAAM,CAAC;CAChB;AAED;;;;;;;;GAQG;AACH,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAsB;IAC7C,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAa;IACxC,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAsB;IAChD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAS;IACpC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAS;IAClC,OAAO,CAAC,aAAa,CAAS;gBAElB,OAAO,EAAE,oBAAoB;IA2BzC;;;;OAIG;IACG,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC;IAyBjC;;OAEG;IACH,aAAa,CAAC,MAAM,EAAE,UAAU,GAAG,IAAI;IAIvC;;OAEG;IACH,QAAQ,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,IAAI;IAI/C;;OAEG;IACH,mBAAmB,CAAC,WAAW,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,GAAG,IAAI;IAInE;;OAEG;IACH,aAAa,IAAI,UAAU;IAI3B;;OAEG;IACH,YAAY,IAAI,mBAAmB;IAInC;;;;;OAKG;IACG,QAAQ,CAAC,OAAO,EAAE,iBAAiB,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAsErE;;;;OAIG;IACH,gBAAgB,IAAI,cAAc;IASlC;;OAEG;IACH,OAAO,CAAC,oBAAoB;IAa5B;;OAEG;IACH,OAAO,CAAC,mBAAmB;CAS5B;AAED;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,mBAAmB,CAAC,OAAO,EAAE,oBAAoB,GAAG,aAAa,CAEhF"}
@@ -0,0 +1,239 @@
1
+ /**
2
+ * Rule-based validator.
3
+ *
4
+ * This validator loads rules from YAML files and validates tool calls
5
+ * by sending them to an external API.
6
+ *
7
+ * @module rules/rule-validator
8
+ */
9
+ import { RuleLoader } from './loader.js';
10
+ import { ValidationAPIClient } from './api-client.js';
11
+ /**
12
+ * Rule-based validator that uses an external API for decisions.
13
+ *
14
+ * This validator:
15
+ * 1. Loads rules from YAML files
16
+ * 2. For each tool call, finds applicable rules
17
+ * 3. Sends the context and rules to an API
18
+ * 4. Returns the decision from the API
19
+ */
20
+ export class RuleValidator {
21
+ logger;
22
+ config;
23
+ ruleLoader;
24
+ apiClient;
25
+ sessionId;
26
+ agentId;
27
+ isInitialized = false;
28
+ constructor(options) {
29
+ this.logger = options.logger;
30
+ this.config = options.config;
31
+ this.sessionId = options.config.sessionId;
32
+ this.agentId = options.config.agentId;
33
+ // Initialize rule loader
34
+ this.ruleLoader = new RuleLoader({ logger: this.logger });
35
+ // Set YAML parser if provided
36
+ if (this.config.yamlParser) {
37
+ this.ruleLoader.setYamlParser(this.config.yamlParser);
38
+ }
39
+ // Initialize API client
40
+ this.apiClient = new ValidationAPIClient({
41
+ config: this.config.api,
42
+ logger: this.logger,
43
+ failMode: this.config.failMode,
44
+ });
45
+ this.logger.info('Rule validator created', {
46
+ rulesDir: this.config.rulesDir,
47
+ apiEndpoint: this.config.api.baseUrl + (this.config.api.endpoint ?? '/tool/call/check'),
48
+ });
49
+ }
50
+ /**
51
+ * Initialize the validator by loading rules.
52
+ *
53
+ * Call this before using the validator if rules are loaded from files.
54
+ */
55
+ async initialize() {
56
+ if (this.isInitialized) {
57
+ return;
58
+ }
59
+ if (this.config.rulesDir) {
60
+ if (!this.config.yamlParser) {
61
+ this.logger.warn('Rules directory specified but no YAML parser provided. ' +
62
+ 'Call setYamlParser() before initialize() or use addRules().');
63
+ }
64
+ else {
65
+ this.ruleLoader.loadFromDirectory(this.config.rulesDir, this.config.recursiveRuleSearch ?? true);
66
+ }
67
+ }
68
+ this.isInitialized = true;
69
+ this.logger.info('Rule validator initialized', {
70
+ totalRules: this.ruleLoader.getRules().allRules.length,
71
+ });
72
+ }
73
+ /**
74
+ * Set the YAML parser.
75
+ */
76
+ setYamlParser(parser) {
77
+ this.ruleLoader.setYamlParser(parser);
78
+ }
79
+ /**
80
+ * Add rules programmatically.
81
+ */
82
+ addRules(rules, setName) {
83
+ this.ruleLoader.addRules(rules, setName);
84
+ }
85
+ /**
86
+ * Load rules from a YAML string.
87
+ */
88
+ loadRulesFromString(yamlContent, sourceName) {
89
+ this.ruleLoader.loadFromString(yamlContent, sourceName);
90
+ }
91
+ /**
92
+ * Get the rule loader for direct access.
93
+ */
94
+ getRuleLoader() {
95
+ return this.ruleLoader;
96
+ }
97
+ /**
98
+ * Get the API client for direct access.
99
+ */
100
+ getAPIClient() {
101
+ return this.apiClient;
102
+ }
103
+ /**
104
+ * Validate a tool call.
105
+ *
106
+ * @param context - Validation context from Veto
107
+ * @returns Validation result
108
+ */
109
+ async validate(context) {
110
+ // Auto-initialize if not already done
111
+ if (!this.isInitialized) {
112
+ await this.initialize();
113
+ }
114
+ // Get applicable rules
115
+ const rules = this.ruleLoader.getRulesForTool(context.toolName);
116
+ this.logger.debug('Validating tool call with rules', {
117
+ toolName: context.toolName,
118
+ callId: context.callId,
119
+ applicableRules: rules.length,
120
+ });
121
+ // If no rules, allow by default
122
+ if (rules.length === 0) {
123
+ this.logger.debug('No rules applicable, allowing by default', {
124
+ toolName: context.toolName,
125
+ });
126
+ return { decision: 'allow' };
127
+ }
128
+ // Build API context
129
+ const apiContext = this.buildToolCallContext(context);
130
+ // Call the API
131
+ const response = await this.apiClient.validate(apiContext, rules);
132
+ // Convert API response to ValidationResult
133
+ if (response.decision === 'pass') {
134
+ this.logger.info('Tool call allowed by API', {
135
+ toolName: context.toolName,
136
+ callId: context.callId,
137
+ passWeight: response.should_pass_weight,
138
+ reasoning: response.reasoning,
139
+ });
140
+ return {
141
+ decision: 'allow',
142
+ reason: response.reasoning,
143
+ metadata: {
144
+ should_pass_weight: response.should_pass_weight,
145
+ should_block_weight: response.should_block_weight,
146
+ matched_rules: response.matched_rules,
147
+ ...response.metadata,
148
+ },
149
+ };
150
+ }
151
+ else {
152
+ this.logger.warn('Tool call blocked by API', {
153
+ toolName: context.toolName,
154
+ callId: context.callId,
155
+ blockWeight: response.should_block_weight,
156
+ reasoning: response.reasoning,
157
+ matchedRules: response.matched_rules,
158
+ });
159
+ return {
160
+ decision: 'deny',
161
+ reason: response.reasoning,
162
+ metadata: {
163
+ should_pass_weight: response.should_pass_weight,
164
+ should_block_weight: response.should_block_weight,
165
+ matched_rules: response.matched_rules,
166
+ ...response.metadata,
167
+ },
168
+ };
169
+ }
170
+ }
171
+ /**
172
+ * Create a NamedValidator for use with Veto.
173
+ *
174
+ * @returns Named validator instance
175
+ */
176
+ toNamedValidator() {
177
+ return {
178
+ name: 'rule-validator',
179
+ description: 'Validates tool calls using YAML rules and external API',
180
+ priority: 50, // Run in the middle
181
+ validate: (context) => this.validate(context),
182
+ };
183
+ }
184
+ /**
185
+ * Build the API context from the validation context.
186
+ */
187
+ buildToolCallContext(context) {
188
+ return {
189
+ call_id: context.callId,
190
+ tool_name: context.toolName,
191
+ arguments: context.arguments,
192
+ timestamp: context.timestamp.toISOString(),
193
+ session_id: this.sessionId,
194
+ agent_id: this.agentId,
195
+ call_history: this.buildHistorySummary(context.callHistory),
196
+ custom: context.custom,
197
+ };
198
+ }
199
+ /**
200
+ * Build a summary of call history for the API.
201
+ */
202
+ buildHistorySummary(history) {
203
+ return history.slice(-10).map((entry) => ({
204
+ tool_name: entry.toolName,
205
+ allowed: entry.validationResult.decision !== 'deny',
206
+ timestamp: entry.timestamp.toISOString(),
207
+ }));
208
+ }
209
+ }
210
+ /**
211
+ * Create a rule-based validator.
212
+ *
213
+ * @param options - Validator options
214
+ * @returns RuleValidator instance
215
+ *
216
+ * @example
217
+ * ```typescript
218
+ * import yaml from 'js-yaml';
219
+ *
220
+ * const ruleValidator = createRuleValidator({
221
+ * config: {
222
+ * api: { baseUrl: 'http://localhost:8080' },
223
+ * rulesDir: './rules',
224
+ * yamlParser: yaml.load,
225
+ * },
226
+ * logger: createLogger('info'),
227
+ * });
228
+ *
229
+ * await ruleValidator.initialize();
230
+ *
231
+ * const veto = new Veto({
232
+ * validators: [ruleValidator.toNamedValidator()],
233
+ * });
234
+ * ```
235
+ */
236
+ export function createRuleValidator(options) {
237
+ return new RuleValidator(options);
238
+ }
239
+ //# sourceMappingURL=rule-validator.js.map