claude-flow-novice 1.5.17 → 1.5.18
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/.claude-flow-novice/dist/config/hooks/post-edit-pipeline.js +1807 -0
- package/.claude-flow-novice/dist/src/hooks/communication-integrated-post-edit.js +673 -0
- package/.claude-flow-novice/dist/src/hooks/enhanced/experience-adaptation-hooks.js +347 -0
- package/.claude-flow-novice/dist/src/hooks/enhanced/personalization-hooks.js +118 -0
- package/.claude-flow-novice/dist/src/hooks/enhanced-post-edit-pipeline.js +2044 -0
- package/.claude-flow-novice/dist/src/hooks/filter-integration.js +542 -0
- package/.claude-flow-novice/dist/src/hooks/guidance-hooks.js +629 -0
- package/.claude-flow-novice/dist/src/hooks/index.ts +239 -0
- package/.claude-flow-novice/dist/src/hooks/managers/enhanced-hook-manager.js +200 -0
- package/.claude-flow-novice/dist/src/hooks/resilient-hook-system.js +812 -0
- package/config/hooks/post-edit-pipeline.js +30 -0
- package/package.json +2 -1
- package/src/cli/simple-commands/init/templates/CLAUDE.md +38 -6
- package/src/hooks/communication-integrated-post-edit.js +673 -0
- package/src/hooks/enhanced/experience-adaptation-hooks.js +347 -0
- package/src/hooks/enhanced/personalization-hooks.js +118 -0
- package/src/hooks/enhanced-hooks-cli.js +168 -0
- package/src/hooks/enhanced-post-edit-pipeline.js +2044 -0
- package/src/hooks/filter-integration.js +542 -0
- package/src/hooks/guidance-hooks.js +629 -0
- package/src/hooks/index.ts +239 -0
- package/src/hooks/managers/enhanced-hook-manager.js +200 -0
- package/src/hooks/resilient-hook-system.js +812 -0
|
@@ -0,0 +1,542 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Filter Integration Hooks
|
|
3
|
+
* Intercepts document generation and applies filtering during agent operations
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
import { ContentFilters } from '../filters/content-filters.js';
|
|
7
|
+
import { ToneProcessors } from '../filters/tone-processors.js';
|
|
8
|
+
import { readFileSync, writeFileSync, existsSync } from 'fs';
|
|
9
|
+
import { join, dirname } from 'path';
|
|
10
|
+
|
|
11
|
+
class FilterIntegrationHooks {
|
|
12
|
+
constructor(projectRoot = process.cwd()) {
|
|
13
|
+
this.projectRoot = projectRoot;
|
|
14
|
+
this.settingsPath = join(projectRoot, '.claude', 'settings.json');
|
|
15
|
+
|
|
16
|
+
this.loadSettings();
|
|
17
|
+
|
|
18
|
+
this.contentFilters = new ContentFilters(this.settings.contentFilters || {});
|
|
19
|
+
this.toneProcessors = new ToneProcessors(this.settings.toneProcessors || {});
|
|
20
|
+
|
|
21
|
+
this.interceptCount = 0;
|
|
22
|
+
this.actionLog = [];
|
|
23
|
+
|
|
24
|
+
this.setupHooks();
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Load settings from .claude/settings.json
|
|
29
|
+
*/
|
|
30
|
+
loadSettings() {
|
|
31
|
+
try {
|
|
32
|
+
if (existsSync(this.settingsPath)) {
|
|
33
|
+
const settingsData = readFileSync(this.settingsPath, 'utf8');
|
|
34
|
+
this.settings = JSON.parse(settingsData);
|
|
35
|
+
} else {
|
|
36
|
+
this.settings = this.getDefaultSettings();
|
|
37
|
+
this.saveSettings();
|
|
38
|
+
}
|
|
39
|
+
} catch (error) {
|
|
40
|
+
console.warn('Error loading settings, using defaults:', error.message);
|
|
41
|
+
this.settings = this.getDefaultSettings();
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* Get default filter settings
|
|
47
|
+
*/
|
|
48
|
+
getDefaultSettings() {
|
|
49
|
+
return {
|
|
50
|
+
contentFilters: {
|
|
51
|
+
enabled: true,
|
|
52
|
+
maxMdFiles: 15,
|
|
53
|
+
allowedDocTypes: ['API', 'README', 'CHANGELOG', 'GUIDE'],
|
|
54
|
+
rootDirectoryProtection: true,
|
|
55
|
+
allowedRootFiles: ['README.md', 'CHANGELOG.md', 'LICENSE.md', 'CONTRIBUTING.md'],
|
|
56
|
+
blockedPatterns: [
|
|
57
|
+
'IMPLEMENTATION_REPORT',
|
|
58
|
+
'COMPLETION_SUMMARY',
|
|
59
|
+
'AGENT_REPORT',
|
|
60
|
+
'PERFORMANCE_ANALYSIS',
|
|
61
|
+
'^TEMP_',
|
|
62
|
+
'^WORKING_',
|
|
63
|
+
'STATUS_UPDATE',
|
|
64
|
+
'PROGRESS_REPORT',
|
|
65
|
+
],
|
|
66
|
+
},
|
|
67
|
+
toneProcessors: {
|
|
68
|
+
enabled: true,
|
|
69
|
+
defaultPreset: 'professional',
|
|
70
|
+
removeSelfCongratulatory: true,
|
|
71
|
+
simplifyJargon: false,
|
|
72
|
+
focusOnActionable: true,
|
|
73
|
+
customPatterns: {
|
|
74
|
+
'we have successfully': 'we have',
|
|
75
|
+
'perfectly implemented': 'implemented',
|
|
76
|
+
'flawless execution': 'execution',
|
|
77
|
+
'amazing results': 'good results',
|
|
78
|
+
},
|
|
79
|
+
},
|
|
80
|
+
hooks: {
|
|
81
|
+
preDocumentGeneration: true,
|
|
82
|
+
postAgentMessage: true,
|
|
83
|
+
preFileWrite: true,
|
|
84
|
+
realTimeFiltering: true,
|
|
85
|
+
},
|
|
86
|
+
userPreferences: {
|
|
87
|
+
tonePreset: 'professional',
|
|
88
|
+
maxDocumentLength: 5000,
|
|
89
|
+
allowReports: false,
|
|
90
|
+
consolidateDocuments: true,
|
|
91
|
+
},
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
/**
|
|
96
|
+
* Save settings to .claude/settings.json
|
|
97
|
+
*/
|
|
98
|
+
saveSettings() {
|
|
99
|
+
try {
|
|
100
|
+
const settingsDir = dirname(this.settingsPath);
|
|
101
|
+
if (!existsSync(settingsDir)) {
|
|
102
|
+
require('fs').mkdirSync(settingsDir, { recursive: true });
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
writeFileSync(this.settingsPath, JSON.stringify(this.settings, null, 2));
|
|
106
|
+
} catch (error) {
|
|
107
|
+
console.error('Error saving settings:', error.message);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Setup integration hooks
|
|
113
|
+
*/
|
|
114
|
+
setupHooks() {
|
|
115
|
+
// Hook into global process if available
|
|
116
|
+
if (typeof process !== 'undefined' && process.on) {
|
|
117
|
+
process.on('documentGeneration', (event) => this.handleDocumentGeneration(event));
|
|
118
|
+
process.on('agentMessage', (event) => this.handleAgentMessage(event));
|
|
119
|
+
process.on('fileWrite', (event) => this.handleFileWrite(event));
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Register CLI hooks
|
|
123
|
+
this.registerCliHooks();
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
/**
|
|
127
|
+
* Register CLI command hooks
|
|
128
|
+
*/
|
|
129
|
+
registerCliHooks() {
|
|
130
|
+
const hookCommands = [
|
|
131
|
+
'pre-document-generation',
|
|
132
|
+
'post-agent-message',
|
|
133
|
+
'pre-file-write',
|
|
134
|
+
'filter-check',
|
|
135
|
+
];
|
|
136
|
+
|
|
137
|
+
// This would integrate with the existing hook system
|
|
138
|
+
hookCommands.forEach((command) => {
|
|
139
|
+
this.registerHook(command);
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
* Register individual hook
|
|
145
|
+
*/
|
|
146
|
+
registerHook(hookName) {
|
|
147
|
+
const hookPath = join(this.projectRoot, '.claude', 'hooks', `${hookName}.js`);
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
if (existsSync(hookPath)) {
|
|
151
|
+
const hookModule = require(hookPath);
|
|
152
|
+
hookModule.addPreProcessor = (processor) => {
|
|
153
|
+
this.addCustomProcessor(hookName, processor);
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
} catch (error) {
|
|
157
|
+
// Hook file doesn't exist or has errors, continue silently
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Intercept document generation requests
|
|
163
|
+
*/
|
|
164
|
+
interceptDocumentGeneration(filePath, content, metadata = {}) {
|
|
165
|
+
if (!this.settings.contentFilters.enabled) {
|
|
166
|
+
return { allowed: true, content, filePath };
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
this.interceptCount++;
|
|
170
|
+
|
|
171
|
+
const filterResult = this.contentFilters.filterDocumentRequest(filePath, content, metadata);
|
|
172
|
+
|
|
173
|
+
let processedContent = content;
|
|
174
|
+
|
|
175
|
+
// Apply tone processing if document is allowed
|
|
176
|
+
if (filterResult.allowed && this.settings.toneProcessors.enabled) {
|
|
177
|
+
const toneResult = this.toneProcessors.processMessage(
|
|
178
|
+
content,
|
|
179
|
+
this.settings.userPreferences.tonePreset,
|
|
180
|
+
this.settings.userPreferences,
|
|
181
|
+
);
|
|
182
|
+
processedContent = toneResult.processed;
|
|
183
|
+
|
|
184
|
+
// Log tone processing
|
|
185
|
+
if (toneResult.changes.length > 0) {
|
|
186
|
+
this.logAction('TONE_PROCESSED', filePath, {
|
|
187
|
+
changes: toneResult.changes,
|
|
188
|
+
metrics: toneResult.metrics,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
const result = {
|
|
194
|
+
allowed: filterResult.allowed,
|
|
195
|
+
content: processedContent,
|
|
196
|
+
filePath: filterResult.suggestedPath,
|
|
197
|
+
reason: filterResult.reason,
|
|
198
|
+
modifications: filterResult.modifications,
|
|
199
|
+
originalPath: filePath,
|
|
200
|
+
processed: content !== processedContent,
|
|
201
|
+
};
|
|
202
|
+
|
|
203
|
+
this.logAction('DOCUMENT_INTERCEPT', filePath, result);
|
|
204
|
+
|
|
205
|
+
return result;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
/**
|
|
209
|
+
* Handle document generation events
|
|
210
|
+
*/
|
|
211
|
+
handleDocumentGeneration(event) {
|
|
212
|
+
const { filePath, content, metadata } = event;
|
|
213
|
+
const result = this.interceptDocumentGeneration(filePath, content, metadata);
|
|
214
|
+
|
|
215
|
+
if (!result.allowed) {
|
|
216
|
+
event.preventDefault();
|
|
217
|
+
event.result = result;
|
|
218
|
+
} else if (result.processed || result.filePath !== result.originalPath) {
|
|
219
|
+
event.content = result.content;
|
|
220
|
+
event.filePath = result.filePath;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
/**
|
|
225
|
+
* Process agent messages through tone filters
|
|
226
|
+
*/
|
|
227
|
+
processAgentMessage(message, agentType = 'generic', context = {}) {
|
|
228
|
+
if (!this.settings.toneProcessors.enabled) {
|
|
229
|
+
return message;
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
// Determine appropriate tone based on agent type and context
|
|
233
|
+
const tonePreset = this.determineTonePreset(agentType, context);
|
|
234
|
+
|
|
235
|
+
const result = this.toneProcessors.processMessage(
|
|
236
|
+
message,
|
|
237
|
+
tonePreset,
|
|
238
|
+
this.settings.userPreferences,
|
|
239
|
+
);
|
|
240
|
+
|
|
241
|
+
this.logAction('MESSAGE_PROCESSED', agentType, {
|
|
242
|
+
originalLength: message.length,
|
|
243
|
+
processedLength: result.processed.length,
|
|
244
|
+
changes: result.changes,
|
|
245
|
+
tone: tonePreset,
|
|
246
|
+
});
|
|
247
|
+
|
|
248
|
+
return result.processed;
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Handle agent message events
|
|
253
|
+
*/
|
|
254
|
+
handleAgentMessage(event) {
|
|
255
|
+
const { message, agentType, context } = event;
|
|
256
|
+
const processedMessage = this.processAgentMessage(message, agentType, context);
|
|
257
|
+
|
|
258
|
+
if (processedMessage !== message) {
|
|
259
|
+
event.message = processedMessage;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
/**
|
|
264
|
+
* Handle file write events
|
|
265
|
+
*/
|
|
266
|
+
handleFileWrite(event) {
|
|
267
|
+
const { filePath, content } = event;
|
|
268
|
+
|
|
269
|
+
if (filePath.endsWith('.md') || this.isDocumentationFile(filePath)) {
|
|
270
|
+
const result = this.interceptDocumentGeneration(filePath, content);
|
|
271
|
+
|
|
272
|
+
if (!result.allowed) {
|
|
273
|
+
event.preventDefault();
|
|
274
|
+
event.result = result;
|
|
275
|
+
|
|
276
|
+
// Suggest alternative action
|
|
277
|
+
if (result.suggestedPath) {
|
|
278
|
+
console.warn(`Document generation blocked: ${result.reason}`);
|
|
279
|
+
console.log(`Suggested alternative: ${result.suggestedPath}`);
|
|
280
|
+
}
|
|
281
|
+
} else {
|
|
282
|
+
event.content = result.content;
|
|
283
|
+
event.filePath = result.filePath;
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
}
|
|
287
|
+
|
|
288
|
+
/**
|
|
289
|
+
* Real-time filtering middleware
|
|
290
|
+
*/
|
|
291
|
+
createFilterMiddleware() {
|
|
292
|
+
return (request, response, next) => {
|
|
293
|
+
// Intercept write operations
|
|
294
|
+
if (request.operation === 'write' && request.filePath) {
|
|
295
|
+
const result = this.interceptDocumentGeneration(
|
|
296
|
+
request.filePath,
|
|
297
|
+
request.content,
|
|
298
|
+
request.metadata,
|
|
299
|
+
);
|
|
300
|
+
|
|
301
|
+
if (!result.allowed) {
|
|
302
|
+
response.status(403).json({
|
|
303
|
+
error: 'Document generation blocked',
|
|
304
|
+
reason: result.reason,
|
|
305
|
+
suggestedPath: result.suggestedPath,
|
|
306
|
+
modifications: result.modifications,
|
|
307
|
+
});
|
|
308
|
+
return;
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
// Update request with processed content
|
|
312
|
+
request.content = result.content;
|
|
313
|
+
request.filePath = result.filePath;
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
next();
|
|
317
|
+
};
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
/**
|
|
321
|
+
* Process multiple documents in batch
|
|
322
|
+
*/
|
|
323
|
+
batchProcessDocuments(documents) {
|
|
324
|
+
return documents.map((doc) => ({
|
|
325
|
+
...doc,
|
|
326
|
+
...this.interceptDocumentGeneration(doc.filePath, doc.content, doc.metadata),
|
|
327
|
+
}));
|
|
328
|
+
}
|
|
329
|
+
|
|
330
|
+
/**
|
|
331
|
+
* Apply filters to agent task output
|
|
332
|
+
*/
|
|
333
|
+
filterTaskOutput(taskId, output, agentType) {
|
|
334
|
+
const processedOutput = {
|
|
335
|
+
messages: [],
|
|
336
|
+
files: [],
|
|
337
|
+
blocked: [],
|
|
338
|
+
modified: [],
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// Process messages
|
|
342
|
+
if (output.messages) {
|
|
343
|
+
output.messages.forEach((message) => {
|
|
344
|
+
const processed = this.processAgentMessage(message.content, agentType, { taskId });
|
|
345
|
+
processedOutput.messages.push({
|
|
346
|
+
...message,
|
|
347
|
+
content: processed,
|
|
348
|
+
modified: processed !== message.content,
|
|
349
|
+
});
|
|
350
|
+
});
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Process file operations
|
|
354
|
+
if (output.files) {
|
|
355
|
+
output.files.forEach((file) => {
|
|
356
|
+
const result = this.interceptDocumentGeneration(file.path, file.content, {
|
|
357
|
+
taskId,
|
|
358
|
+
agentType,
|
|
359
|
+
});
|
|
360
|
+
|
|
361
|
+
if (result.allowed) {
|
|
362
|
+
processedOutput.files.push({
|
|
363
|
+
...file,
|
|
364
|
+
path: result.filePath,
|
|
365
|
+
content: result.content,
|
|
366
|
+
modified: result.processed || result.filePath !== file.path,
|
|
367
|
+
});
|
|
368
|
+
} else {
|
|
369
|
+
processedOutput.blocked.push({
|
|
370
|
+
...file,
|
|
371
|
+
reason: result.reason,
|
|
372
|
+
suggestedPath: result.suggestedPath,
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
}
|
|
377
|
+
|
|
378
|
+
this.logAction('TASK_OUTPUT_FILTERED', taskId, {
|
|
379
|
+
agentType,
|
|
380
|
+
messagesProcessed: processedOutput.messages.length,
|
|
381
|
+
filesAllowed: processedOutput.files.length,
|
|
382
|
+
filesBlocked: processedOutput.blocked.length,
|
|
383
|
+
});
|
|
384
|
+
|
|
385
|
+
return processedOutput;
|
|
386
|
+
}
|
|
387
|
+
|
|
388
|
+
// Helper methods
|
|
389
|
+
|
|
390
|
+
determineTonePreset(agentType, context = {}) {
|
|
391
|
+
const agentToneMap = {
|
|
392
|
+
researcher: 'technical',
|
|
393
|
+
coder: 'concise',
|
|
394
|
+
reviewer: 'professional',
|
|
395
|
+
tester: 'professional',
|
|
396
|
+
planner: 'professional',
|
|
397
|
+
'backend-dev': 'technical',
|
|
398
|
+
'frontend-dev': 'friendly',
|
|
399
|
+
devops: 'concise',
|
|
400
|
+
generic: this.settings.userPreferences.tonePreset,
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
return agentToneMap[agentType] || this.settings.userPreferences.tonePreset;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
isDocumentationFile(filePath) {
|
|
407
|
+
const docExtensions = ['.md', '.txt', '.rst', '.adoc'];
|
|
408
|
+
const docPaths = ['/docs/', '/documentation/', '/guides/', '/README'];
|
|
409
|
+
|
|
410
|
+
return (
|
|
411
|
+
docExtensions.some((ext) => filePath.endsWith(ext)) ||
|
|
412
|
+
docPaths.some((path) => filePath.includes(path))
|
|
413
|
+
);
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
logAction(action, target, details = {}) {
|
|
417
|
+
const logEntry = {
|
|
418
|
+
timestamp: new Date().toISOString(),
|
|
419
|
+
action,
|
|
420
|
+
target,
|
|
421
|
+
details,
|
|
422
|
+
id: this.actionLog.length + 1,
|
|
423
|
+
};
|
|
424
|
+
|
|
425
|
+
this.actionLog.push(logEntry);
|
|
426
|
+
|
|
427
|
+
// Keep log manageable
|
|
428
|
+
if (this.actionLog.length > 1000) {
|
|
429
|
+
this.actionLog = this.actionLog.slice(-500);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
|
|
433
|
+
/**
|
|
434
|
+
* Add custom processor
|
|
435
|
+
*/
|
|
436
|
+
addCustomProcessor(hookName, processor) {
|
|
437
|
+
if (!this.customProcessors) {
|
|
438
|
+
this.customProcessors = {};
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
if (!this.customProcessors[hookName]) {
|
|
442
|
+
this.customProcessors[hookName] = [];
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
this.customProcessors[hookName].push(processor);
|
|
446
|
+
}
|
|
447
|
+
|
|
448
|
+
/**
|
|
449
|
+
* Get comprehensive statistics
|
|
450
|
+
*/
|
|
451
|
+
getFilterStats() {
|
|
452
|
+
return {
|
|
453
|
+
interceptCount: this.interceptCount,
|
|
454
|
+
contentFilters: this.contentFilters.getFilterStats(),
|
|
455
|
+
toneProcessors: this.toneProcessors.getProcessingStats(),
|
|
456
|
+
recentActions: this.actionLog.slice(-20),
|
|
457
|
+
settings: this.settings,
|
|
458
|
+
topBlockedReasons: this.getTopBlockedReasons(),
|
|
459
|
+
};
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
getTopBlockedReasons() {
|
|
463
|
+
const reasonCounts = {};
|
|
464
|
+
|
|
465
|
+
this.actionLog
|
|
466
|
+
.filter((entry) => entry.action === 'DOCUMENT_INTERCEPT' && !entry.details.allowed)
|
|
467
|
+
.forEach((entry) => {
|
|
468
|
+
const reason = entry.details.reason;
|
|
469
|
+
reasonCounts[reason] = (reasonCounts[reason] || 0) + 1;
|
|
470
|
+
});
|
|
471
|
+
|
|
472
|
+
return Object.entries(reasonCounts)
|
|
473
|
+
.sort(([, a], [, b]) => b - a)
|
|
474
|
+
.slice(0, 5)
|
|
475
|
+
.map(([reason, count]) => ({ reason, count }));
|
|
476
|
+
}
|
|
477
|
+
|
|
478
|
+
/**
|
|
479
|
+
* Update user preferences
|
|
480
|
+
*/
|
|
481
|
+
updatePreferences(preferences) {
|
|
482
|
+
this.settings.userPreferences = { ...this.settings.userPreferences, ...preferences };
|
|
483
|
+
this.saveSettings();
|
|
484
|
+
|
|
485
|
+
// Update processor configurations
|
|
486
|
+
this.contentFilters.updateLimits(this.settings.contentFilters);
|
|
487
|
+
this.toneProcessors.updateConfig(this.settings.toneProcessors);
|
|
488
|
+
}
|
|
489
|
+
|
|
490
|
+
/**
|
|
491
|
+
* Export filter configuration for auditing
|
|
492
|
+
*/
|
|
493
|
+
exportConfiguration() {
|
|
494
|
+
return {
|
|
495
|
+
settings: this.settings,
|
|
496
|
+
stats: this.getFilterStats(),
|
|
497
|
+
contentFiltersConfig: this.contentFilters.exportConfig(),
|
|
498
|
+
toneProcessorsConfig: this.toneProcessors.exportConfig(),
|
|
499
|
+
};
|
|
500
|
+
}
|
|
501
|
+
|
|
502
|
+
/**
|
|
503
|
+
* Reset all filters and logs
|
|
504
|
+
*/
|
|
505
|
+
reset() {
|
|
506
|
+
this.contentFilters.reset();
|
|
507
|
+
this.toneProcessors.reset();
|
|
508
|
+
this.actionLog = [];
|
|
509
|
+
this.interceptCount = 0;
|
|
510
|
+
}
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* CLI command handlers for integration
|
|
514
|
+
*/
|
|
515
|
+
static createCliHandlers(hooks) {
|
|
516
|
+
return {
|
|
517
|
+
'filter-check': (filePath, content) => {
|
|
518
|
+
return hooks.interceptDocumentGeneration(filePath, content);
|
|
519
|
+
},
|
|
520
|
+
|
|
521
|
+
'filter-stats': () => {
|
|
522
|
+
return hooks.getFilterStats();
|
|
523
|
+
},
|
|
524
|
+
|
|
525
|
+
'filter-config': (newConfig) => {
|
|
526
|
+
if (newConfig) {
|
|
527
|
+
hooks.updatePreferences(newConfig);
|
|
528
|
+
return { updated: true, config: hooks.settings };
|
|
529
|
+
}
|
|
530
|
+
return hooks.settings;
|
|
531
|
+
},
|
|
532
|
+
|
|
533
|
+
'filter-reset': () => {
|
|
534
|
+
hooks.reset();
|
|
535
|
+
return { reset: true };
|
|
536
|
+
},
|
|
537
|
+
};
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
|
|
541
|
+
export default FilterIntegrationHooks;
|
|
542
|
+
export { FilterIntegrationHooks };
|