@codebolt/agent 1.2.1 → 2.2.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/README.md +157 -66
- package/dist/{agent.js → builderpattern/agent.js} +2 -2
- package/dist/{followupquestionbuilder.d.ts → builderpattern/followupquestionbuilder.d.ts} +1 -1
- package/dist/{followupquestionbuilder.js → builderpattern/followupquestionbuilder.js} +1 -1
- package/dist/{index.d.ts → builderpattern/index.d.ts} +3 -3
- package/dist/{llmoutputhandler.d.ts → builderpattern/llmoutputhandler.d.ts} +1 -1
- package/dist/{llmoutputhandler.js → builderpattern/llmoutputhandler.js} +7 -7
- package/dist/{promptbuilder.d.ts → builderpattern/promptbuilder.d.ts} +3 -3
- package/dist/{taskInstruction.d.ts → builderpattern/taskInstruction.d.ts} +2 -2
- package/dist/{usermessage.d.ts → builderpattern/usermessage.d.ts} +9 -4
- package/dist/composablepattern/agent.d.ts +169 -0
- package/dist/composablepattern/agent.js +598 -0
- package/dist/composablepattern/codebolt-storage.d.ts +67 -0
- package/dist/composablepattern/codebolt-storage.js +320 -0
- package/dist/composablepattern/document.d.ts +149 -0
- package/dist/composablepattern/document.js +372 -0
- package/dist/composablepattern/examples/codebolt-integration-example.d.ts +12 -0
- package/dist/composablepattern/examples/codebolt-integration-example.js +218 -0
- package/dist/composablepattern/examples/codebolt-storage-example.d.ts +40 -0
- package/dist/composablepattern/examples/codebolt-storage-example.js +223 -0
- package/dist/composablepattern/examples/custom-steps-example.d.ts +20 -0
- package/dist/composablepattern/examples/custom-steps-example.js +455 -0
- package/dist/composablepattern/examples/document-agent.d.ts +17 -0
- package/dist/composablepattern/examples/document-agent.js +107 -0
- package/dist/composablepattern/examples/simple-codebolt-integration.d.ts +8 -0
- package/dist/composablepattern/examples/simple-codebolt-integration.js +164 -0
- package/dist/composablepattern/examples/weather-agent.d.ts +18 -0
- package/dist/composablepattern/examples/weather-agent.js +86 -0
- package/dist/composablepattern/examples/workflow-example.d.ts +12 -0
- package/dist/composablepattern/examples/workflow-example.js +463 -0
- package/dist/composablepattern/index.d.ts +63 -0
- package/dist/composablepattern/index.js +115 -0
- package/dist/composablepattern/memory.d.ts +89 -0
- package/dist/composablepattern/memory.js +141 -0
- package/dist/composablepattern/tool.d.ts +84 -0
- package/dist/composablepattern/tool.js +260 -0
- package/dist/composablepattern/types.d.ts +194 -0
- package/dist/composablepattern/types.js +6 -0
- package/dist/composablepattern/user-context.d.ts +214 -0
- package/dist/composablepattern/user-context.js +275 -0
- package/dist/composablepattern/workflow.d.ts +388 -0
- package/dist/composablepattern/workflow.js +562 -0
- package/dist/local-tools/fileTools.d.ts +26 -0
- package/dist/local-tools/fileTools.js +162 -0
- package/dist/processor/agent/agentStep.d.ts +49 -0
- package/dist/processor/agent/agentStep.js +241 -0
- package/dist/processor/agent/toolExecutor.d.ts +19 -0
- package/dist/processor/agent/toolExecutor.js +90 -0
- package/dist/processor/index.d.ts +7 -0
- package/dist/processor/index.js +36 -0
- package/dist/processor/messageModifiers/baseMessageModifier.d.ts +20 -0
- package/dist/processor/messageModifiers/baseMessageModifier.js +55 -0
- package/dist/processor/processors/baseProcessor.d.ts +14 -0
- package/dist/processor/processors/baseProcessor.js +29 -0
- package/dist/processor/tools/baseTool.d.ts +10 -0
- package/dist/processor/tools/baseTool.js +20 -0
- package/dist/processor/tools/toolList.d.ts +9 -0
- package/dist/processor/tools/toolList.js +22 -0
- package/dist/processor/types/interfaces.d.ts +117 -0
- package/dist/processor/types/interfaces.js +2 -0
- package/dist/processor-pieces/additionalModifiers/argumentProcessorModifier.d.ts +13 -0
- package/dist/processor-pieces/additionalModifiers/argumentProcessorModifier.js +68 -0
- package/dist/processor-pieces/additionalModifiers/atFileProcessorModifier.d.ts +15 -0
- package/dist/processor-pieces/additionalModifiers/atFileProcessorModifier.js +212 -0
- package/dist/processor-pieces/additionalModifiers/chatCompressionModifier.d.ts +19 -0
- package/dist/processor-pieces/additionalModifiers/chatCompressionModifier.js +110 -0
- package/dist/processor-pieces/additionalModifiers/chatRecordingModifier.d.ts +23 -0
- package/dist/processor-pieces/additionalModifiers/chatRecordingModifier.js +173 -0
- package/dist/processor-pieces/additionalModifiers/coreSystemPromptModifier.d.ts +14 -0
- package/dist/processor-pieces/additionalModifiers/coreSystemPromptModifier.js +93 -0
- package/dist/processor-pieces/additionalModifiers/directoryContextModifier.d.ts +30 -0
- package/dist/processor-pieces/additionalModifiers/directoryContextModifier.js +330 -0
- package/dist/processor-pieces/additionalModifiers/environmentContextModifier.d.ts +26 -0
- package/dist/processor-pieces/additionalModifiers/environmentContextModifier.js +269 -0
- package/dist/processor-pieces/additionalModifiers/fallbackHandlerModifier.d.ts +38 -0
- package/dist/processor-pieces/additionalModifiers/fallbackHandlerModifier.js +217 -0
- package/dist/processor-pieces/additionalModifiers/ideContextModifier.d.ts +34 -0
- package/dist/processor-pieces/additionalModifiers/ideContextModifier.js +147 -0
- package/dist/processor-pieces/additionalModifiers/index.d.ts +12 -0
- package/dist/processor-pieces/additionalModifiers/index.js +28 -0
- package/dist/processor-pieces/additionalModifiers/loopDetectionModifier.d.ts +29 -0
- package/dist/processor-pieces/additionalModifiers/loopDetectionModifier.js +155 -0
- package/dist/processor-pieces/additionalModifiers/memoryImportModifier.d.ts +15 -0
- package/dist/processor-pieces/additionalModifiers/memoryImportModifier.js +129 -0
- package/dist/processor-pieces/additionalModifiers/shellProcessorModifier.d.ts +25 -0
- package/dist/processor-pieces/additionalModifiers/shellProcessorModifier.js +169 -0
- package/dist/processor-pieces/additionalModifiers/toolInjectionModifier.d.ts +20 -0
- package/dist/processor-pieces/additionalModifiers/toolInjectionModifier.js +152 -0
- package/dist/processor-pieces/base/baseMessageModifier.d.ts +12 -0
- package/dist/processor-pieces/base/baseMessageModifier.js +15 -0
- package/dist/processor-pieces/base/basePostInferenceProcessor.d.ts +13 -0
- package/dist/processor-pieces/base/basePostInferenceProcessor.js +18 -0
- package/dist/processor-pieces/base/basePostToolCallProcessor.d.ts +15 -0
- package/dist/processor-pieces/base/basePostToolCallProcessor.js +25 -0
- package/dist/processor-pieces/base/basePreInferenceProcessor.d.ts +12 -0
- package/dist/processor-pieces/base/basePreInferenceProcessor.js +17 -0
- package/dist/processor-pieces/base/basePreToolCallProcessor.d.ts +18 -0
- package/dist/processor-pieces/base/basePreToolCallProcessor.js +66 -0
- package/dist/processor-pieces/base/index.d.ts +9 -0
- package/dist/processor-pieces/base/index.js +18 -0
- package/dist/processor-pieces/index.d.ts +1 -0
- package/dist/processor-pieces/index.js +59 -0
- package/dist/processor-pieces/messageModifiers/addCurrentDirectoryRootFilesModifier.d.ts +7 -0
- package/dist/processor-pieces/messageModifiers/addCurrentDirectoryRootFilesModifier.js +93 -0
- package/dist/processor-pieces/messageModifiers/addToolsListMessageModifier.d.ts +31 -0
- package/dist/processor-pieces/messageModifiers/addToolsListMessageModifier.js +145 -0
- package/dist/processor-pieces/messageModifiers/advancedSystemInstructionMessageModifier.d.ts +9 -0
- package/dist/processor-pieces/messageModifiers/advancedSystemInstructionMessageModifier.js +77 -0
- package/dist/processor-pieces/messageModifiers/argumentProcessorModifier.d.ts +13 -0
- package/dist/processor-pieces/messageModifiers/argumentProcessorModifier.js +68 -0
- package/dist/processor-pieces/messageModifiers/atFileProcessorModifier.d.ts +25 -0
- package/dist/processor-pieces/messageModifiers/atFileProcessorModifier.js +453 -0
- package/dist/processor-pieces/messageModifiers/baseContextMessageModifier.d.ts +7 -0
- package/dist/processor-pieces/messageModifiers/baseContextMessageModifier.js +67 -0
- package/dist/processor-pieces/messageModifiers/baseSystemInstructionMessageModifier.d.ts +9 -0
- package/dist/processor-pieces/messageModifiers/baseSystemInstructionMessageModifier.js +90 -0
- package/dist/processor-pieces/messageModifiers/chatCompressionModifier.d.ts +19 -0
- package/dist/processor-pieces/messageModifiers/chatCompressionModifier.js +110 -0
- package/dist/processor-pieces/messageModifiers/chatHistoryMessageModifier.d.ts +18 -0
- package/dist/processor-pieces/messageModifiers/chatHistoryMessageModifier.example.d.ts +20 -0
- package/dist/processor-pieces/messageModifiers/chatHistoryMessageModifier.example.js +124 -0
- package/dist/processor-pieces/messageModifiers/chatHistoryMessageModifier.js +104 -0
- package/dist/processor-pieces/messageModifiers/chatRecordingModifier.d.ts +23 -0
- package/dist/processor-pieces/messageModifiers/chatRecordingModifier.js +173 -0
- package/dist/processor-pieces/messageModifiers/coreSystemPromptModifier.d.ts +14 -0
- package/dist/processor-pieces/messageModifiers/coreSystemPromptModifier.js +130 -0
- package/dist/processor-pieces/messageModifiers/directoryContextModifier.d.ts +36 -0
- package/dist/processor-pieces/messageModifiers/directoryContextModifier.js +418 -0
- package/dist/processor-pieces/messageModifiers/environmentContext.d.ts +41 -0
- package/dist/processor-pieces/messageModifiers/environmentContext.js +355 -0
- package/dist/processor-pieces/messageModifiers/environmentContextModifier.d.ts +26 -0
- package/dist/processor-pieces/messageModifiers/environmentContextModifier.js +260 -0
- package/dist/processor-pieces/messageModifiers/handleUrlMessageModifier.d.ts +13 -0
- package/dist/processor-pieces/messageModifiers/handleUrlMessageModifier.js +59 -0
- package/dist/processor-pieces/messageModifiers/ideContextModifier.d.ts +34 -0
- package/dist/processor-pieces/messageModifiers/ideContextModifier.js +157 -0
- package/dist/processor-pieces/messageModifiers/imageAttachmentMessageModifier.d.ts +19 -0
- package/dist/processor-pieces/messageModifiers/imageAttachmentMessageModifier.js +221 -0
- package/dist/processor-pieces/messageModifiers/index.d.ts +11 -0
- package/dist/processor-pieces/messageModifiers/index.js +26 -0
- package/dist/processor-pieces/messageModifiers/memoryImportModifier.d.ts +15 -0
- package/dist/processor-pieces/messageModifiers/memoryImportModifier.js +129 -0
- package/dist/processor-pieces/messageModifiers/mentionedFilesModifier.d.ts +23 -0
- package/dist/processor-pieces/messageModifiers/mentionedFilesModifier.js +207 -0
- package/dist/processor-pieces/messageModifiers/simpleMessageModifier.d.ts +7 -0
- package/dist/processor-pieces/messageModifiers/simpleMessageModifier.js +26 -0
- package/dist/processor-pieces/messageModifiers/toolInjectionModifier.d.ts +20 -0
- package/dist/processor-pieces/messageModifiers/toolInjectionModifier.js +152 -0
- package/dist/processor-pieces/messageModifiers/workingDirectoryMessageModifier.d.ts +38 -0
- package/dist/processor-pieces/messageModifiers/workingDirectoryMessageModifier.js +392 -0
- package/dist/processor-pieces/postInference/llmOutputValidityProcessor.d.ts +1 -0
- package/dist/processor-pieces/postInference/llmOutputValidityProcessor.js +2 -0
- package/dist/processor-pieces/postInferenceProcessors/checkForNoToolCall.d.ts +7 -0
- package/dist/processor-pieces/postInferenceProcessors/checkForNoToolCall.js +24 -0
- package/dist/processor-pieces/postInferenceProcessors/loopDetectionModifier.d.ts +29 -0
- package/dist/processor-pieces/postInferenceProcessors/loopDetectionModifier.js +174 -0
- package/dist/processor-pieces/postToolCall/advancedLoopDetectionProcessor.d.ts +41 -0
- package/dist/processor-pieces/postToolCall/advancedLoopDetectionProcessor.js +197 -0
- package/dist/processor-pieces/postToolCall/chatCompressionProcessor.d.ts +26 -0
- package/dist/processor-pieces/postToolCall/chatCompressionProcessor.js +90 -0
- package/dist/processor-pieces/postToolCall/chatRecordingProcessor.d.ts +81 -0
- package/dist/processor-pieces/postToolCall/chatRecordingProcessor.js +329 -0
- package/dist/processor-pieces/postToolCall/contextManagementProcessor.d.ts +40 -0
- package/dist/processor-pieces/postToolCall/contextManagementProcessor.js +272 -0
- package/dist/processor-pieces/postToolCall/conversationCompactorProcessor.d.ts +49 -0
- package/dist/processor-pieces/postToolCall/conversationCompactorProcessor.js +291 -0
- package/dist/processor-pieces/postToolCall/conversationContinuityProcessor.d.ts +49 -0
- package/dist/processor-pieces/postToolCall/conversationContinuityProcessor.js +293 -0
- package/dist/processor-pieces/postToolCall/followUpConversationProcessor.d.ts +47 -0
- package/dist/processor-pieces/postToolCall/followUpConversationProcessor.js +249 -0
- package/dist/processor-pieces/postToolCall/loopDetectionProcessor.d.ts +30 -0
- package/dist/processor-pieces/postToolCall/loopDetectionProcessor.js +137 -0
- package/dist/processor-pieces/postToolCall/responseValidationProcessor.d.ts +30 -0
- package/dist/processor-pieces/postToolCall/responseValidationProcessor.js +228 -0
- package/dist/processor-pieces/postToolCall/telemetryProcessor.d.ts +99 -0
- package/dist/processor-pieces/postToolCall/telemetryProcessor.js +278 -0
- package/dist/processor-pieces/postToolCall/tokenManagementProcessor.d.ts +37 -0
- package/dist/processor-pieces/postToolCall/tokenManagementProcessor.js +178 -0
- package/dist/processor-pieces/postToolCall/toolExecutionProcessor.d.ts +43 -0
- package/dist/processor-pieces/postToolCall/toolExecutionProcessor.js +207 -0
- package/dist/processor-pieces/postToolCallProcessors/index.d.ts +1 -0
- package/dist/processor-pieces/postToolCallProcessors/index.js +2 -0
- package/dist/processor-pieces/postToolCallProcessors/shellProcessorModifier.d.ts +25 -0
- package/dist/processor-pieces/postToolCallProcessors/shellProcessorModifier.js +225 -0
- package/dist/processor-pieces/preInference/conversationCompactorProcessor.d.ts +52 -0
- package/dist/processor-pieces/preInference/conversationCompactorProcessor.js +264 -0
- package/dist/processor-pieces/preInference/conversationContinuityProcessor.d.ts +49 -0
- package/dist/processor-pieces/preInference/conversationContinuityProcessor.js +293 -0
- package/dist/processor-pieces/preInferenceProcessors/chatCompressionModifier.d.ts +35 -0
- package/dist/processor-pieces/preInferenceProcessors/chatCompressionModifier.js +255 -0
- package/dist/processor-pieces/preInferenceProcessors/conversationCompaction.d.ts +7 -0
- package/dist/processor-pieces/preInferenceProcessors/conversationCompaction.js +31 -0
- package/dist/processor-pieces/preInferenceProcessors/index.d.ts +1 -0
- package/dist/processor-pieces/preInferenceProcessors/index.js +2 -0
- package/dist/processor-pieces/preToolCall/index.d.ts +9 -0
- package/dist/processor-pieces/preToolCall/index.js +18 -0
- package/dist/processor-pieces/preToolCall/localToolInterceptorProcessor.d.ts +58 -0
- package/dist/processor-pieces/preToolCall/localToolInterceptorProcessor.js +444 -0
- package/dist/processor-pieces/preToolCall/toolParameterModifierProcessor.d.ts +44 -0
- package/dist/processor-pieces/preToolCall/toolParameterModifierProcessor.js +367 -0
- package/dist/processor-pieces/preToolCall/toolValidationProcessor.d.ts +58 -0
- package/dist/processor-pieces/preToolCall/toolValidationProcessor.js +391 -0
- package/dist/processor-pieces/pretoolCallProcessors/index.d.ts +1 -0
- package/dist/processor-pieces/pretoolCallProcessors/index.js +2 -0
- package/dist/processor-pieces/processors/advancedLoopDetectionProcessor.d.ts +41 -0
- package/dist/processor-pieces/processors/advancedLoopDetectionProcessor.js +197 -0
- package/dist/processor-pieces/processors/chatCompressionProcessor.d.ts +26 -0
- package/dist/processor-pieces/processors/chatCompressionProcessor.js +90 -0
- package/dist/processor-pieces/processors/chatRecordingProcessor.d.ts +81 -0
- package/dist/processor-pieces/processors/chatRecordingProcessor.js +329 -0
- package/dist/processor-pieces/processors/contextManagementProcessor.d.ts +40 -0
- package/dist/processor-pieces/processors/contextManagementProcessor.js +305 -0
- package/dist/processor-pieces/processors/loopDetectionProcessor.d.ts +30 -0
- package/dist/processor-pieces/processors/loopDetectionProcessor.js +137 -0
- package/dist/processor-pieces/processors/responseValidationProcessor.d.ts +30 -0
- package/dist/processor-pieces/processors/responseValidationProcessor.js +228 -0
- package/dist/processor-pieces/processors/telemetryProcessor.d.ts +99 -0
- package/dist/processor-pieces/processors/telemetryProcessor.js +311 -0
- package/dist/processor-pieces/processors/tokenManagementProcessor.d.ts +37 -0
- package/dist/processor-pieces/processors/tokenManagementProcessor.js +178 -0
- package/dist/processor-pieces/processors/toolExecutionProcessor.d.ts +43 -0
- package/dist/processor-pieces/processors/toolExecutionProcessor.js +207 -0
- package/dist/processor-pieces/tools/fileTools.d.ts +26 -0
- package/dist/processor-pieces/tools/fileTools.js +162 -0
- package/dist/processor-pieces/utils/messageModifierHelper.d.ts +4 -0
- package/dist/processor-pieces/utils/messageModifierHelper.js +58 -0
- package/dist/types/commonTypes.d.ts +4 -0
- package/dist/types/processorTypes.d.ts +67 -0
- package/dist/types/processorTypes.js +58 -0
- package/dist/unified/agent/agent.d.ts +17 -0
- package/dist/unified/agent/agent.js +79 -0
- package/dist/unified/agent/team.d.ts +2 -0
- package/dist/unified/agent/team.js +6 -0
- package/dist/unified/agent/tool.d.ts +99 -0
- package/dist/unified/agent/tool.js +440 -0
- package/dist/unified/agent/tools.d.ts +44 -0
- package/dist/unified/agent/tools.js +487 -0
- package/dist/unified/agent/workflow.d.ts +24 -0
- package/dist/unified/agent/workflow.js +275 -0
- package/dist/unified/agent/workflowControls.d.ts +11 -0
- package/dist/unified/agent/workflowControls.js +20 -0
- package/dist/unified/agent/workflowSteps.d.ts +63 -0
- package/dist/unified/agent/workflowSteps.js +284 -0
- package/dist/unified/base/agentStep.d.ts +32 -0
- package/dist/unified/base/agentStep.js +96 -0
- package/dist/unified/base/create/createInitialPromptGenerators.d.ts +5 -0
- package/dist/unified/base/create/createInitialPromptGenerators.js +17 -0
- package/dist/unified/base/index.d.ts +5 -0
- package/dist/unified/base/index.js +13 -0
- package/dist/unified/base/initialPromptGenerator.d.ts +48 -0
- package/dist/unified/base/initialPromptGenerator.js +118 -0
- package/dist/unified/base/responseExecutor.d.ts +36 -0
- package/dist/unified/base/responseExecutor.js +283 -0
- package/dist/unified/examples/agentExample.d.ts +46 -0
- package/dist/unified/examples/agentExample.js +464 -0
- package/dist/unified/examples/documentationPatternExample.d.ts +10 -0
- package/dist/unified/examples/documentationPatternExample.js +385 -0
- package/dist/unified/examples/followUpProcessorsExample.d.ts +45 -0
- package/dist/unified/examples/followUpProcessorsExample.js +311 -0
- package/dist/unified/examples/orchestratorExample.d.ts +16 -0
- package/dist/unified/examples/orchestratorExample.js +415 -0
- package/dist/unified/examples/preToolCallProcessorsExample.d.ts +36 -0
- package/dist/unified/examples/preToolCallProcessorsExample.js +458 -0
- package/dist/unified/examples/workflowExample.d.ts +12 -0
- package/dist/unified/examples/workflowExample.js +497 -0
- package/dist/unified/index.d.ts +18 -0
- package/dist/unified/index.js +42 -0
- package/dist/unified/orchestrator/orchestrator.d.ts +260 -0
- package/dist/unified/orchestrator/orchestrator.js +519 -0
- package/dist/unified/team/team.d.ts +1 -0
- package/dist/unified/team/team.js +2 -0
- package/dist/unified/types/libTypes.d.ts +378 -0
- package/dist/unified/types/libTypes.js +6 -0
- package/dist/unified/types/types.d.ts +212 -0
- package/dist/unified/types/types.js +43 -0
- package/dist/unified/utils/utils.d.ts +40 -0
- package/dist/unified/utils/utils.js +219 -0
- package/package.json +35 -13
- /package/dist/{agent.d.ts → builderpattern/agent.d.ts} +0 -0
- /package/dist/{index.js → builderpattern/index.js} +0 -0
- /package/dist/{promptbuilder.js → builderpattern/promptbuilder.js} +0 -0
- /package/dist/{systemprompt.d.ts → builderpattern/systemprompt.d.ts} +0 -0
- /package/dist/{systemprompt.js → builderpattern/systemprompt.js} +0 -0
- /package/dist/{taskInstruction.js → builderpattern/taskInstruction.js} +0 -0
- /package/dist/{usermessage.js → builderpattern/usermessage.js} +0 -0
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ToolValidationProcessor = void 0;
|
|
4
|
+
const processor_1 = require("../../processor");
|
|
5
|
+
/**
|
|
6
|
+
* Processor that validates tool calls before execution, checking parameters,
|
|
7
|
+
* security constraints, and tool availability.
|
|
8
|
+
*/
|
|
9
|
+
class ToolValidationProcessor extends processor_1.BaseProcessor {
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
super(options);
|
|
12
|
+
this.enableParameterValidation = options.enableParameterValidation !== false;
|
|
13
|
+
this.enableSecurityValidation = options.enableSecurityValidation !== false;
|
|
14
|
+
this.enableTypeValidation = options.enableTypeValidation !== false;
|
|
15
|
+
this.strictMode = options.strictMode || false;
|
|
16
|
+
this.allowedTools = new Set(options.allowedTools || []);
|
|
17
|
+
this.blockedTools = new Set(options.blockedTools || []);
|
|
18
|
+
this.maxParameterSize = options.maxParameterSize || 1024 * 1024; // 1MB
|
|
19
|
+
this.enableLogging = options.enableLogging !== false;
|
|
20
|
+
}
|
|
21
|
+
async processInput(input) {
|
|
22
|
+
var _a;
|
|
23
|
+
try {
|
|
24
|
+
const { message, context } = input;
|
|
25
|
+
// Check if this is a pre-tool call processing
|
|
26
|
+
if (!(context === null || context === void 0 ? void 0 : context.preToolCallProcessing)) {
|
|
27
|
+
return [this.createEvent('ToolValidationSkipped', {
|
|
28
|
+
reason: 'Not a pre-tool call processing context'
|
|
29
|
+
})];
|
|
30
|
+
}
|
|
31
|
+
const toolName = context.toolName;
|
|
32
|
+
const toolInput = context.toolInput;
|
|
33
|
+
const toolUseId = context.toolUseId;
|
|
34
|
+
// Perform validation
|
|
35
|
+
const validationResult = await this.validateTool(toolName, toolInput, context);
|
|
36
|
+
if (!validationResult.isValid) {
|
|
37
|
+
// Tool validation failed - intercept and return error
|
|
38
|
+
const errorMessage = this.formatValidationErrors(validationResult);
|
|
39
|
+
return [
|
|
40
|
+
this.createEvent('ToolValidationFailed', validationResult),
|
|
41
|
+
this.createEvent('ToolIntercepted', {
|
|
42
|
+
result: errorMessage,
|
|
43
|
+
toolName,
|
|
44
|
+
userRejected: false,
|
|
45
|
+
validationFailed: true
|
|
46
|
+
})
|
|
47
|
+
];
|
|
48
|
+
}
|
|
49
|
+
// Validation passed
|
|
50
|
+
return [
|
|
51
|
+
this.createEvent('ToolValidationPassed', validationResult)
|
|
52
|
+
];
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
console.error('Error in ToolValidationProcessor:', error);
|
|
56
|
+
return [this.createEvent('ToolValidationError', {
|
|
57
|
+
error: error instanceof Error ? error.message : String(error),
|
|
58
|
+
toolName: (_a = input.context) === null || _a === void 0 ? void 0 : _a.toolName
|
|
59
|
+
})];
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async validateTool(toolName, toolInput, context) {
|
|
63
|
+
const validationResult = {
|
|
64
|
+
toolName,
|
|
65
|
+
isValid: true,
|
|
66
|
+
validationErrors: [],
|
|
67
|
+
validationWarnings: [],
|
|
68
|
+
parameterValidation: {
|
|
69
|
+
required: [],
|
|
70
|
+
missing: [],
|
|
71
|
+
invalid: []
|
|
72
|
+
},
|
|
73
|
+
securityChecks: {
|
|
74
|
+
passed: true,
|
|
75
|
+
issues: []
|
|
76
|
+
}
|
|
77
|
+
};
|
|
78
|
+
// Tool availability validation
|
|
79
|
+
if (!this.validateToolAvailability(toolName, validationResult)) {
|
|
80
|
+
validationResult.isValid = false;
|
|
81
|
+
}
|
|
82
|
+
// Parameter validation
|
|
83
|
+
if (this.enableParameterValidation) {
|
|
84
|
+
if (!this.validateParameters(toolName, toolInput, validationResult)) {
|
|
85
|
+
validationResult.isValid = false;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Security validation
|
|
89
|
+
if (this.enableSecurityValidation) {
|
|
90
|
+
if (!this.validateSecurity(toolName, toolInput, validationResult)) {
|
|
91
|
+
validationResult.isValid = false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Type validation
|
|
95
|
+
if (this.enableTypeValidation) {
|
|
96
|
+
if (!this.validateTypes(toolName, toolInput, validationResult)) {
|
|
97
|
+
validationResult.isValid = false;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Size validation
|
|
101
|
+
if (!this.validateSize(toolInput, validationResult)) {
|
|
102
|
+
validationResult.isValid = false;
|
|
103
|
+
}
|
|
104
|
+
return validationResult;
|
|
105
|
+
}
|
|
106
|
+
validateToolAvailability(toolName, result) {
|
|
107
|
+
let isValid = true;
|
|
108
|
+
// Check if tool is explicitly blocked
|
|
109
|
+
if (this.blockedTools.has(toolName)) {
|
|
110
|
+
result.validationErrors.push(`Tool '${toolName}' is blocked and cannot be executed`);
|
|
111
|
+
isValid = false;
|
|
112
|
+
}
|
|
113
|
+
// Check if tool is in allowed list (if allowlist is configured)
|
|
114
|
+
if (this.allowedTools.size > 0 && !this.allowedTools.has(toolName)) {
|
|
115
|
+
result.validationErrors.push(`Tool '${toolName}' is not in the allowed tools list`);
|
|
116
|
+
isValid = false;
|
|
117
|
+
}
|
|
118
|
+
// Check for dangerous tool patterns
|
|
119
|
+
const dangerousPatterns = [
|
|
120
|
+
/^(rm|del|delete)$/i,
|
|
121
|
+
/^(format|fdisk)$/i,
|
|
122
|
+
/^(sudo|su)$/i,
|
|
123
|
+
/^(chmod|chown).*777/i,
|
|
124
|
+
/eval|exec|system/i
|
|
125
|
+
];
|
|
126
|
+
if (dangerousPatterns.some(pattern => pattern.test(toolName))) {
|
|
127
|
+
result.validationWarnings.push(`Tool '${toolName}' matches potentially dangerous pattern`);
|
|
128
|
+
if (this.strictMode) {
|
|
129
|
+
result.validationErrors.push(`Tool '${toolName}' is considered dangerous in strict mode`);
|
|
130
|
+
isValid = false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return isValid;
|
|
134
|
+
}
|
|
135
|
+
validateParameters(toolName, toolInput, result) {
|
|
136
|
+
let isValid = true;
|
|
137
|
+
// Get expected parameters for known tools
|
|
138
|
+
const expectedParams = this.getExpectedParameters(toolName);
|
|
139
|
+
if (expectedParams) {
|
|
140
|
+
result.parameterValidation.required = expectedParams.required || [];
|
|
141
|
+
// Check required parameters
|
|
142
|
+
for (const requiredParam of expectedParams.required || []) {
|
|
143
|
+
if (!toolInput || !(requiredParam in toolInput)) {
|
|
144
|
+
result.parameterValidation.missing.push(requiredParam);
|
|
145
|
+
result.validationErrors.push(`Required parameter '${requiredParam}' is missing for tool '${toolName}'`);
|
|
146
|
+
isValid = false;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
// Check parameter types
|
|
150
|
+
if (expectedParams.types && toolInput) {
|
|
151
|
+
for (const [paramName, expectedType] of Object.entries(expectedParams.types)) {
|
|
152
|
+
if (paramName in toolInput) {
|
|
153
|
+
const actualType = typeof toolInput[paramName];
|
|
154
|
+
if (actualType !== expectedType) {
|
|
155
|
+
result.parameterValidation.invalid.push(paramName);
|
|
156
|
+
result.validationErrors.push(`Parameter '${paramName}' should be of type '${expectedType}' but got '${actualType}'`);
|
|
157
|
+
isValid = false;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
// Check for unexpected parameters in strict mode
|
|
163
|
+
if (this.strictMode && expectedParams.allowed && toolInput) {
|
|
164
|
+
for (const paramName of Object.keys(toolInput)) {
|
|
165
|
+
if (!expectedParams.allowed.includes(paramName)) {
|
|
166
|
+
result.validationWarnings.push(`Unexpected parameter '${paramName}' for tool '${toolName}'`);
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
return isValid;
|
|
172
|
+
}
|
|
173
|
+
validateSecurity(toolName, toolInput, result) {
|
|
174
|
+
let isValid = true;
|
|
175
|
+
// Check for injection patterns in parameters
|
|
176
|
+
if (toolInput && typeof toolInput === 'object') {
|
|
177
|
+
for (const [key, value] of Object.entries(toolInput)) {
|
|
178
|
+
if (typeof value === 'string') {
|
|
179
|
+
// SQL injection patterns
|
|
180
|
+
const sqlInjectionPatterns = [
|
|
181
|
+
/('|\\'|;|\\;|--|\s*or\s+|union\s+select)/i,
|
|
182
|
+
/(drop\s+table|delete\s+from|insert\s+into)/i
|
|
183
|
+
];
|
|
184
|
+
// Command injection patterns
|
|
185
|
+
const commandInjectionPatterns = [
|
|
186
|
+
/[;&|`$(){}[\]]/,
|
|
187
|
+
/(rm\s+-rf)|(sudo\s+)|(chmod\s+)/i
|
|
188
|
+
];
|
|
189
|
+
// Path traversal patterns
|
|
190
|
+
const pathTraversalPatterns = [
|
|
191
|
+
/\.\.\//,
|
|
192
|
+
/\.\.\\/, // fixed: properly closed regex for Windows path traversal
|
|
193
|
+
/%2[eE]%2[eE]%2[fF]/i
|
|
194
|
+
];
|
|
195
|
+
const allPatterns = [
|
|
196
|
+
...sqlInjectionPatterns,
|
|
197
|
+
...commandInjectionPatterns,
|
|
198
|
+
...pathTraversalPatterns
|
|
199
|
+
];
|
|
200
|
+
for (const pattern of allPatterns) {
|
|
201
|
+
if (pattern.test(value)) {
|
|
202
|
+
result.securityChecks.issues.push(`Potential security issue in parameter '${key}': suspicious pattern detected`);
|
|
203
|
+
result.securityChecks.passed = false;
|
|
204
|
+
if (this.strictMode) {
|
|
205
|
+
result.validationErrors.push(`Security validation failed for parameter '${key}' in tool '${toolName}'`);
|
|
206
|
+
isValid = false;
|
|
207
|
+
}
|
|
208
|
+
else {
|
|
209
|
+
result.validationWarnings.push(`Security warning for parameter '${key}' in tool '${toolName}'`);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Check for sensitive file operations
|
|
217
|
+
if (toolName.includes('file') || toolName.includes('read') || toolName.includes('write')) {
|
|
218
|
+
const sensitiveFiles = [
|
|
219
|
+
'/etc/passwd',
|
|
220
|
+
'/etc/shadow',
|
|
221
|
+
'~/.ssh/',
|
|
222
|
+
'.env',
|
|
223
|
+
'config.json',
|
|
224
|
+
'secrets.json'
|
|
225
|
+
];
|
|
226
|
+
const filePath = (toolInput === null || toolInput === void 0 ? void 0 : toolInput.filePath) || (toolInput === null || toolInput === void 0 ? void 0 : toolInput.path) || (toolInput === null || toolInput === void 0 ? void 0 : toolInput.file);
|
|
227
|
+
if (typeof filePath === 'string') {
|
|
228
|
+
for (const sensitiveFile of sensitiveFiles) {
|
|
229
|
+
if (filePath.includes(sensitiveFile)) {
|
|
230
|
+
result.securityChecks.issues.push(`Attempt to access sensitive file: ${filePath}`);
|
|
231
|
+
result.securityChecks.passed = false;
|
|
232
|
+
if (this.strictMode) {
|
|
233
|
+
result.validationErrors.push(`Access to sensitive file '${filePath}' is not allowed`);
|
|
234
|
+
isValid = false;
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
result.validationWarnings.push(`Warning: accessing potentially sensitive file '${filePath}'`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
return isValid;
|
|
244
|
+
}
|
|
245
|
+
validateTypes(toolName, toolInput, result) {
|
|
246
|
+
let isValid = true;
|
|
247
|
+
if (toolInput === null || toolInput === undefined) {
|
|
248
|
+
if (this.strictMode) {
|
|
249
|
+
result.validationErrors.push(`Tool input cannot be null or undefined for '${toolName}'`);
|
|
250
|
+
isValid = false;
|
|
251
|
+
}
|
|
252
|
+
return isValid;
|
|
253
|
+
}
|
|
254
|
+
// Validate input is serializable
|
|
255
|
+
try {
|
|
256
|
+
JSON.stringify(toolInput);
|
|
257
|
+
}
|
|
258
|
+
catch (error) {
|
|
259
|
+
result.validationErrors.push(`Tool input for '${toolName}' is not serializable`);
|
|
260
|
+
isValid = false;
|
|
261
|
+
}
|
|
262
|
+
// Check for circular references
|
|
263
|
+
if (typeof toolInput === 'object' && this.hasCircularReference(toolInput)) {
|
|
264
|
+
result.validationErrors.push(`Tool input for '${toolName}' contains circular references`);
|
|
265
|
+
isValid = false;
|
|
266
|
+
}
|
|
267
|
+
return isValid;
|
|
268
|
+
}
|
|
269
|
+
validateSize(toolInput, result) {
|
|
270
|
+
try {
|
|
271
|
+
const serialized = JSON.stringify(toolInput);
|
|
272
|
+
const size = new Blob([serialized]).size;
|
|
273
|
+
if (size > this.maxParameterSize) {
|
|
274
|
+
result.validationErrors.push(`Tool input size (${size} bytes) exceeds maximum allowed size (${this.maxParameterSize} bytes)`);
|
|
275
|
+
return false;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
catch (error) {
|
|
279
|
+
result.validationWarnings.push('Could not determine tool input size');
|
|
280
|
+
}
|
|
281
|
+
return true;
|
|
282
|
+
}
|
|
283
|
+
getExpectedParameters(toolName) {
|
|
284
|
+
// Define expected parameters for common tools
|
|
285
|
+
const toolSchemas = {
|
|
286
|
+
'file_read': {
|
|
287
|
+
required: ['filePath'],
|
|
288
|
+
types: { filePath: 'string' },
|
|
289
|
+
allowed: ['filePath', 'encoding']
|
|
290
|
+
},
|
|
291
|
+
'file_write': {
|
|
292
|
+
required: ['filePath', 'content'],
|
|
293
|
+
types: { filePath: 'string', content: 'string' },
|
|
294
|
+
allowed: ['filePath', 'content', 'encoding', 'append']
|
|
295
|
+
},
|
|
296
|
+
'execute_command': {
|
|
297
|
+
required: ['command'],
|
|
298
|
+
types: { command: 'string' },
|
|
299
|
+
allowed: ['command', 'args', 'cwd', 'timeout']
|
|
300
|
+
},
|
|
301
|
+
'http_request': {
|
|
302
|
+
required: ['url'],
|
|
303
|
+
types: { url: 'string' },
|
|
304
|
+
allowed: ['url', 'method', 'headers', 'body', 'timeout']
|
|
305
|
+
},
|
|
306
|
+
'database_query': {
|
|
307
|
+
required: ['query'],
|
|
308
|
+
types: { query: 'string' },
|
|
309
|
+
allowed: ['query', 'parameters', 'database']
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
return toolSchemas[toolName] || null;
|
|
313
|
+
}
|
|
314
|
+
hasCircularReference(obj, seen = new WeakSet()) {
|
|
315
|
+
if (obj === null || typeof obj !== 'object') {
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
if (seen.has(obj)) {
|
|
319
|
+
return true;
|
|
320
|
+
}
|
|
321
|
+
seen.add(obj);
|
|
322
|
+
for (const value of Object.values(obj)) {
|
|
323
|
+
if (this.hasCircularReference(value, seen)) {
|
|
324
|
+
return true;
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
seen.delete(obj);
|
|
328
|
+
return false;
|
|
329
|
+
}
|
|
330
|
+
formatValidationErrors(result) {
|
|
331
|
+
const errors = result.validationErrors;
|
|
332
|
+
const warnings = result.validationWarnings;
|
|
333
|
+
let message = `Tool validation failed for '${result.toolName}':\n`;
|
|
334
|
+
if (errors.length > 0) {
|
|
335
|
+
message += '\nErrors:\n' + errors.map(error => `- ${error}`).join('\n');
|
|
336
|
+
}
|
|
337
|
+
if (warnings.length > 0) {
|
|
338
|
+
message += '\nWarnings:\n' + warnings.map(warning => `- ${warning}`).join('\n');
|
|
339
|
+
}
|
|
340
|
+
if (result.parameterValidation.missing.length > 0) {
|
|
341
|
+
message += `\nMissing required parameters: ${result.parameterValidation.missing.join(', ')}`;
|
|
342
|
+
}
|
|
343
|
+
if (result.securityChecks.issues.length > 0) {
|
|
344
|
+
message += '\nSecurity issues:\n' + result.securityChecks.issues.map(issue => `- ${issue}`).join('\n');
|
|
345
|
+
}
|
|
346
|
+
return message;
|
|
347
|
+
}
|
|
348
|
+
// Public methods for configuration
|
|
349
|
+
addAllowedTool(toolName) {
|
|
350
|
+
this.allowedTools.add(toolName);
|
|
351
|
+
if (this.enableLogging) {
|
|
352
|
+
console.log(`[ToolValidation] Added allowed tool: ${toolName}`);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
removeAllowedTool(toolName) {
|
|
356
|
+
const removed = this.allowedTools.delete(toolName);
|
|
357
|
+
if (removed && this.enableLogging) {
|
|
358
|
+
console.log(`[ToolValidation] Removed allowed tool: ${toolName}`);
|
|
359
|
+
}
|
|
360
|
+
return removed;
|
|
361
|
+
}
|
|
362
|
+
addBlockedTool(toolName) {
|
|
363
|
+
this.blockedTools.add(toolName);
|
|
364
|
+
if (this.enableLogging) {
|
|
365
|
+
console.log(`[ToolValidation] Added blocked tool: ${toolName}`);
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
removeBlockedTool(toolName) {
|
|
369
|
+
const removed = this.blockedTools.delete(toolName);
|
|
370
|
+
if (removed && this.enableLogging) {
|
|
371
|
+
console.log(`[ToolValidation] Removed blocked tool: ${toolName}`);
|
|
372
|
+
}
|
|
373
|
+
return removed;
|
|
374
|
+
}
|
|
375
|
+
getAllowedTools() {
|
|
376
|
+
return Array.from(this.allowedTools);
|
|
377
|
+
}
|
|
378
|
+
getBlockedTools() {
|
|
379
|
+
return Array.from(this.blockedTools);
|
|
380
|
+
}
|
|
381
|
+
isToolAllowed(toolName) {
|
|
382
|
+
if (this.blockedTools.has(toolName)) {
|
|
383
|
+
return false;
|
|
384
|
+
}
|
|
385
|
+
if (this.allowedTools.size > 0) {
|
|
386
|
+
return this.allowedTools.has(toolName);
|
|
387
|
+
}
|
|
388
|
+
return true;
|
|
389
|
+
}
|
|
390
|
+
}
|
|
391
|
+
exports.ToolValidationProcessor = ToolValidationProcessor;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import { BaseProcessor, ProcessorInput, ProcessorOutput } from '../../processor';
|
|
2
|
+
export interface AdvancedLoopDetectionProcessorOptions {
|
|
3
|
+
toolCallThreshold?: number;
|
|
4
|
+
contentLoopThreshold?: number;
|
|
5
|
+
contentChunkSize?: number;
|
|
6
|
+
maxHistoryLength?: number;
|
|
7
|
+
enableLLMDetection?: boolean;
|
|
8
|
+
llmCheckAfterTurns?: number;
|
|
9
|
+
defaultLLMCheckInterval?: number;
|
|
10
|
+
}
|
|
11
|
+
export declare class AdvancedLoopDetectionProcessor extends BaseProcessor {
|
|
12
|
+
private readonly toolCallThreshold;
|
|
13
|
+
private readonly contentLoopThreshold;
|
|
14
|
+
private readonly contentChunkSize;
|
|
15
|
+
private readonly maxHistoryLength;
|
|
16
|
+
private readonly enableLLMDetection;
|
|
17
|
+
private readonly llmCheckAfterTurns;
|
|
18
|
+
private readonly defaultLLMCheckInterval;
|
|
19
|
+
private lastToolCallKey;
|
|
20
|
+
private toolCallRepetitionCount;
|
|
21
|
+
private streamContentHistory;
|
|
22
|
+
private contentStats;
|
|
23
|
+
private lastContentIndex;
|
|
24
|
+
private loopDetected;
|
|
25
|
+
private inCodeBlock;
|
|
26
|
+
private turnsInCurrentPrompt;
|
|
27
|
+
private llmCheckInterval;
|
|
28
|
+
private lastCheckTurn;
|
|
29
|
+
constructor(options?: AdvancedLoopDetectionProcessorOptions);
|
|
30
|
+
processInput(input: ProcessorInput): Promise<ProcessorOutput[]>;
|
|
31
|
+
private getToolCallKey;
|
|
32
|
+
private checkToolCallLoop;
|
|
33
|
+
private checkContentLoop;
|
|
34
|
+
private truncateAndUpdate;
|
|
35
|
+
private analyzeContentChunksForLoop;
|
|
36
|
+
private hasMoreChunksToProcess;
|
|
37
|
+
private isLoopDetectedForChunk;
|
|
38
|
+
private isActualContentMatch;
|
|
39
|
+
private resetContentTracking;
|
|
40
|
+
reset(): void;
|
|
41
|
+
}
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AdvancedLoopDetectionProcessor = void 0;
|
|
4
|
+
const processor_1 = require("../../processor");
|
|
5
|
+
const crypto_1 = require("crypto");
|
|
6
|
+
class AdvancedLoopDetectionProcessor extends processor_1.BaseProcessor {
|
|
7
|
+
constructor(options = {}) {
|
|
8
|
+
super();
|
|
9
|
+
// Tool call tracking
|
|
10
|
+
this.lastToolCallKey = null;
|
|
11
|
+
this.toolCallRepetitionCount = 0;
|
|
12
|
+
// Content streaming tracking
|
|
13
|
+
this.streamContentHistory = '';
|
|
14
|
+
this.contentStats = new Map();
|
|
15
|
+
this.lastContentIndex = 0;
|
|
16
|
+
this.loopDetected = false;
|
|
17
|
+
this.inCodeBlock = false;
|
|
18
|
+
// Turn tracking
|
|
19
|
+
this.turnsInCurrentPrompt = 0;
|
|
20
|
+
this.lastCheckTurn = 0;
|
|
21
|
+
this.toolCallThreshold = options.toolCallThreshold || 5;
|
|
22
|
+
this.contentLoopThreshold = options.contentLoopThreshold || 10;
|
|
23
|
+
this.contentChunkSize = options.contentChunkSize || 50;
|
|
24
|
+
this.maxHistoryLength = options.maxHistoryLength || 1000;
|
|
25
|
+
this.enableLLMDetection = options.enableLLMDetection || false;
|
|
26
|
+
this.llmCheckAfterTurns = options.llmCheckAfterTurns || 30;
|
|
27
|
+
this.defaultLLMCheckInterval = options.defaultLLMCheckInterval || 3;
|
|
28
|
+
this.llmCheckInterval = this.defaultLLMCheckInterval;
|
|
29
|
+
}
|
|
30
|
+
async processInput(input) {
|
|
31
|
+
const { message, context } = input;
|
|
32
|
+
// Increment turn counter
|
|
33
|
+
this.turnsInCurrentPrompt++;
|
|
34
|
+
// Check for tool call loops in the last message
|
|
35
|
+
const lastMessage = message.messages[message.messages.length - 1];
|
|
36
|
+
if (lastMessage.tool_calls && lastMessage.tool_calls.length > 0) {
|
|
37
|
+
for (const toolCall of lastMessage.tool_calls) {
|
|
38
|
+
const isLoop = this.checkToolCallLoop({
|
|
39
|
+
name: toolCall.function.name,
|
|
40
|
+
args: typeof toolCall.function.arguments === 'string'
|
|
41
|
+
? JSON.parse(toolCall.function.arguments)
|
|
42
|
+
: toolCall.function.arguments
|
|
43
|
+
});
|
|
44
|
+
if (isLoop) {
|
|
45
|
+
this.loopDetected = true;
|
|
46
|
+
return [this.createEvent('LoopDetected', {
|
|
47
|
+
type: 'tool_call_loop',
|
|
48
|
+
toolCall: toolCall.function.name,
|
|
49
|
+
repetitionCount: this.toolCallRepetitionCount,
|
|
50
|
+
threshold: this.toolCallThreshold
|
|
51
|
+
})];
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
// Check for content loops
|
|
56
|
+
if (lastMessage.content && typeof lastMessage.content === 'string') {
|
|
57
|
+
const isContentLoop = this.checkContentLoop(lastMessage.content);
|
|
58
|
+
if (isContentLoop) {
|
|
59
|
+
this.loopDetected = true;
|
|
60
|
+
return [this.createEvent('LoopDetected', {
|
|
61
|
+
type: 'content_loop',
|
|
62
|
+
contentLength: this.streamContentHistory.length,
|
|
63
|
+
threshold: this.contentLoopThreshold
|
|
64
|
+
})];
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
// LLM-based loop detection (if enabled)
|
|
68
|
+
if (this.enableLLMDetection &&
|
|
69
|
+
this.turnsInCurrentPrompt >= this.llmCheckAfterTurns &&
|
|
70
|
+
this.turnsInCurrentPrompt - this.lastCheckTurn >= this.llmCheckInterval) {
|
|
71
|
+
this.lastCheckTurn = this.turnsInCurrentPrompt;
|
|
72
|
+
// For now, just log that LLM check would happen
|
|
73
|
+
// In a real implementation, this would call an LLM to analyze the conversation
|
|
74
|
+
console.log('[AdvancedLoopDetection] LLM-based loop check would be performed here');
|
|
75
|
+
}
|
|
76
|
+
return [this.createEvent('LoopCheckCompleted', {
|
|
77
|
+
loopDetected: this.loopDetected,
|
|
78
|
+
turnsInPrompt: this.turnsInCurrentPrompt,
|
|
79
|
+
toolCallCount: this.toolCallRepetitionCount
|
|
80
|
+
})];
|
|
81
|
+
}
|
|
82
|
+
getToolCallKey(toolCall) {
|
|
83
|
+
const argsString = JSON.stringify(toolCall.args);
|
|
84
|
+
const keyString = `${toolCall.name}:${argsString}`;
|
|
85
|
+
return (0, crypto_1.createHash)('sha256').update(keyString).digest('hex');
|
|
86
|
+
}
|
|
87
|
+
checkToolCallLoop(toolCall) {
|
|
88
|
+
const key = this.getToolCallKey(toolCall);
|
|
89
|
+
if (this.lastToolCallKey === key) {
|
|
90
|
+
this.toolCallRepetitionCount++;
|
|
91
|
+
}
|
|
92
|
+
else {
|
|
93
|
+
this.lastToolCallKey = key;
|
|
94
|
+
this.toolCallRepetitionCount = 1;
|
|
95
|
+
}
|
|
96
|
+
return this.toolCallRepetitionCount >= this.toolCallThreshold;
|
|
97
|
+
}
|
|
98
|
+
checkContentLoop(content) {
|
|
99
|
+
var _a;
|
|
100
|
+
// Different content elements can often contain repetitive syntax that is not indicative of a loop.
|
|
101
|
+
// To avoid false positives, we detect when we encounter different content types and
|
|
102
|
+
// reset tracking to avoid analyzing content that spans across different element boundaries.
|
|
103
|
+
const numFences = ((_a = content.match(/```/g)) !== null && _a !== void 0 ? _a : []).length;
|
|
104
|
+
const hasTable = /(^|\n)\s*(\|.*\||[|+-]{3,})/.test(content);
|
|
105
|
+
const hasListItem = /(^|\n)\s*[*-+]\s/.test(content) || /(^|\n)\s*\d+\.\s/.test(content);
|
|
106
|
+
const hasHeading = /(^|\n)#+\s/.test(content);
|
|
107
|
+
const hasBlockquote = /(^|\n)>\s/.test(content);
|
|
108
|
+
if (numFences || hasTable || hasListItem || hasHeading || hasBlockquote) {
|
|
109
|
+
// Reset tracking when different content elements are detected
|
|
110
|
+
this.resetContentTracking();
|
|
111
|
+
}
|
|
112
|
+
const wasInCodeBlock = this.inCodeBlock;
|
|
113
|
+
this.inCodeBlock = numFences % 2 === 0 ? this.inCodeBlock : !this.inCodeBlock;
|
|
114
|
+
if (wasInCodeBlock || this.inCodeBlock) {
|
|
115
|
+
return false;
|
|
116
|
+
}
|
|
117
|
+
this.streamContentHistory += content;
|
|
118
|
+
this.truncateAndUpdate();
|
|
119
|
+
return this.analyzeContentChunksForLoop();
|
|
120
|
+
}
|
|
121
|
+
truncateAndUpdate() {
|
|
122
|
+
if (this.streamContentHistory.length <= this.maxHistoryLength) {
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
const truncationAmount = this.streamContentHistory.length - this.maxHistoryLength;
|
|
126
|
+
this.streamContentHistory = this.streamContentHistory.slice(truncationAmount);
|
|
127
|
+
this.lastContentIndex = Math.max(0, this.lastContentIndex - truncationAmount);
|
|
128
|
+
// Update all stored chunk indices to account for the truncation
|
|
129
|
+
for (const [hash, oldIndices] of this.contentStats.entries()) {
|
|
130
|
+
const adjustedIndices = oldIndices
|
|
131
|
+
.map((index) => index - truncationAmount)
|
|
132
|
+
.filter((index) => index >= 0);
|
|
133
|
+
if (adjustedIndices.length > 0) {
|
|
134
|
+
this.contentStats.set(hash, adjustedIndices);
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
this.contentStats.delete(hash);
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
analyzeContentChunksForLoop() {
|
|
142
|
+
while (this.hasMoreChunksToProcess()) {
|
|
143
|
+
const currentChunk = this.streamContentHistory.substring(this.lastContentIndex, this.lastContentIndex + this.contentChunkSize);
|
|
144
|
+
const chunkHash = (0, crypto_1.createHash)('sha256').update(currentChunk).digest('hex');
|
|
145
|
+
if (this.isLoopDetectedForChunk(currentChunk, chunkHash)) {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
this.lastContentIndex++;
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
hasMoreChunksToProcess() {
|
|
153
|
+
return this.lastContentIndex + this.contentChunkSize <= this.streamContentHistory.length;
|
|
154
|
+
}
|
|
155
|
+
isLoopDetectedForChunk(chunk, hash) {
|
|
156
|
+
const existingIndices = this.contentStats.get(hash);
|
|
157
|
+
if (!existingIndices) {
|
|
158
|
+
this.contentStats.set(hash, [this.lastContentIndex]);
|
|
159
|
+
return false;
|
|
160
|
+
}
|
|
161
|
+
if (!this.isActualContentMatch(chunk, existingIndices[0])) {
|
|
162
|
+
return false;
|
|
163
|
+
}
|
|
164
|
+
existingIndices.push(this.lastContentIndex);
|
|
165
|
+
if (existingIndices.length < this.contentLoopThreshold) {
|
|
166
|
+
return false;
|
|
167
|
+
}
|
|
168
|
+
// Analyze the most recent occurrences to see if they're clustered closely together
|
|
169
|
+
const recentIndices = existingIndices.slice(-this.contentLoopThreshold);
|
|
170
|
+
const totalDistance = recentIndices[recentIndices.length - 1] - recentIndices[0];
|
|
171
|
+
const averageDistance = totalDistance / (this.contentLoopThreshold - 1);
|
|
172
|
+
const maxAllowedDistance = this.contentChunkSize * 1.5;
|
|
173
|
+
return averageDistance <= maxAllowedDistance;
|
|
174
|
+
}
|
|
175
|
+
isActualContentMatch(currentChunk, originalIndex) {
|
|
176
|
+
const originalChunk = this.streamContentHistory.substring(originalIndex, originalIndex + this.contentChunkSize);
|
|
177
|
+
return originalChunk === currentChunk;
|
|
178
|
+
}
|
|
179
|
+
resetContentTracking(resetHistory = true) {
|
|
180
|
+
if (resetHistory) {
|
|
181
|
+
this.streamContentHistory = '';
|
|
182
|
+
}
|
|
183
|
+
this.contentStats.clear();
|
|
184
|
+
this.lastContentIndex = 0;
|
|
185
|
+
}
|
|
186
|
+
reset() {
|
|
187
|
+
this.lastToolCallKey = null;
|
|
188
|
+
this.toolCallRepetitionCount = 0;
|
|
189
|
+
this.resetContentTracking();
|
|
190
|
+
this.turnsInCurrentPrompt = 0;
|
|
191
|
+
this.llmCheckInterval = this.defaultLLMCheckInterval;
|
|
192
|
+
this.lastCheckTurn = 0;
|
|
193
|
+
this.loopDetected = false;
|
|
194
|
+
this.inCodeBlock = false;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
exports.AdvancedLoopDetectionProcessor = AdvancedLoopDetectionProcessor;
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { BaseProcessor, ProcessorInput, ProcessorOutput } from '../../processor';
|
|
2
|
+
export interface ChatCompressionInfo {
|
|
3
|
+
originalTokenCount: number;
|
|
4
|
+
newTokenCount: number;
|
|
5
|
+
compressionRatio: number;
|
|
6
|
+
threshold: number;
|
|
7
|
+
}
|
|
8
|
+
export interface ChatCompressionProcessorOptions {
|
|
9
|
+
compressionThreshold?: number;
|
|
10
|
+
compressionPreserveThreshold?: number;
|
|
11
|
+
tokenLimit?: number;
|
|
12
|
+
enableCompression?: boolean;
|
|
13
|
+
}
|
|
14
|
+
export declare class ChatCompressionProcessor extends BaseProcessor {
|
|
15
|
+
private readonly compressionThreshold;
|
|
16
|
+
private readonly compressionPreserveThreshold;
|
|
17
|
+
private readonly tokenLimit;
|
|
18
|
+
private readonly enableCompression;
|
|
19
|
+
constructor(options?: ChatCompressionProcessorOptions);
|
|
20
|
+
processInput(input: ProcessorInput): Promise<ProcessorOutput[]>;
|
|
21
|
+
private estimateTokenCount;
|
|
22
|
+
setCompressionThreshold(threshold: number): void;
|
|
23
|
+
setTokenLimit(limit: number): void;
|
|
24
|
+
enableCompressionForSession(): void;
|
|
25
|
+
disableCompressionForSession(): void;
|
|
26
|
+
}
|