@codebolt/agent 1.2.1 → 2.2.2
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/builderpattern/agent.d.ts +86 -0
- package/dist/builderpattern/agent.js +324 -0
- package/dist/builderpattern/followupquestionbuilder.d.ts +75 -0
- package/dist/builderpattern/followupquestionbuilder.js +197 -0
- package/dist/builderpattern/index.d.ts +14 -0
- package/dist/builderpattern/index.js +23 -0
- package/dist/builderpattern/llmoutputhandler.d.ts +102 -0
- package/dist/builderpattern/llmoutputhandler.js +452 -0
- package/dist/builderpattern/promptbuilder.d.ts +382 -0
- package/dist/builderpattern/promptbuilder.js +805 -0
- package/dist/builderpattern/systemprompt.d.ts +20 -0
- package/dist/builderpattern/systemprompt.js +48 -0
- package/dist/builderpattern/taskInstruction.d.ts +37 -0
- package/dist/builderpattern/taskInstruction.js +57 -0
- package/dist/builderpattern/usermessage.d.ts +70 -0
- package/dist/builderpattern/usermessage.js +123 -0
- 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 +405 -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/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 +94 -0
- package/dist/processor/types/interfaces.js +2 -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/addToolsListMessageModifier.d.ts +22 -0
- package/dist/processor-pieces/messageModifiers/addToolsListMessageModifier.js +144 -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 +15 -0
- package/dist/processor-pieces/messageModifiers/baseContextMessageModifier.js +75 -0
- package/dist/processor-pieces/messageModifiers/baseSystemInstructionMessageModifier.d.ts +11 -0
- package/dist/processor-pieces/messageModifiers/baseSystemInstructionMessageModifier.js +46 -0
- package/dist/processor-pieces/messageModifiers/chatHistoryMessageModifier.d.ts +18 -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/environmentContextModifier.d.ts +26 -0
- package/dist/processor-pieces/messageModifiers/environmentContextModifier.js +260 -0
- package/dist/processor-pieces/messageModifiers/handleUrlMessageModifier.d.ts +12 -0
- package/dist/processor-pieces/messageModifiers/handleUrlMessageModifier.js +60 -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 +18 -0
- package/dist/processor-pieces/messageModifiers/imageAttachmentMessageModifier.js +222 -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/toolInjectionModifier.d.ts +20 -0
- package/dist/processor-pieces/messageModifiers/toolInjectionModifier.js +152 -0
- package/dist/processor-pieces/messageModifiers/workingDirectoryMessageModifier.d.ts +22 -0
- package/dist/processor-pieces/messageModifiers/workingDirectoryMessageModifier.js +194 -0
- package/dist/processor-pieces/postInferenceProcessors/loopDetectionModifier.d.ts +29 -0
- package/dist/processor-pieces/postInferenceProcessors/loopDetectionModifier.js +174 -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/preInferenceProcessors/chatCompressionModifier.d.ts +35 -0
- package/dist/processor-pieces/preInferenceProcessors/chatCompressionModifier.js +255 -0
- package/dist/processor-pieces/preInferenceProcessors/index.d.ts +1 -0
- package/dist/processor-pieces/preInferenceProcessors/index.js +2 -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/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/index.d.ts +18 -0
- package/dist/unified/index.js +42 -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 +29 -7
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.WorkingDirectoryMessageModifier = void 0;
|
|
40
|
+
const processor_1 = require("../../processor");
|
|
41
|
+
const codeboltjs_1 = __importDefault(require("@codebolt/codeboltjs"));
|
|
42
|
+
const path = __importStar(require("path"));
|
|
43
|
+
class WorkingDirectoryMessageModifier extends processor_1.BaseMessageModifier {
|
|
44
|
+
constructor(options = {}) {
|
|
45
|
+
super({ context: options });
|
|
46
|
+
this.showFolderStructureSummary = options.showFolderStructureSummary || false;
|
|
47
|
+
this.listFiles = options.listFiles || false;
|
|
48
|
+
this.listFilesDepth = options.listFilesDepth || 2;
|
|
49
|
+
this.listFilesLimit = options.listFilesLimit || 200;
|
|
50
|
+
this.listFilesIgnoreFromGitignore = options.listFilesIgnoreFromGitignore || true;
|
|
51
|
+
this.listFilesIgnore = options.listFilesIgnore || ['node_modules', '.git', 'dist', 'build'];
|
|
52
|
+
}
|
|
53
|
+
async modify(input) {
|
|
54
|
+
try {
|
|
55
|
+
const { originalRequest, createdMessage, context } = input;
|
|
56
|
+
const contextParts = [];
|
|
57
|
+
// Get project information
|
|
58
|
+
try {
|
|
59
|
+
const projectPathResponse = await codeboltjs_1.default.project.getProjectPath();
|
|
60
|
+
const projectPath = typeof projectPathResponse === 'string'
|
|
61
|
+
? projectPathResponse
|
|
62
|
+
: (projectPathResponse === null || projectPathResponse === void 0 ? void 0 : projectPathResponse.path) || String(projectPathResponse) || '';
|
|
63
|
+
contextParts.push(`Project Directory: ${projectPath}`);
|
|
64
|
+
if (this.showFolderStructureSummary) {
|
|
65
|
+
const summary = await this.generateFolderStructureSummary(projectPath);
|
|
66
|
+
contextParts.push(`Folder Structure Summary:\n${summary}`);
|
|
67
|
+
}
|
|
68
|
+
if (this.listFiles) {
|
|
69
|
+
const filesList = await this.generateFilesList(projectPath);
|
|
70
|
+
contextParts.push(`Files List:\n${filesList}`);
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
catch (error) {
|
|
74
|
+
console.error('Error getting project information:', error);
|
|
75
|
+
contextParts.push('Working Directory: Unable to access project information');
|
|
76
|
+
}
|
|
77
|
+
// Create context message if we have any context parts
|
|
78
|
+
if (contextParts.length > 0) {
|
|
79
|
+
const contextMessage = {
|
|
80
|
+
role: 'system',
|
|
81
|
+
content: contextParts.join('\n\n'),
|
|
82
|
+
name: 'working-directory-context'
|
|
83
|
+
};
|
|
84
|
+
return {
|
|
85
|
+
messages: [contextMessage, ...createdMessage.messages],
|
|
86
|
+
metadata: {
|
|
87
|
+
...createdMessage.metadata,
|
|
88
|
+
workingDirectoryContextAdded: true,
|
|
89
|
+
contextParts: contextParts.length
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
return createdMessage;
|
|
94
|
+
}
|
|
95
|
+
catch (error) {
|
|
96
|
+
console.error('Error in WorkingDirectoryMessageModifier:', error);
|
|
97
|
+
throw error;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
async generateFolderStructureSummary(projectPath) {
|
|
101
|
+
try {
|
|
102
|
+
// Use CodeBolt's directory listing with recursive option
|
|
103
|
+
const response = await codeboltjs_1.default.fs.listDirectory({
|
|
104
|
+
path: projectPath,
|
|
105
|
+
show_hidden: false,
|
|
106
|
+
detailed: false,
|
|
107
|
+
limit: 200,
|
|
108
|
+
notifyUser: false
|
|
109
|
+
});
|
|
110
|
+
const directories = new Set();
|
|
111
|
+
// Extract directories from the response
|
|
112
|
+
if (response && response.success) {
|
|
113
|
+
let entries;
|
|
114
|
+
if (typeof response.result === 'string') {
|
|
115
|
+
// If result is a string, we'll need to parse it or work with what we have
|
|
116
|
+
return response.result.split('\n').slice(0, 20).join('\n');
|
|
117
|
+
}
|
|
118
|
+
else if (response.result && response.result.entries) {
|
|
119
|
+
entries = response.result.entries;
|
|
120
|
+
}
|
|
121
|
+
else if (response.entries) {
|
|
122
|
+
entries = response.entries;
|
|
123
|
+
}
|
|
124
|
+
if (entries) {
|
|
125
|
+
entries.forEach((entry) => {
|
|
126
|
+
if (entry.type === 'directory' && !this.shouldIgnore(entry.path || entry.name)) {
|
|
127
|
+
directories.add(entry.path || entry.name);
|
|
128
|
+
}
|
|
129
|
+
// Also get parent directories of files
|
|
130
|
+
const dir = path.dirname(entry.path || entry.name);
|
|
131
|
+
if (dir !== '.' && !this.shouldIgnore(dir)) {
|
|
132
|
+
directories.add(dir);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const sortedDirs = Array.from(directories).sort();
|
|
138
|
+
return sortedDirs.length > 0
|
|
139
|
+
? sortedDirs.slice(0, 20).join('\n')
|
|
140
|
+
: 'No accessible directories found';
|
|
141
|
+
}
|
|
142
|
+
catch (error) {
|
|
143
|
+
return 'Unable to generate folder structure summary';
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
async generateFilesList(projectPath) {
|
|
147
|
+
try {
|
|
148
|
+
// Use CodeBolt's directory listing to get files
|
|
149
|
+
const response = await codeboltjs_1.default.fs.listDirectory({
|
|
150
|
+
path: projectPath,
|
|
151
|
+
show_hidden: false,
|
|
152
|
+
detailed: false,
|
|
153
|
+
limit: this.listFilesLimit,
|
|
154
|
+
notifyUser: false
|
|
155
|
+
});
|
|
156
|
+
const files = [];
|
|
157
|
+
// Extract files from the response
|
|
158
|
+
if (response && response.success) {
|
|
159
|
+
let entries;
|
|
160
|
+
if (typeof response.result === 'string') {
|
|
161
|
+
// If result is a string, split and filter for files
|
|
162
|
+
return response.result.split('\n')
|
|
163
|
+
.filter((line) => !this.shouldIgnore(line))
|
|
164
|
+
.slice(0, this.listFilesLimit)
|
|
165
|
+
.join('\n');
|
|
166
|
+
}
|
|
167
|
+
else if (response.result && response.result.entries) {
|
|
168
|
+
entries = response.result.entries;
|
|
169
|
+
}
|
|
170
|
+
else if (response.entries) {
|
|
171
|
+
entries = response.entries;
|
|
172
|
+
}
|
|
173
|
+
if (entries) {
|
|
174
|
+
entries.forEach((entry) => {
|
|
175
|
+
if (entry.type === 'file' && !this.shouldIgnore(entry.path || entry.name)) {
|
|
176
|
+
files.push(entry.path || entry.name);
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
const filteredFiles = files.slice(0, this.listFilesLimit);
|
|
182
|
+
return filteredFiles.length > 0
|
|
183
|
+
? filteredFiles.join('\n')
|
|
184
|
+
: 'No accessible files found';
|
|
185
|
+
}
|
|
186
|
+
catch (error) {
|
|
187
|
+
return 'Unable to generate files list';
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
shouldIgnore(filePath) {
|
|
191
|
+
return this.listFilesIgnore.some(ignore => filePath.includes(ignore) || path.basename(filePath) === ignore);
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
exports.WorkingDirectoryMessageModifier = WorkingDirectoryMessageModifier;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { ProcessedMessage } from "@codebolt/types/agent";
|
|
2
|
+
import { BasePostInferenceProcessor } from "../base";
|
|
3
|
+
import { LLMResponse } from "@codebolt/types/sdk";
|
|
4
|
+
export interface LoopDetectionOptions {
|
|
5
|
+
maxSimilarMessages?: number;
|
|
6
|
+
similarityThreshold?: number;
|
|
7
|
+
timeWindowMs?: number;
|
|
8
|
+
enableLoopPrevention?: boolean;
|
|
9
|
+
}
|
|
10
|
+
interface MessageHistory {
|
|
11
|
+
content: string;
|
|
12
|
+
timestamp: number;
|
|
13
|
+
role: string;
|
|
14
|
+
}
|
|
15
|
+
export declare class LoopDetectionModifier extends BasePostInferenceProcessor {
|
|
16
|
+
private readonly options;
|
|
17
|
+
private messageHistory;
|
|
18
|
+
private loopDetected;
|
|
19
|
+
constructor(options?: LoopDetectionOptions);
|
|
20
|
+
modify(llmMessageSent: ProcessedMessage, llmResponseMessage: LLMResponse, nextPrompt: ProcessedMessage): Promise<ProcessedMessage>;
|
|
21
|
+
private detectLoop;
|
|
22
|
+
private checkSimilarMessages;
|
|
23
|
+
private calculateSimilarity;
|
|
24
|
+
private levenshteinDistance;
|
|
25
|
+
private cleanOldMessages;
|
|
26
|
+
resetLoopDetection(): void;
|
|
27
|
+
getMessageHistory(): MessageHistory[];
|
|
28
|
+
}
|
|
29
|
+
export {};
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.LoopDetectionModifier = void 0;
|
|
4
|
+
const base_1 = require("../base");
|
|
5
|
+
class LoopDetectionModifier extends base_1.BasePostInferenceProcessor {
|
|
6
|
+
constructor(options = {}) {
|
|
7
|
+
super();
|
|
8
|
+
this.messageHistory = [];
|
|
9
|
+
this.loopDetected = false;
|
|
10
|
+
this.options = {
|
|
11
|
+
maxSimilarMessages: options.maxSimilarMessages || 3,
|
|
12
|
+
similarityThreshold: options.similarityThreshold || 0.8,
|
|
13
|
+
timeWindowMs: options.timeWindowMs || 60000, // 1 minute
|
|
14
|
+
enableLoopPrevention: options.enableLoopPrevention !== false
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
modify(llmMessageSent, llmResponseMessage, nextPrompt) {
|
|
18
|
+
try {
|
|
19
|
+
if (!this.options.enableLoopPrevention) {
|
|
20
|
+
return Promise.resolve(nextPrompt);
|
|
21
|
+
}
|
|
22
|
+
const currentTime = Date.now();
|
|
23
|
+
// Add LLM response to history
|
|
24
|
+
if (llmResponseMessage.content) {
|
|
25
|
+
this.messageHistory.push({
|
|
26
|
+
content: llmResponseMessage.content,
|
|
27
|
+
timestamp: currentTime,
|
|
28
|
+
role: llmResponseMessage.role
|
|
29
|
+
});
|
|
30
|
+
}
|
|
31
|
+
// Add any choice messages from LLM response to history
|
|
32
|
+
if (llmResponseMessage.choices) {
|
|
33
|
+
for (const choice of llmResponseMessage.choices) {
|
|
34
|
+
if (choice.message && choice.message.content) {
|
|
35
|
+
this.messageHistory.push({
|
|
36
|
+
content: choice.message.content,
|
|
37
|
+
timestamp: currentTime,
|
|
38
|
+
role: choice.message.role
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
// Add the original sent message to history if it exists
|
|
44
|
+
for (const message of llmMessageSent.message.messages) {
|
|
45
|
+
if (typeof message.content === 'string') {
|
|
46
|
+
this.messageHistory.push({
|
|
47
|
+
content: message.content,
|
|
48
|
+
timestamp: currentTime,
|
|
49
|
+
role: message.role
|
|
50
|
+
});
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
// Clean old messages from history
|
|
54
|
+
this.cleanOldMessages(currentTime);
|
|
55
|
+
// Check for loops
|
|
56
|
+
const loopDetected = this.detectLoop();
|
|
57
|
+
if (loopDetected && !this.loopDetected) {
|
|
58
|
+
this.loopDetected = true;
|
|
59
|
+
// Add loop detection warning to the next prompt
|
|
60
|
+
const warningMessage = {
|
|
61
|
+
role: 'system',
|
|
62
|
+
content: `[Loop Detection Warning] Similar messages detected in recent conversation. This may indicate a conversational loop. Consider rephrasing your request or providing more specific information.`
|
|
63
|
+
};
|
|
64
|
+
const updatedMessages = [...nextPrompt.message.messages, warningMessage];
|
|
65
|
+
return Promise.resolve({
|
|
66
|
+
message: {
|
|
67
|
+
...nextPrompt.message,
|
|
68
|
+
messages: updatedMessages
|
|
69
|
+
},
|
|
70
|
+
metadata: {
|
|
71
|
+
...nextPrompt.metadata,
|
|
72
|
+
loopDetected: true,
|
|
73
|
+
loopDetectionWarningAdded: true
|
|
74
|
+
}
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
// Reset loop detection if we haven't detected a loop recently
|
|
78
|
+
if (!loopDetected && this.loopDetected) {
|
|
79
|
+
this.loopDetected = false;
|
|
80
|
+
}
|
|
81
|
+
return Promise.resolve({
|
|
82
|
+
message: nextPrompt.message,
|
|
83
|
+
metadata: {
|
|
84
|
+
...nextPrompt.metadata,
|
|
85
|
+
loopDetectionChecked: true,
|
|
86
|
+
loopDetected: false
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
console.error('Error in LoopDetectionModifier:', error);
|
|
92
|
+
return Promise.resolve(nextPrompt);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
detectLoop() {
|
|
96
|
+
if (this.messageHistory.length < this.options.maxSimilarMessages) {
|
|
97
|
+
return false;
|
|
98
|
+
}
|
|
99
|
+
// Get recent messages grouped by role
|
|
100
|
+
const recentUserMessages = this.messageHistory
|
|
101
|
+
.filter(msg => msg.role === 'user')
|
|
102
|
+
.slice(-this.options.maxSimilarMessages);
|
|
103
|
+
const recentAssistantMessages = this.messageHistory
|
|
104
|
+
.filter(msg => msg.role === 'assistant')
|
|
105
|
+
.slice(-this.options.maxSimilarMessages);
|
|
106
|
+
// Check for similar user messages
|
|
107
|
+
if (recentUserMessages.length >= this.options.maxSimilarMessages) {
|
|
108
|
+
const userLoop = this.checkSimilarMessages(recentUserMessages);
|
|
109
|
+
if (userLoop)
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
// Check for similar assistant messages
|
|
113
|
+
if (recentAssistantMessages.length >= this.options.maxSimilarMessages) {
|
|
114
|
+
const assistantLoop = this.checkSimilarMessages(recentAssistantMessages);
|
|
115
|
+
if (assistantLoop)
|
|
116
|
+
return true;
|
|
117
|
+
}
|
|
118
|
+
return false;
|
|
119
|
+
}
|
|
120
|
+
checkSimilarMessages(messages) {
|
|
121
|
+
if (messages.length < 2)
|
|
122
|
+
return false;
|
|
123
|
+
// Compare each message with every other message
|
|
124
|
+
for (let i = 0; i < messages.length - 1; i++) {
|
|
125
|
+
for (let j = i + 1; j < messages.length; j++) {
|
|
126
|
+
const similarity = this.calculateSimilarity(messages[i].content, messages[j].content);
|
|
127
|
+
if (similarity >= this.options.similarityThreshold) {
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return false;
|
|
133
|
+
}
|
|
134
|
+
calculateSimilarity(text1, text2) {
|
|
135
|
+
// Simple similarity calculation using Levenshtein distance
|
|
136
|
+
const distance = this.levenshteinDistance(text1.toLowerCase(), text2.toLowerCase());
|
|
137
|
+
const maxLength = Math.max(text1.length, text2.length);
|
|
138
|
+
if (maxLength === 0)
|
|
139
|
+
return 1;
|
|
140
|
+
return 1 - (distance / maxLength);
|
|
141
|
+
}
|
|
142
|
+
levenshteinDistance(str1, str2) {
|
|
143
|
+
const matrix = [];
|
|
144
|
+
for (let i = 0; i <= str2.length; i++) {
|
|
145
|
+
matrix[i] = [i];
|
|
146
|
+
}
|
|
147
|
+
for (let j = 0; j <= str1.length; j++) {
|
|
148
|
+
matrix[0][j] = j;
|
|
149
|
+
}
|
|
150
|
+
for (let i = 1; i <= str2.length; i++) {
|
|
151
|
+
for (let j = 1; j <= str1.length; j++) {
|
|
152
|
+
if (str2.charAt(i - 1) === str1.charAt(j - 1)) {
|
|
153
|
+
matrix[i][j] = matrix[i - 1][j - 1];
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j] + 1);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return matrix[str2.length][str1.length];
|
|
161
|
+
}
|
|
162
|
+
cleanOldMessages(currentTime) {
|
|
163
|
+
const cutoffTime = currentTime - this.options.timeWindowMs;
|
|
164
|
+
this.messageHistory = this.messageHistory.filter(msg => msg.timestamp >= cutoffTime);
|
|
165
|
+
}
|
|
166
|
+
resetLoopDetection() {
|
|
167
|
+
this.messageHistory = [];
|
|
168
|
+
this.loopDetected = false;
|
|
169
|
+
}
|
|
170
|
+
getMessageHistory() {
|
|
171
|
+
return [...this.messageHistory];
|
|
172
|
+
}
|
|
173
|
+
}
|
|
174
|
+
exports.LoopDetectionModifier = LoopDetectionModifier;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { PostToolCallProcessorInput, PostToolCallProcessorOutput } from "@codebolt/types/agent";
|
|
2
|
+
import { BasePostToolCallProcessor } from "../base";
|
|
3
|
+
export interface ShellProcessorOptions {
|
|
4
|
+
enableShellExecution?: boolean;
|
|
5
|
+
maxExecutionTime?: number;
|
|
6
|
+
allowedCommands?: string[];
|
|
7
|
+
blockedCommands?: string[];
|
|
8
|
+
workingDirectory?: string;
|
|
9
|
+
}
|
|
10
|
+
export declare class ShellProcessorModifier extends BasePostToolCallProcessor {
|
|
11
|
+
private readonly options;
|
|
12
|
+
private readonly execAsync;
|
|
13
|
+
private readonly SHELL_TRIGGER;
|
|
14
|
+
private readonly SHELL_CLOSE;
|
|
15
|
+
private readonly ARGS_PLACEHOLDER;
|
|
16
|
+
constructor(options?: ShellProcessorOptions);
|
|
17
|
+
modify(input: PostToolCallProcessorInput): Promise<PostToolCallProcessorOutput>;
|
|
18
|
+
private processShellInToolResults;
|
|
19
|
+
private processShellInjections;
|
|
20
|
+
private extractShellInjections;
|
|
21
|
+
private validateCommand;
|
|
22
|
+
private executeCommand;
|
|
23
|
+
private escapeShellArg;
|
|
24
|
+
private escapeRegex;
|
|
25
|
+
}
|
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ShellProcessorModifier = void 0;
|
|
4
|
+
const base_1 = require("../base");
|
|
5
|
+
const child_process_1 = require("child_process");
|
|
6
|
+
const util_1 = require("util");
|
|
7
|
+
class ShellProcessorModifier extends base_1.BasePostToolCallProcessor {
|
|
8
|
+
constructor(options = {}) {
|
|
9
|
+
super();
|
|
10
|
+
this.execAsync = (0, util_1.promisify)(child_process_1.exec);
|
|
11
|
+
this.SHELL_TRIGGER = '!{';
|
|
12
|
+
this.SHELL_CLOSE = '}';
|
|
13
|
+
this.ARGS_PLACEHOLDER = '{{args}}';
|
|
14
|
+
this.options = {
|
|
15
|
+
enableShellExecution: options.enableShellExecution || false, // Disabled by default for security
|
|
16
|
+
maxExecutionTime: options.maxExecutionTime || 10000, // 10 seconds
|
|
17
|
+
allowedCommands: options.allowedCommands || ['ls', 'pwd', 'echo', 'cat', 'head', 'tail', 'grep', 'find', 'wc'],
|
|
18
|
+
blockedCommands: options.blockedCommands || ['rm', 'del', 'format', 'sudo', 'su', 'chmod', 'chown', 'kill', 'killall'],
|
|
19
|
+
workingDirectory: options.workingDirectory || process.cwd()
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
async modify(input) {
|
|
23
|
+
var _a;
|
|
24
|
+
try {
|
|
25
|
+
const { llmMessageSent, rawLLMResponseMessage, nextPrompt, toolResults } = input;
|
|
26
|
+
// Process shell commands in tool results if they exist
|
|
27
|
+
let processedNextPrompt = nextPrompt;
|
|
28
|
+
let shouldExit = false;
|
|
29
|
+
if (toolResults && toolResults.length > 0) {
|
|
30
|
+
// Look for shell-related tool results or commands in the content
|
|
31
|
+
const shellResults = toolResults.filter(result =>
|
|
32
|
+
// Check if the tool call ID suggests it's a shell command
|
|
33
|
+
(result.tool_call_id && (result.tool_call_id.includes('run_terminal_cmd') ||
|
|
34
|
+
result.tool_call_id.includes('shell'))) ||
|
|
35
|
+
// Check if content contains shell triggers or placeholders
|
|
36
|
+
(result.content && typeof result.content === 'string' &&
|
|
37
|
+
(result.content.includes(this.SHELL_TRIGGER) || result.content.includes(this.ARGS_PLACEHOLDER))));
|
|
38
|
+
if (shellResults.length > 0) {
|
|
39
|
+
processedNextPrompt = await this.processShellInToolResults(nextPrompt, shellResults);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Also process any shell injections in the next prompt messages
|
|
43
|
+
const updatedMessages = [];
|
|
44
|
+
let contentModified = false;
|
|
45
|
+
for (const message of processedNextPrompt.message.messages) {
|
|
46
|
+
if (typeof message.content === 'string') {
|
|
47
|
+
let processedContent = message.content;
|
|
48
|
+
// Replace {{args}} placeholders if metadata has args
|
|
49
|
+
const args = ((_a = processedNextPrompt.metadata) === null || _a === void 0 ? void 0 : _a.args) || '';
|
|
50
|
+
if (processedContent.includes(this.ARGS_PLACEHOLDER)) {
|
|
51
|
+
processedContent = processedContent.replace(new RegExp(this.escapeRegex(this.ARGS_PLACEHOLDER), 'g'), args);
|
|
52
|
+
contentModified = true;
|
|
53
|
+
}
|
|
54
|
+
// Process shell injections if enabled
|
|
55
|
+
if (this.options.enableShellExecution && processedContent.includes(this.SHELL_TRIGGER)) {
|
|
56
|
+
processedContent = await this.processShellInjections(processedContent, args);
|
|
57
|
+
contentModified = true;
|
|
58
|
+
}
|
|
59
|
+
updatedMessages.push({
|
|
60
|
+
...message,
|
|
61
|
+
content: processedContent
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
updatedMessages.push(message);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
if (contentModified) {
|
|
69
|
+
processedNextPrompt = {
|
|
70
|
+
message: {
|
|
71
|
+
...processedNextPrompt.message,
|
|
72
|
+
messages: updatedMessages
|
|
73
|
+
},
|
|
74
|
+
metadata: {
|
|
75
|
+
...processedNextPrompt.metadata,
|
|
76
|
+
shellProcessed: true,
|
|
77
|
+
argsReplaced: true
|
|
78
|
+
}
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
return {
|
|
82
|
+
nextPrompt: processedNextPrompt,
|
|
83
|
+
shouldExit
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
catch (error) {
|
|
87
|
+
console.error('Error in ShellProcessorModifier:', error);
|
|
88
|
+
return {
|
|
89
|
+
nextPrompt: input.nextPrompt,
|
|
90
|
+
shouldExit: false
|
|
91
|
+
};
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
async processShellInToolResults(nextPrompt, shellResults) {
|
|
95
|
+
var _a;
|
|
96
|
+
// Process shell commands found in tool results
|
|
97
|
+
let processedPrompt = nextPrompt;
|
|
98
|
+
for (const result of shellResults) {
|
|
99
|
+
if (result.content && typeof result.content === 'string') {
|
|
100
|
+
const args = ((_a = processedPrompt.metadata) === null || _a === void 0 ? void 0 : _a.args) || '';
|
|
101
|
+
// Process any shell injections in the tool result content
|
|
102
|
+
if (result.content.includes(this.SHELL_TRIGGER)) {
|
|
103
|
+
const processedContent = await this.processShellInjections(result.content, args);
|
|
104
|
+
// Add the processed result as a system message
|
|
105
|
+
const systemMessage = {
|
|
106
|
+
role: 'system',
|
|
107
|
+
content: `[Shell Tool Result]: ${processedContent}`
|
|
108
|
+
};
|
|
109
|
+
processedPrompt = {
|
|
110
|
+
message: {
|
|
111
|
+
...processedPrompt.message,
|
|
112
|
+
messages: [...processedPrompt.message.messages, systemMessage]
|
|
113
|
+
},
|
|
114
|
+
metadata: {
|
|
115
|
+
...processedPrompt.metadata,
|
|
116
|
+
shellToolResultsProcessed: true
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return processedPrompt;
|
|
123
|
+
}
|
|
124
|
+
async processShellInjections(content, args) {
|
|
125
|
+
let processedContent = content;
|
|
126
|
+
const injections = this.extractShellInjections(content);
|
|
127
|
+
// Process injections in reverse order to maintain correct indices
|
|
128
|
+
for (let i = injections.length - 1; i >= 0; i--) {
|
|
129
|
+
const injection = injections[i];
|
|
130
|
+
try {
|
|
131
|
+
// Replace {{args}} in the command with shell-escaped args
|
|
132
|
+
const command = injection.command.replace(new RegExp(this.escapeRegex(this.ARGS_PLACEHOLDER), 'g'), this.escapeShellArg(args));
|
|
133
|
+
// Validate and execute command
|
|
134
|
+
this.validateCommand(command);
|
|
135
|
+
const result = await this.executeCommand(command);
|
|
136
|
+
const replacement = result;
|
|
137
|
+
processedContent = processedContent.substring(0, injection.startIndex) +
|
|
138
|
+
replacement +
|
|
139
|
+
processedContent.substring(injection.endIndex);
|
|
140
|
+
}
|
|
141
|
+
catch (error) {
|
|
142
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error';
|
|
143
|
+
const replacement = `[Shell command error: ${errorMessage}]`;
|
|
144
|
+
processedContent = processedContent.substring(0, injection.startIndex) +
|
|
145
|
+
replacement +
|
|
146
|
+
processedContent.substring(injection.endIndex);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return processedContent;
|
|
150
|
+
}
|
|
151
|
+
extractShellInjections(content) {
|
|
152
|
+
const injections = [];
|
|
153
|
+
let searchIndex = 0;
|
|
154
|
+
while (true) {
|
|
155
|
+
const startIndex = content.indexOf(this.SHELL_TRIGGER, searchIndex);
|
|
156
|
+
if (startIndex === -1)
|
|
157
|
+
break;
|
|
158
|
+
const contentStart = startIndex + this.SHELL_TRIGGER.length;
|
|
159
|
+
const endIndex = content.indexOf(this.SHELL_CLOSE, contentStart);
|
|
160
|
+
if (endIndex === -1) {
|
|
161
|
+
// No closing brace found, skip this occurrence
|
|
162
|
+
searchIndex = contentStart;
|
|
163
|
+
continue;
|
|
164
|
+
}
|
|
165
|
+
const command = content.substring(contentStart, endIndex).trim();
|
|
166
|
+
if (command.length > 0) {
|
|
167
|
+
injections.push({
|
|
168
|
+
startIndex,
|
|
169
|
+
endIndex: endIndex + this.SHELL_CLOSE.length,
|
|
170
|
+
command
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
searchIndex = endIndex + this.SHELL_CLOSE.length;
|
|
174
|
+
}
|
|
175
|
+
return injections;
|
|
176
|
+
}
|
|
177
|
+
validateCommand(command) {
|
|
178
|
+
if (!this.options.enableShellExecution) {
|
|
179
|
+
throw new Error('Shell execution is disabled');
|
|
180
|
+
}
|
|
181
|
+
// Extract the base command (first word)
|
|
182
|
+
const baseCommand = command.trim().split(/\s+/)[0];
|
|
183
|
+
// Check blocked commands
|
|
184
|
+
if (this.options.blockedCommands.some(blocked => baseCommand.includes(blocked))) {
|
|
185
|
+
throw new Error(`Command '${baseCommand}' is blocked for security reasons`);
|
|
186
|
+
}
|
|
187
|
+
// Check allowed commands (if allowlist is defined)
|
|
188
|
+
if (this.options.allowedCommands.length > 0 &&
|
|
189
|
+
!this.options.allowedCommands.some(allowed => baseCommand.includes(allowed))) {
|
|
190
|
+
throw new Error(`Command '${baseCommand}' is not in the allowed commands list`);
|
|
191
|
+
}
|
|
192
|
+
// Additional security checks
|
|
193
|
+
if (command.includes('&&') || command.includes('||') || command.includes(';') || command.includes('|')) {
|
|
194
|
+
throw new Error('Command chaining and piping are not allowed');
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async executeCommand(command) {
|
|
198
|
+
try {
|
|
199
|
+
const { stdout, stderr } = await this.execAsync(command, {
|
|
200
|
+
cwd: this.options.workingDirectory,
|
|
201
|
+
timeout: this.options.maxExecutionTime,
|
|
202
|
+
maxBuffer: 1024 * 1024 // 1MB buffer
|
|
203
|
+
});
|
|
204
|
+
let result = stdout;
|
|
205
|
+
if (stderr) {
|
|
206
|
+
result += `\n[stderr]: ${stderr}`;
|
|
207
|
+
}
|
|
208
|
+
return result || '[Command executed successfully with no output]';
|
|
209
|
+
}
|
|
210
|
+
catch (error) {
|
|
211
|
+
if (error.killed && error.signal === 'SIGTERM') {
|
|
212
|
+
throw new Error(`Command timed out after ${this.options.maxExecutionTime}ms`);
|
|
213
|
+
}
|
|
214
|
+
throw new Error(`Command failed: ${error.message}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
escapeShellArg(arg) {
|
|
218
|
+
// Basic shell escaping - in production, use a proper shell escaping library
|
|
219
|
+
return `"${arg.replace(/"/g, '\\"')}"`;
|
|
220
|
+
}
|
|
221
|
+
escapeRegex(str) {
|
|
222
|
+
return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
exports.ShellProcessorModifier = ShellProcessorModifier;
|