@codebolt/agent 5.0.7 → 5.0.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. package/dist/processor-pieces/base/basePreToolCallProcessor.js +5 -2
  2. package/dist/processor-pieces/messageModifiers/argumentProcessorModifier.d.ts +1 -1
  3. package/dist/processor-pieces/messageModifiers/argumentProcessorModifier.js +2 -2
  4. package/dist/processor-pieces/messageModifiers/atFileProcessorModifier.js +24 -34
  5. package/dist/processor-pieces/messageModifiers/chatRecordingModifier.d.ts +1 -1
  6. package/dist/processor-pieces/messageModifiers/chatRecordingModifier.js +2 -2
  7. package/dist/processor-pieces/messageModifiers/coreSystemPromptModifier.d.ts +1 -1
  8. package/dist/processor-pieces/messageModifiers/coreSystemPromptModifier.js +2 -2
  9. package/dist/processor-pieces/messageModifiers/directoryContextModifier.d.ts +1 -1
  10. package/dist/processor-pieces/messageModifiers/directoryContextModifier.js +8 -3
  11. package/dist/processor-pieces/messageModifiers/environmentContextModifier.d.ts +1 -1
  12. package/dist/processor-pieces/messageModifiers/environmentContextModifier.js +1 -1
  13. package/dist/processor-pieces/messageModifiers/ideContextModifier.js +114 -17
  14. package/dist/processor-pieces/messageModifiers/memoryImportModifier.d.ts +1 -1
  15. package/dist/processor-pieces/messageModifiers/memoryImportModifier.js +13 -5
  16. package/dist/processor-pieces/messageModifiers/toolInjectionModifier.d.ts +5 -0
  17. package/dist/processor-pieces/messageModifiers/toolInjectionModifier.js +4 -0
  18. package/dist/processor-pieces/postInferenceProcessors/loopDetectionModifier.js +24 -8
  19. package/dist/processor-pieces/postToolCallProcessors/conversationCompactorModifier.d.ts +202 -5
  20. package/dist/processor-pieces/postToolCallProcessors/conversationCompactorModifier.js +826 -19
  21. package/dist/processor-pieces/postToolCallProcessors/index.d.ts +1 -1
  22. package/dist/processor-pieces/postToolCallProcessors/index.js +2 -1
  23. package/dist/processor-pieces/postToolCallProcessors/shellProcessorModifier.js +7 -4
  24. package/dist/processor-pieces/preInferenceProcessors/chatCompressionModifier.d.ts +1 -1
  25. package/dist/processor-pieces/preInferenceProcessors/chatCompressionModifier.js +12 -16
  26. package/dist/processor-pieces/pretoolCallProcessors/toolParameterModifier.d.ts +2 -3
  27. package/dist/processor-pieces/pretoolCallProcessors/toolParameterModifier.js +1 -2
  28. package/dist/processor-pieces/utils/messageModifierHelper.js +5 -2
  29. package/dist/types/InternalTypes.d.ts +8 -6
  30. package/dist/unified/agent/agent.js +1 -2
  31. package/dist/unified/agent/codeboltAgent.d.ts +23 -2
  32. package/dist/unified/agent/codeboltAgent.js +55 -12
  33. package/dist/unified/agent/tools.d.ts +7 -11
  34. package/dist/unified/agent/tools.js +12 -3
  35. package/dist/unified/agent/workflow.js +38 -20
  36. package/dist/unified/agent/workflowSteps.d.ts +1 -1
  37. package/dist/unified/agent/workflowSteps.js +58 -23
  38. package/dist/unified/base/agentStep.js +20 -1
  39. package/dist/unified/base/initialPromptGenerator.js +3 -1
  40. package/dist/unified/base/responseExecutor.d.ts +3 -0
  41. package/dist/unified/base/responseExecutor.js +40 -18
  42. package/dist/unified/index.d.ts +1 -0
  43. package/dist/unified/index.js +4 -1
  44. package/dist/unified/services/LoopDetectionService.d.ts +44 -0
  45. package/dist/unified/services/LoopDetectionService.js +79 -0
  46. package/dist/unified/utils/utils.d.ts +20 -1
  47. package/dist/unified/utils/utils.js +8 -4
  48. package/package.json +5 -5
@@ -7,8 +7,12 @@ class ParallelStep {
7
7
  this.id = config.id;
8
8
  this.description = config.description;
9
9
  this.type = config.type;
10
- this.inputSchema = config.inputSchema;
11
- this.outputSchema = config.outputSchema;
10
+ if (config.inputSchema !== undefined) {
11
+ this.inputSchema = config.inputSchema;
12
+ }
13
+ if (config.outputSchema !== undefined) {
14
+ this.outputSchema = config.outputSchema;
15
+ }
12
16
  }
13
17
  async execute(context) {
14
18
  try {
@@ -41,8 +45,12 @@ class ConditionStep {
41
45
  this.id = config.id;
42
46
  this.description = config.description;
43
47
  this.type = config.type;
44
- this.inputSchema = config.inputSchema;
45
- this.outputSchema = config.outputSchema;
48
+ if (config.inputSchema !== undefined) {
49
+ this.inputSchema = config.inputSchema;
50
+ }
51
+ if (config.outputSchema !== undefined) {
52
+ this.outputSchema = config.outputSchema;
53
+ }
46
54
  }
47
55
  async execute(context) {
48
56
  try {
@@ -51,6 +59,8 @@ class ConditionStep {
51
59
  const results = [];
52
60
  for (let i = 0; i < this.steps.length; i++) {
53
61
  const step = this.steps[i];
62
+ if (!step)
63
+ continue;
54
64
  try {
55
65
  const result = await step.execute(context);
56
66
  results.push(result);
@@ -91,8 +101,12 @@ class LoopStep {
91
101
  this.id = config.id;
92
102
  this.description = config.description;
93
103
  this.type = config.type;
94
- this.inputSchema = config.inputSchema;
95
- this.outputSchema = config.outputSchema;
104
+ if (config.inputSchema !== undefined) {
105
+ this.inputSchema = config.inputSchema;
106
+ }
107
+ if (config.outputSchema !== undefined) {
108
+ this.outputSchema = config.outputSchema;
109
+ }
96
110
  this.maxIterations = maxIterations;
97
111
  }
98
112
  async execute(context) {
@@ -105,6 +119,8 @@ class LoopStep {
105
119
  // Execute all steps in this iteration
106
120
  for (let i = 0; i < this.steps.length; i++) {
107
121
  const step = this.steps[i];
122
+ if (!step)
123
+ continue;
108
124
  try {
109
125
  const result = await step.execute(context);
110
126
  result.stepId = `${result.stepId}_loop_${iteration}`;
@@ -153,8 +169,12 @@ class WorkFlowStep {
153
169
  this.id = config.id;
154
170
  this.description = config.description;
155
171
  this.type = config.type;
156
- this.inputSchema = config.inputSchema;
157
- this.outputSchema = config.outputSchema;
172
+ if (config.inputSchema !== undefined) {
173
+ this.inputSchema = config.inputSchema;
174
+ }
175
+ if (config.outputSchema !== undefined) {
176
+ this.outputSchema = config.outputSchema;
177
+ }
158
178
  }
159
179
  async execute(context) {
160
180
  try {
@@ -184,17 +204,24 @@ class AgentStep {
184
204
  this.id = config.id;
185
205
  this.description = config.description;
186
206
  this.type = config.type;
187
- this.inputSchema = config.inputSchema;
188
- this.outputSchema = config.outputSchema;
207
+ if (config.inputSchema !== undefined) {
208
+ this.inputSchema = config.inputSchema;
209
+ }
210
+ if (config.outputSchema !== undefined) {
211
+ this.outputSchema = config.outputSchema;
212
+ }
189
213
  }
190
214
  async execute(context) {
191
- let { result, success, error } = await this.agent.execute(context);
192
- return {
215
+ const { result, success, error } = await this.agent.execute(context);
216
+ const output = {
193
217
  stepId: this.id,
194
218
  success: success,
195
- result: result,
196
- error: error
219
+ result: result
197
220
  };
221
+ if (error !== undefined) {
222
+ output.error = error;
223
+ }
224
+ return output;
198
225
  }
199
226
  }
200
227
  exports.AgentStep = AgentStep;
@@ -203,28 +230,36 @@ class ToolStep {
203
230
  this.id = config.id;
204
231
  this.description = config.description;
205
232
  this.type = config.type;
206
- this.inputSchema = config.inputSchema;
207
- this.outputSchema = config.outputSchema;
233
+ if (config.inputSchema !== undefined) {
234
+ this.inputSchema = config.inputSchema;
235
+ }
236
+ if (config.outputSchema !== undefined) {
237
+ this.outputSchema = config.outputSchema;
238
+ }
208
239
  this.tool = tool;
209
240
  }
210
241
  async execute(context) {
211
242
  try {
212
- let { result, success, error } = await this.tool.execute({}, context);
213
- return {
243
+ const { result, success, error } = await this.tool.execute({}, context);
244
+ const output = {
214
245
  stepId: this.id,
215
246
  success: success,
216
- result: result,
217
- error: error
247
+ result: result
218
248
  };
249
+ if (error !== undefined) {
250
+ output.error = error;
251
+ }
252
+ return output;
219
253
  }
220
254
  catch (error) {
221
255
  const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
222
- return {
256
+ const output = {
223
257
  stepId: this.id,
224
258
  success: false,
225
- result: null,
226
- error: errorMessage
259
+ result: null
227
260
  };
261
+ output.error = errorMessage;
262
+ return output;
228
263
  }
229
264
  }
230
265
  }
@@ -63,8 +63,27 @@ class AgentStep {
63
63
  }
64
64
  }
65
65
  async generateResponse(messageForLLM) {
66
+ var _a, _b;
66
67
  const response = await codeboltjs_1.default.llm.inference(messageForLLM);
67
- return response.completion;
68
+ const completion = response.completion;
69
+ // Add tokenLimit and maxOutputTokens to completion object if available in response
70
+ if (completion) {
71
+ // Check if tokenLimit exists at response level or in completion
72
+ if (response.tokenLimit !== undefined) {
73
+ completion.tokenLimit = response.tokenLimit;
74
+ }
75
+ if (response.maxOutputTokens !== undefined) {
76
+ completion.maxOutputTokens = response.maxOutputTokens;
77
+ }
78
+ // Also check inside completion object itself (from LLM provider response)
79
+ if (((_a = completion.completion) === null || _a === void 0 ? void 0 : _a.tokenLimit) !== undefined) {
80
+ completion.tokenLimit = completion.completion.tokenLimit;
81
+ }
82
+ if (((_b = completion.completion) === null || _b === void 0 ? void 0 : _b.maxOutputTokens) !== undefined) {
83
+ completion.maxOutputTokens = completion.completion.maxOutputTokens;
84
+ }
85
+ }
86
+ return completion;
68
87
  }
69
88
  /**
70
89
  * Update LLM configuration
@@ -17,7 +17,9 @@ class InitialPromptGenerator {
17
17
  this.processors = options.processors || [];
18
18
  this.metaData = options.metaData || {};
19
19
  this.enableLogging = options.enableLogging !== false;
20
- this.baseSystemPrompt = options.baseSystemPrompt;
20
+ if (options.baseSystemPrompt !== undefined) {
21
+ this.baseSystemPrompt = options.baseSystemPrompt;
22
+ }
21
23
  }
22
24
  /**
23
25
  * Process and modify input messages using the message modifier pattern
@@ -1,4 +1,5 @@
1
1
  import { AgentResponseExecutor, PostToolCallProcessor, PreToolCallProcessor, ResponseInput, ResponseOutput } from '@codebolt/types/agent';
2
+ import { LoopDetectionService } from '../services/LoopDetectionService';
2
3
  export declare class ResponseExecutor implements AgentResponseExecutor {
3
4
  private preToolCallProcessors;
4
5
  private postToolCallProcessors;
@@ -7,7 +8,9 @@ export declare class ResponseExecutor implements AgentResponseExecutor {
7
8
  constructor(options: {
8
9
  preToolCallProcessors: PreToolCallProcessor[];
9
10
  postToolCallProcessors: PostToolCallProcessor[];
11
+ loopDetectionService?: LoopDetectionService;
10
12
  });
13
+ private loopDetectionService?;
11
14
  executeResponse(input: ResponseInput): Promise<ResponseOutput>;
12
15
  /**
13
16
  * Extract tool details from tool call
@@ -13,8 +13,12 @@ class ResponseExecutor {
13
13
  this.finalMessage = undefined;
14
14
  this.preToolCallProcessors = options.preToolCallProcessors;
15
15
  this.postToolCallProcessors = options.postToolCallProcessors;
16
+ if (options.loopDetectionService) {
17
+ this.loopDetectionService = options.loopDetectionService;
18
+ }
16
19
  }
17
20
  async executeResponse(input) {
21
+ var _a, _b;
18
22
  let nextMessage = input.nextMessage;
19
23
  for (const preToolCallProcessor of this.preToolCallProcessors) {
20
24
  try {
@@ -59,13 +63,17 @@ class ResponseExecutor {
59
63
  }
60
64
  for (const postToolCallProcessor of this.postToolCallProcessors) {
61
65
  try {
62
- // TODO: Extract required properties from input for PreToolCallProcessorInput
66
+ // Pass current nextMessage (with tool results) to the processor
63
67
  let { nextPrompt, shouldExit } = await postToolCallProcessor.modify({
64
68
  llmMessageSent: input.actualMessageSentToLLM,
65
69
  rawLLMResponseMessage: input.rawLLMOutput,
66
- nextPrompt: input.nextMessage,
67
- toolResults: []
70
+ nextPrompt: nextMessage,
71
+ toolResults: toolResults,
72
+ tokenLimit: (_a = input.rawLLMOutput) === null || _a === void 0 ? void 0 : _a.tokenLimit,
73
+ maxOutputTokens: (_b = input.rawLLMOutput) === null || _b === void 0 ? void 0 : _b.maxOutputTokens
68
74
  });
75
+ // Update nextMessage with the (potentially compressed) result
76
+ nextMessage = nextPrompt;
69
77
  if (shouldExit) {
70
78
  this.completed = true;
71
79
  Promise.resolve({
@@ -75,16 +83,19 @@ class ResponseExecutor {
75
83
  }
76
84
  }
77
85
  catch (error) {
78
- console.error(`[InitialPromptGenerator] Error in message modifier:`, error);
79
- // Continue with other modifiers
86
+ console.error(`[ResponseExecutor] Error in post tool call processor:`, error);
87
+ // Continue with other processors
80
88
  }
81
89
  }
82
- return {
90
+ const output = {
83
91
  completed: this.completed,
84
92
  nextMessage: nextMessage,
85
- toolResults: toolResults,
86
- finalMessage: this.finalMessage
93
+ toolResults: toolResults
87
94
  };
95
+ if (this.finalMessage !== undefined) {
96
+ output.finalMessage = this.finalMessage;
97
+ }
98
+ return output;
88
99
  }
89
100
  /**
90
101
  * Extract tool details from tool call
@@ -142,6 +153,22 @@ class ResponseExecutor {
142
153
  });
143
154
  }
144
155
  }
156
+ // Check for loops before execution
157
+ if (this.loopDetectionService) {
158
+ const toolCallsToCheck = toolsToExecute.map(t => ({ name: t.toolName, args: t.toolInput }));
159
+ for (const toolCall of toolCallsToCheck) {
160
+ const loopDetected = this.loopDetectionService.checkToolCallLoop(toolCall.name, toolCall.args);
161
+ if (loopDetected) {
162
+ this.completed = true;
163
+ this.finalMessage = `Loop Detected: The agent is stuck in a loop of identical tool calls (${toolCall.name}). Execution stopped to prevent infinite recurrence.`;
164
+ return [{
165
+ role: 'tool',
166
+ tool_call_id: 'system-loop-detection', // Virtual ID
167
+ content: JSON.stringify({ error: this.finalMessage })
168
+ }];
169
+ }
170
+ }
171
+ }
145
172
  // Second pass: Execute tools sequentially (one by one)
146
173
  for (const item of toolsToExecute) {
147
174
  try {
@@ -149,7 +176,7 @@ class ResponseExecutor {
149
176
  let [serverName] = item.toolName.replace('--', ':').split(':');
150
177
  // codebolt.chat.sendMessage(`tool call ${serverName} ${item.toolName} ${item.toolInput}`, {});
151
178
  if (serverName == 'subagent') {
152
- const agentResponse = await codeboltjs_1.default.agent.startAgent(item.toolName.replace("subagent--", ''), item.toolInput.task);
179
+ await codeboltjs_1.default.agent.startAgent(item.toolName.replace("subagent--", ''), item.toolInput.task);
153
180
  const [didUserReject, result] = [false, "tool result is successful"];
154
181
  let toolResult = this.parseToolResult(item.toolUseId, result);
155
182
  // Handle side effects (fallback messages)
@@ -169,14 +196,6 @@ class ResponseExecutor {
169
196
  });
170
197
  }
171
198
  else if (item.toolName == "codebolt--thread_management") {
172
- codeboltjs_1.default.chat.sendMessage(JSON.stringify({
173
- title: item.toolInput.title || item.toolInput.task || 'Background Thread',
174
- description: item.toolInput.description || item.toolInput.task || '',
175
- userMessage: item.toolInput.task || item.toolInput.userMessage || '',
176
- selectedAgent: item.toolInput.selectedAgent,
177
- isGrouped: item.toolInput.isGrouped,
178
- groupId: item.toolInput.groupId,
179
- }));
180
199
  const response = await codeboltjs_1.default.thread.createThreadInBackground({
181
200
  title: item.toolInput.title || item.toolInput.task || 'Background Thread',
182
201
  description: item.toolInput.description || item.toolInput.task || '',
@@ -282,9 +301,12 @@ class ResponseExecutor {
282
301
  * @returns Promise with tuple [userRejected, result]
283
302
  */
284
303
  async executeTool(toolName, toolInput) {
304
+ var _a, _b;
285
305
  //codebolttools--readfile
286
306
  // console.log("Executing tool: ", toolName, toolInput);
287
- const [toolboxName, actualToolName] = toolName.split('--');
307
+ const parts = toolName.split('--');
308
+ const toolboxName = (_a = parts[0]) !== null && _a !== void 0 ? _a : '';
309
+ const actualToolName = (_b = parts[1]) !== null && _b !== void 0 ? _b : '';
288
310
  // console.log("Toolbox name: ", toolboxName, "Actual tool name: ", actualToolName);
289
311
  const { data } = await codeboltjs_1.default.mcp.executeTool(toolboxName, actualToolName, toolInput);
290
312
  // console.log("Tool result: ", data);
@@ -14,6 +14,7 @@ export { createDefaultMessageProcessor } from './base/create/createInitialPrompt
14
14
  export { InitialPromptGenerator } from './base/initialPromptGenerator';
15
15
  export { AgentStep } from './base/agentStep';
16
16
  export { ResponseExecutor } from './base/responseExecutor';
17
+ export { LoopDetectionService, LoopType } from './services/LoopDetectionService';
17
18
  export { Agent } from './agent/agent';
18
19
  export { CodeboltAgent, createCodeboltAgent, type CodeboltAgentConfig } from './agent/codeboltAgent';
19
20
  export { Tool, createTool } from './agent/tools';
@@ -10,7 +10,7 @@
10
10
  * The framework is designed to be modular, extensible, and easy to use.
11
11
  */
12
12
  Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.Workflow = exports.createTool = exports.Tool = exports.createCodeboltAgent = exports.CodeboltAgent = exports.Agent = exports.ResponseExecutor = exports.AgentStep = exports.InitialPromptGenerator = exports.createDefaultMessageProcessor = exports.UnifiedToolExecutionError = exports.UnifiedResponseExecutionError = exports.UnifiedStepExecutionError = exports.UnifiedMessageProcessingError = exports.UnifiedAgentError = void 0;
13
+ exports.Workflow = exports.createTool = exports.Tool = exports.createCodeboltAgent = exports.CodeboltAgent = exports.Agent = exports.LoopType = exports.LoopDetectionService = exports.ResponseExecutor = exports.AgentStep = exports.InitialPromptGenerator = exports.createDefaultMessageProcessor = exports.UnifiedToolExecutionError = exports.UnifiedResponseExecutionError = exports.UnifiedStepExecutionError = exports.UnifiedMessageProcessingError = exports.UnifiedAgentError = void 0;
14
14
  // Error types
15
15
  var types_1 = require("./types/types");
16
16
  Object.defineProperty(exports, "UnifiedAgentError", { enumerable: true, get: function () { return types_1.UnifiedAgentError; } });
@@ -27,6 +27,9 @@ var agentStep_1 = require("./base/agentStep");
27
27
  Object.defineProperty(exports, "AgentStep", { enumerable: true, get: function () { return agentStep_1.AgentStep; } });
28
28
  var responseExecutor_1 = require("./base/responseExecutor");
29
29
  Object.defineProperty(exports, "ResponseExecutor", { enumerable: true, get: function () { return responseExecutor_1.ResponseExecutor; } });
30
+ var LoopDetectionService_1 = require("./services/LoopDetectionService");
31
+ Object.defineProperty(exports, "LoopDetectionService", { enumerable: true, get: function () { return LoopDetectionService_1.LoopDetectionService; } });
32
+ Object.defineProperty(exports, "LoopType", { enumerable: true, get: function () { return LoopDetectionService_1.LoopType; } });
30
33
  // Agent framework components
31
34
  var agent_1 = require("./agent/agent");
32
35
  Object.defineProperty(exports, "Agent", { enumerable: true, get: function () { return agent_1.Agent; } });
@@ -0,0 +1,44 @@
1
+ export declare enum LoopType {
2
+ CONSECUTIVE_IDENTICAL_TOOL_CALLS = "CONSECUTIVE_IDENTICAL_TOOL_CALLS",
3
+ CHANTING_IDENTICAL_SENTENCES = "CHANTING_IDENTICAL_SENTENCES"
4
+ }
5
+ export interface LoopDetectedEvent {
6
+ type: LoopType;
7
+ threshold: number;
8
+ count: number;
9
+ }
10
+ export interface LoopDetectionOptions {
11
+ toolCallLoopThreshold?: number;
12
+ contentLoopThreshold?: number;
13
+ debug?: boolean;
14
+ }
15
+ /**
16
+ * Service for detecting and preventing infinite loops in AI responses.
17
+ * Monitors tool call repetitions and content sentence repetitions.
18
+ *
19
+ * Ported from gemini-cli/packages/core/src/services/loopDetectionService.ts
20
+ */
21
+ export declare class LoopDetectionService {
22
+ private readonly toolCallLoopThreshold;
23
+ private readonly debug;
24
+ private lastToolCallKey;
25
+ private toolCallRepetitionCount;
26
+ private loopDetected;
27
+ constructor(options?: LoopDetectionOptions);
28
+ /**
29
+ * Resets the loop detection state. Call this when a "fresh" start is needed
30
+ * or a user explicitly interrupts.
31
+ */
32
+ reset(): void;
33
+ /**
34
+ * Generates a unique hash for a tool call based on name and arguments.
35
+ */
36
+ private getToolCallKey;
37
+ /**
38
+ * Checks if the given tool call constitutes a loop.
39
+ * @param toolName Name of the tool
40
+ * @param toolArgs Arguments passed to the tool
41
+ * @returns LoopDetectedEvent if a loop is detected, null otherwise
42
+ */
43
+ checkToolCallLoop(toolName: string, toolArgs: any): LoopDetectedEvent | null;
44
+ }
@@ -0,0 +1,79 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.LoopDetectionService = exports.LoopType = void 0;
4
+ const node_crypto_1 = require("node:crypto");
5
+ var LoopType;
6
+ (function (LoopType) {
7
+ LoopType["CONSECUTIVE_IDENTICAL_TOOL_CALLS"] = "CONSECUTIVE_IDENTICAL_TOOL_CALLS";
8
+ LoopType["CHANTING_IDENTICAL_SENTENCES"] = "CHANTING_IDENTICAL_SENTENCES";
9
+ })(LoopType || (exports.LoopType = LoopType = {}));
10
+ /**
11
+ * Service for detecting and preventing infinite loops in AI responses.
12
+ * Monitors tool call repetitions and content sentence repetitions.
13
+ *
14
+ * Ported from gemini-cli/packages/core/src/services/loopDetectionService.ts
15
+ */
16
+ class LoopDetectionService {
17
+ constructor(options = {}) {
18
+ // State
19
+ this.lastToolCallKey = null;
20
+ this.toolCallRepetitionCount = 0;
21
+ this.loopDetected = false;
22
+ this.toolCallLoopThreshold = options.toolCallLoopThreshold || 5;
23
+ this.debug = options.debug || false;
24
+ }
25
+ /**
26
+ * Resets the loop detection state. Call this when a "fresh" start is needed
27
+ * or a user explicitly interrupts.
28
+ */
29
+ reset() {
30
+ this.lastToolCallKey = null;
31
+ this.toolCallRepetitionCount = 0;
32
+ this.loopDetected = false;
33
+ }
34
+ /**
35
+ * Generates a unique hash for a tool call based on name and arguments.
36
+ */
37
+ getToolCallKey(toolName, toolArgs) {
38
+ const argsString = typeof toolArgs === 'string' ? toolArgs : JSON.stringify(toolArgs);
39
+ const keyString = `${toolName}:${argsString}`;
40
+ return (0, node_crypto_1.createHash)('sha256').update(keyString).digest('hex');
41
+ }
42
+ /**
43
+ * Checks if the given tool call constitutes a loop.
44
+ * @param toolName Name of the tool
45
+ * @param toolArgs Arguments passed to the tool
46
+ * @returns LoopDetectedEvent if a loop is detected, null otherwise
47
+ */
48
+ checkToolCallLoop(toolName, toolArgs) {
49
+ if (this.loopDetected) {
50
+ // Already caught a loop, stick to it until reset
51
+ return {
52
+ type: LoopType.CONSECUTIVE_IDENTICAL_TOOL_CALLS,
53
+ threshold: this.toolCallLoopThreshold,
54
+ count: this.toolCallRepetitionCount
55
+ };
56
+ }
57
+ const key = this.getToolCallKey(toolName, toolArgs);
58
+ if (this.lastToolCallKey === key) {
59
+ this.toolCallRepetitionCount++;
60
+ }
61
+ else {
62
+ this.lastToolCallKey = key;
63
+ this.toolCallRepetitionCount = 1;
64
+ }
65
+ if (this.toolCallRepetitionCount >= this.toolCallLoopThreshold) {
66
+ this.loopDetected = true;
67
+ if (this.debug) {
68
+ console.warn(`[LoopDetection] Detected consecutive identical tool calls: ${toolName} (${this.toolCallRepetitionCount})`);
69
+ }
70
+ return {
71
+ type: LoopType.CONSECUTIVE_IDENTICAL_TOOL_CALLS,
72
+ threshold: this.toolCallLoopThreshold,
73
+ count: this.toolCallRepetitionCount
74
+ };
75
+ }
76
+ return null;
77
+ }
78
+ }
79
+ exports.LoopDetectionService = LoopDetectionService;
@@ -1,4 +1,23 @@
1
- import type { UnifiedAgentConfig } from '../types/types';
1
+ /**
2
+ * Configuration for unified agent - defined locally as it's not exported from types
3
+ */
4
+ export interface UnifiedAgentConfig {
5
+ maxIterations?: number;
6
+ maxConversationLength?: number;
7
+ enableLogging?: boolean;
8
+ llmConfig?: {
9
+ llmname?: string;
10
+ model?: string;
11
+ temperature?: number;
12
+ maxTokens?: number;
13
+ apiKey?: string;
14
+ baseUrl?: string;
15
+ };
16
+ retryConfig?: {
17
+ maxRetries?: number;
18
+ retryDelay?: number;
19
+ };
20
+ }
2
21
  /**
3
22
  * Advanced agent creation with full configuration
4
23
  */
@@ -1,4 +1,5 @@
1
1
  "use strict";
2
+ // Utility exports for the unified agent framework
2
3
  Object.defineProperty(exports, "__esModule", { value: true });
3
4
  exports.validateAgentConfig = validateAgentConfig;
4
5
  exports.benchmarkAgent = benchmarkAgent;
@@ -201,13 +202,16 @@ async function benchmarkAgent(agent, testCases) {
201
202
  }
202
203
  const duration = Date.now() - startTime;
203
204
  totalDuration += duration;
204
- results.push({
205
+ const resultEntry = {
205
206
  name: testCase.name,
206
207
  success,
207
208
  duration,
208
- output,
209
- error
210
- });
209
+ output
210
+ };
211
+ if (error !== undefined) {
212
+ resultEntry.error = error;
213
+ }
214
+ results.push(resultEntry);
211
215
  }
212
216
  const summary = {
213
217
  totalTests: testCases.length,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@codebolt/agent",
3
- "version": "5.0.7",
3
+ "version": "5.0.8",
4
4
  "description": "CodeBolt Agent utilities for building and managing AI agents",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -30,10 +30,10 @@
30
30
  "dependencies": {
31
31
  "js-yaml": "^4.1.0",
32
32
  "zod": "^3.22.4",
33
- "@codebolt/types": "5.0.7"
33
+ "@codebolt/types": "5.0.8"
34
34
  },
35
35
  "peerDependencies": {
36
- "@codebolt/codeboltjs": "5.0.7"
36
+ "@codebolt/codeboltjs": "5.0.8"
37
37
  },
38
38
  "devDependencies": {
39
39
  "@types/js-yaml": "^4.0.9",
@@ -43,8 +43,8 @@
43
43
  "typedoc": "0.28.16",
44
44
  "typedoc-plugin-markdown": "4.9.0",
45
45
  "typescript": "^5.4.5",
46
- "@codebolt/types": "5.0.7",
47
- "@codebolt/codeboltjs": "5.0.7"
46
+ "@codebolt/codeboltjs": "5.0.8",
47
+ "@codebolt/types": "5.0.8"
48
48
  },
49
49
  "exports": {
50
50
  "./builder": {