@codebolt/agent 6.0.0 → 6.1.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.
Files changed (48) hide show
  1. package/README.md +118 -153
  2. package/dist/index.d.ts +2 -0
  3. package/dist/index.js +41 -0
  4. package/dist/processor-pieces/messageModifiers/chatHistoryMessageModifier.js +2 -4
  5. package/dist/processor-pieces/messageModifiers/contextAssemblyModifier.d.ts +81 -0
  6. package/dist/processor-pieces/messageModifiers/contextAssemblyModifier.js +316 -0
  7. package/dist/processor-pieces/messageModifiers/coreSystemPromptModifier.js +2 -19
  8. package/dist/processor-pieces/messageModifiers/directoryContextModifier.js +2 -6
  9. package/dist/processor-pieces/messageModifiers/environmentContextModifier.js +2 -7
  10. package/dist/processor-pieces/messageModifiers/ideContextModifier.js +2 -21
  11. package/dist/processor-pieces/messageModifiers/index.d.ts +3 -0
  12. package/dist/processor-pieces/messageModifiers/index.js +7 -1
  13. package/dist/processor-pieces/messageModifiers/toolInjectionModifier.js +2 -1
  14. package/dist/processor-pieces/postToolCallProcessors/conversationCompactorModifier.d.ts +34 -5
  15. package/dist/processor-pieces/postToolCallProcessors/conversationCompactorModifier.js +374 -89
  16. package/dist/processor-pieces/preInferenceProcessors/chatCompressionModifier.d.ts +3 -0
  17. package/dist/processor-pieces/preInferenceProcessors/chatCompressionModifier.js +50 -27
  18. package/dist/unified/agent/agent.d.ts +10 -0
  19. package/dist/unified/agent/agent.js +198 -10
  20. package/dist/unified/agent/codeboltAgent.d.ts +19 -100
  21. package/dist/unified/agent/codeboltAgent.js +209 -109
  22. package/dist/unified/base/agentStep.js +17 -17
  23. package/dist/unified/base/initialPromptGenerator.js +13 -31
  24. package/dist/unified/base/promptContext.d.ts +13 -0
  25. package/dist/unified/base/promptContext.js +213 -0
  26. package/dist/unified/base/responseExecutor.d.ts +7 -19
  27. package/dist/unified/base/responseExecutor.js +280 -259
  28. package/dist/unified/index.d.ts +9 -0
  29. package/dist/unified/index.js +20 -13
  30. package/dist/unified/services/CompressionCoordinator.d.ts +67 -0
  31. package/dist/unified/services/CompressionCoordinator.js +214 -0
  32. package/dist/unified/services/compaction/autoCompact.d.ts +52 -0
  33. package/dist/unified/services/compaction/autoCompact.js +294 -0
  34. package/dist/unified/services/compaction/compactionOrchestrator.d.ts +78 -0
  35. package/dist/unified/services/compaction/compactionOrchestrator.js +230 -0
  36. package/dist/unified/services/compaction/contextCollapse.d.ts +63 -0
  37. package/dist/unified/services/compaction/contextCollapse.js +291 -0
  38. package/dist/unified/services/compaction/microCompact.d.ts +34 -0
  39. package/dist/unified/services/compaction/microCompact.js +195 -0
  40. package/dist/unified/services/compaction/postCompactCleanup.d.ts +15 -0
  41. package/dist/unified/services/compaction/postCompactCleanup.js +37 -0
  42. package/dist/unified/services/compaction/reactiveCompact.d.ts +65 -0
  43. package/dist/unified/services/compaction/reactiveCompact.js +301 -0
  44. package/dist/unified/services/compaction/snipCompact.d.ts +31 -0
  45. package/dist/unified/services/compaction/snipCompact.js +124 -0
  46. package/dist/unified/services/compaction/types.d.ts +66 -0
  47. package/dist/unified/services/compaction/types.js +39 -0
  48. package/package.json +25 -29
@@ -51,19 +51,8 @@ function isFunctionResponse(message) {
51
51
  }
52
52
  return false;
53
53
  }
54
- // Mock token limit for different models (should be replaced with actual implementation)
55
- function tokenLimit(model) {
56
- // Default token limits for common models
57
- if (model.includes('gemini-pro'))
58
- return 30720;
59
- if (model.includes('gemini-flash'))
60
- return 1048576;
61
- if (model.includes('gpt-4'))
62
- return 8192;
63
- if (model.includes('gpt-3.5'))
64
- return 4096;
65
- return 8192; // Default fallback
66
- }
54
+ /** Default model token limit when none is configured */
55
+ const DEFAULT_MODEL_TOKEN_LIMIT = 128000;
67
56
  class ChatCompressionModifier extends base_1.BasePreInferenceProcessor {
68
57
  constructor(options = {}) {
69
58
  super();
@@ -71,11 +60,50 @@ class ChatCompressionModifier extends base_1.BasePreInferenceProcessor {
71
60
  this.options = {
72
61
  contextPercentageThreshold: options.contextPercentageThreshold || COMPRESSION_TOKEN_THRESHOLD,
73
62
  enableCompression: options.enableCompression !== false,
74
- force: options.force || false
63
+ force: options.force || false,
64
+ modelTokenLimit: options.modelTokenLimit || DEFAULT_MODEL_TOKEN_LIMIT
65
+ };
66
+ }
67
+ buildCompressionMetadata(compressionInfo, stage) {
68
+ var _a;
69
+ return {
70
+ status: (_a = CompressionStatus[compressionInfo.compressionStatus]) !== null && _a !== void 0 ? _a : 'NOOP',
71
+ stage,
72
+ originalTokenCount: compressionInfo.originalTokenCount,
73
+ newTokenCount: compressionInfo.newTokenCount,
74
+ timestamp: new Date().toISOString(),
75
+ strategy: 'summarize',
76
+ failedAttempts: this.hasFailedCompressionAttempt ? 1 : 0,
75
77
  };
76
78
  }
77
79
  async modify(_originalRequest, createdMessage) {
80
+ var _a, _b, _c;
78
81
  try {
82
+ // Check if ConversationCompactorModifier already compressed in the previous iteration.
83
+ // If so, skip re-compression unless token count has grown past the threshold again.
84
+ const compressionMeta = (_a = createdMessage.metadata) === null || _a === void 0 ? void 0 : _a['compression'];
85
+ if ((compressionMeta === null || compressionMeta === void 0 ? void 0 : compressionMeta.status) === 'COMPRESSED' &&
86
+ compressionMeta.stage !== 'reactive_force_compact') {
87
+ const modelTokenLimit = this.options.modelTokenLimit || DEFAULT_MODEL_TOKEN_LIMIT;
88
+ const threshold = ((_b = this.options.contextPercentageThreshold) !== null && _b !== void 0 ? _b : COMPRESSION_TOKEN_THRESHOLD) * modelTokenLimit;
89
+ const currentTokens = (_c = compressionMeta.newTokenCount) !== null && _c !== void 0 ? _c : 0;
90
+ if (currentTokens < threshold) {
91
+ // Already compressed and still under threshold — skip
92
+ return {
93
+ ...createdMessage,
94
+ metadata: {
95
+ ...createdMessage.metadata,
96
+ compression: this.buildCompressionMetadata({
97
+ originalTokenCount: currentTokens,
98
+ newTokenCount: currentTokens,
99
+ compressionStatus: CompressionStatus.NOOP,
100
+ }, 'pre_inference'),
101
+ chatCompressionSkipped: true,
102
+ chatCompressionSkipReason: 'Already compressed by ConversationCompactorModifier'
103
+ }
104
+ };
105
+ }
106
+ }
79
107
  const compressionResult = await this.tryCompressChat(createdMessage.message.messages, this.options.force || false);
80
108
  if (compressionResult.compressionStatus === CompressionStatus.COMPRESSED) {
81
109
  return {
@@ -85,10 +113,8 @@ class ChatCompressionModifier extends base_1.BasePreInferenceProcessor {
85
113
  },
86
114
  metadata: {
87
115
  ...createdMessage.metadata,
116
+ compression: this.buildCompressionMetadata(compressionResult, 'pre_inference'),
88
117
  chatCompressed: true,
89
- originalTokenCount: compressionResult.originalTokenCount,
90
- newTokenCount: compressionResult.newTokenCount,
91
- compressionStatus: compressionResult.compressionStatus
92
118
  }
93
119
  };
94
120
  }
@@ -96,9 +122,7 @@ class ChatCompressionModifier extends base_1.BasePreInferenceProcessor {
96
122
  ...createdMessage,
97
123
  metadata: {
98
124
  ...createdMessage.metadata,
99
- compressionStatus: compressionResult.compressionStatus,
100
- originalTokenCount: compressionResult.originalTokenCount,
101
- newTokenCount: compressionResult.newTokenCount
125
+ compression: this.buildCompressionMetadata(compressionResult, 'pre_inference'),
102
126
  }
103
127
  };
104
128
  }
@@ -119,11 +143,10 @@ class ChatCompressionModifier extends base_1.BasePreInferenceProcessor {
119
143
  compressionStatus: CompressionStatus.NOOP,
120
144
  };
121
145
  }
122
- // Mock model - should be replaced with actual model detection
123
- const model = "gemini-pro";
124
- const originalTokenCount = await this.countTokens(model, curatedHistory);
146
+ const modelTokenLimit = this.options.modelTokenLimit || DEFAULT_MODEL_TOKEN_LIMIT;
147
+ const originalTokenCount = await this.countTokens(curatedHistory);
125
148
  if (originalTokenCount === undefined) {
126
- console.warn(`Could not determine token count for model ${model}.`);
149
+ console.warn(`Could not determine token count.`);
127
150
  this.hasFailedCompressionAttempt = !force && true;
128
151
  return {
129
152
  originalTokenCount: 0,
@@ -135,7 +158,7 @@ class ChatCompressionModifier extends base_1.BasePreInferenceProcessor {
135
158
  // Don't compress if not forced and we are under the limit.
136
159
  if (!force) {
137
160
  const threshold = contextPercentageThreshold !== null && contextPercentageThreshold !== void 0 ? contextPercentageThreshold : COMPRESSION_TOKEN_THRESHOLD;
138
- if (originalTokenCount < threshold * tokenLimit(model)) {
161
+ if (originalTokenCount < threshold * modelTokenLimit) {
139
162
  return {
140
163
  originalTokenCount,
141
164
  newTokenCount: originalTokenCount,
@@ -168,7 +191,7 @@ class ChatCompressionModifier extends base_1.BasePreInferenceProcessor {
168
191
  },
169
192
  ...historyToKeep,
170
193
  ];
171
- const newTokenCount = await this.countTokens(model, compressedMessages);
194
+ const newTokenCount = await this.countTokens(compressedMessages);
172
195
  if (newTokenCount === undefined) {
173
196
  console.warn('Could not determine compressed history token count.');
174
197
  this.hasFailedCompressionAttempt = !force && true;
@@ -193,7 +216,7 @@ class ChatCompressionModifier extends base_1.BasePreInferenceProcessor {
193
216
  compressedMessages,
194
217
  };
195
218
  }
196
- async countTokens(_model, messages) {
219
+ async countTokens(messages) {
197
220
  // Mock token counting - should be replaced with actual API call
198
221
  // Rough approximation: 4 characters per token
199
222
  const totalCharacters = messages.reduce((sum, msg) => {
@@ -8,10 +8,20 @@ export declare class Agent implements AgentInterface {
8
8
  private readonly preToolCallProcessors;
9
9
  private readonly postToolCallProcessors;
10
10
  private readonly enableLogging;
11
+ private readonly compactionOrchestrator;
12
+ private readonly loopDetectionService;
13
+ private readonly maxTurns;
11
14
  constructor(config: AgentConfig);
12
15
  execute(reqMessage: FlatUserMessage): Promise<{
13
16
  success: boolean;
14
17
  result: any;
15
18
  error?: string;
16
19
  }>;
20
+ private applyCompaction;
21
+ private tryRecoverPrompt;
22
+ private refreshAvailableTools;
23
+ private mergeTools;
24
+ private getAllowedToolNames;
25
+ private getRecoverableResponseError;
26
+ private collectResponseMessages;
17
27
  }
@@ -1,12 +1,19 @@
1
1
  "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
2
5
  Object.defineProperty(exports, "__esModule", { value: true });
3
6
  exports.Agent = void 0;
7
+ const codeboltjs_1 = __importDefault(require("@codebolt/codeboltjs"));
4
8
  const base_1 = require("../base");
5
- const responseExecutor_1 = require("../base/responseExecutor");
6
9
  const agentStep_1 = require("../base/agentStep");
10
+ const responseExecutor_1 = require("../base/responseExecutor");
11
+ const promptContext_1 = require("../base/promptContext");
12
+ const compactionOrchestrator_1 = require("../services/compaction/compactionOrchestrator");
7
13
  class Agent {
8
14
  constructor(config) {
9
- var _a, _b, _c, _d, _e;
15
+ var _a, _b, _c, _d, _e, _f;
16
+ const runtimeConfig = config;
10
17
  this.config = { ...config };
11
18
  this.messageModifiers = ((_a = config.processors) === null || _a === void 0 ? void 0 : _a.messageModifiers) || [];
12
19
  this.preInferenceProcessors = ((_b = config.processors) === null || _b === void 0 ? void 0 : _b.preInferenceProcessors) || [];
@@ -14,6 +21,9 @@ class Agent {
14
21
  this.preToolCallProcessors = ((_d = config.processors) === null || _d === void 0 ? void 0 : _d.preToolCallProcessors) || [];
15
22
  this.postToolCallProcessors = ((_e = config.processors) === null || _e === void 0 ? void 0 : _e.postToolCallProcessors) || [];
16
23
  this.enableLogging = config.enableLogging !== false;
24
+ this.compactionOrchestrator = new compactionOrchestrator_1.CompactionOrchestrator(runtimeConfig.compaction || {});
25
+ this.loopDetectionService = runtimeConfig.loopDetectionService;
26
+ this.maxTurns = (_f = runtimeConfig.maxTurns) !== null && _f !== void 0 ? _f : 25;
17
27
  }
18
28
  async execute(reqMessage) {
19
29
  if (!reqMessage) {
@@ -31,19 +41,51 @@ class Agent {
31
41
  });
32
42
  let prompt = await promptGenerator.processMessage(reqMessage);
33
43
  let completed = false;
44
+ let turnNumber = 0;
34
45
  while (!completed) {
46
+ turnNumber += 1;
47
+ if (turnNumber > this.maxTurns) {
48
+ throw new Error(`Agent exceeded the maximum turn limit of ${this.maxTurns}.`);
49
+ }
50
+ this.compactionOrchestrator.resetForTurn();
51
+ prompt = await this.applyCompaction(prompt);
52
+ prompt = await this.refreshAvailableTools(reqMessage, prompt);
35
53
  const agentStep = new agentStep_1.AgentStep({
36
54
  preInferenceProcessors: this.preInferenceProcessors,
37
55
  postInferenceProcessors: this.postInferenceProcessors
38
56
  });
39
- const stepResult = await agentStep.executeStep(reqMessage, prompt);
40
- prompt = stepResult.nextMessage;
41
- if (this.enableLogging) {
42
- // console.log('[Agent] Step completed, processing response');
57
+ let stepResult;
58
+ while (!stepResult) {
59
+ try {
60
+ const nextStepResult = await agentStep.executeStep(reqMessage, prompt);
61
+ const recoverableResponseError = this.getRecoverableResponseError(nextStepResult.rawLLMResponse);
62
+ if (!recoverableResponseError) {
63
+ stepResult = nextStepResult;
64
+ break;
65
+ }
66
+ const recoveredPrompt = await this.tryRecoverPrompt(prompt, new Error(recoverableResponseError));
67
+ if (!recoveredPrompt) {
68
+ throw new Error(recoverableResponseError);
69
+ }
70
+ prompt = recoveredPrompt;
71
+ }
72
+ catch (error) {
73
+ const recoveredPrompt = await this.tryRecoverPrompt(prompt, error);
74
+ if (!recoveredPrompt) {
75
+ throw error;
76
+ }
77
+ prompt = recoveredPrompt;
78
+ }
79
+ }
80
+ if (!stepResult) {
81
+ throw new Error('Agent step did not produce a response.');
43
82
  }
44
83
  const responseExecutor = new responseExecutor_1.ResponseExecutor({
45
84
  preToolCallProcessors: this.preToolCallProcessors,
46
- postToolCallProcessors: this.postToolCallProcessors
85
+ postToolCallProcessors: this.postToolCallProcessors,
86
+ ...(this.loopDetectionService
87
+ ? { loopDetectionService: this.loopDetectionService }
88
+ : {}),
47
89
  });
48
90
  const executionResult = await responseExecutor.executeResponse({
49
91
  initialUserMessage: reqMessage,
@@ -54,9 +96,6 @@ class Agent {
54
96
  completed = executionResult.completed;
55
97
  prompt = executionResult.nextMessage;
56
98
  }
57
- if (this.enableLogging) {
58
- // console.log('[Agent] Execution completed successfully');
59
- }
60
99
  return {
61
100
  success: true,
62
101
  result: prompt
@@ -74,5 +113,154 @@ class Agent {
74
113
  };
75
114
  }
76
115
  }
116
+ async applyCompaction(prompt) {
117
+ const result = await this.compactionOrchestrator.compact((0, promptContext_1.getTranscriptMessages)(prompt));
118
+ if (!result.wasCompacted) {
119
+ return prompt;
120
+ }
121
+ return {
122
+ ...(0, promptContext_1.replaceTranscriptMessages)(prompt, result.messages),
123
+ metadata: {
124
+ ...prompt.metadata,
125
+ compaction: {
126
+ totalTokensFreed: result.totalTokensFreed,
127
+ layersApplied: result.layersApplied,
128
+ boundaries: result.boundaries,
129
+ timestamp: new Date().toISOString(),
130
+ },
131
+ },
132
+ };
133
+ }
134
+ async tryRecoverPrompt(prompt, error) {
135
+ const errorMessage = error instanceof Error ? error.message : String(error);
136
+ if (!this.compactionOrchestrator.getReactiveLayer().isRecoverableError(errorMessage)) {
137
+ return null;
138
+ }
139
+ const recovery = await this.compactionOrchestrator.recoverFromError((0, promptContext_1.getTranscriptMessages)(prompt), error);
140
+ if (!recovery.wasCompacted) {
141
+ return null;
142
+ }
143
+ return {
144
+ ...(0, promptContext_1.replaceTranscriptMessages)(prompt, recovery.messages),
145
+ metadata: {
146
+ ...prompt.metadata,
147
+ reactiveCompaction: {
148
+ totalTokensFreed: recovery.totalTokensFreed,
149
+ layersApplied: recovery.layersApplied,
150
+ boundaries: recovery.boundaries,
151
+ timestamp: new Date().toISOString(),
152
+ error: errorMessage,
153
+ },
154
+ },
155
+ };
156
+ }
157
+ async refreshAvailableTools(originalRequest, prompt) {
158
+ var _a, _b, _c, _d;
159
+ if (((_a = prompt.metadata) === null || _a === void 0 ? void 0 : _a['toolsInjected']) !== true ||
160
+ ((_b = prompt.metadata) === null || _b === void 0 ? void 0 : _b['toolsLocation']) !== 'Tool') {
161
+ return prompt;
162
+ }
163
+ const existingTools = Array.isArray(prompt.message.tools)
164
+ ? prompt.message.tools
165
+ : [];
166
+ try {
167
+ const toolsResponse = await codeboltjs_1.default.mcp.listMcpFromServers(['codebolt']);
168
+ let refreshedTools = ((_c = toolsResponse === null || toolsResponse === void 0 ? void 0 : toolsResponse.data) === null || _c === void 0 ? void 0 : _c.tools) || (toolsResponse === null || toolsResponse === void 0 ? void 0 : toolsResponse.data) || [];
169
+ const mentionedMCPs = Array.isArray(originalRequest.mentionedMCPs)
170
+ ? originalRequest.mentionedMCPs
171
+ : [];
172
+ if (mentionedMCPs.length > 0) {
173
+ const { data: mentionedTools } = await codeboltjs_1.default.mcp.getTools(mentionedMCPs);
174
+ refreshedTools = [...refreshedTools, ...(mentionedTools || [])];
175
+ }
176
+ const allowedToolNames = this.getAllowedToolNames(prompt);
177
+ if (allowedToolNames && allowedToolNames.length > 0) {
178
+ const allowed = new Set(allowedToolNames);
179
+ refreshedTools = refreshedTools.filter((tool) => { var _a; return !!((_a = tool.function) === null || _a === void 0 ? void 0 : _a.name) && allowed.has(tool.function.name); });
180
+ }
181
+ const mergedTools = this.mergeTools(existingTools, refreshedTools);
182
+ return {
183
+ ...prompt,
184
+ message: {
185
+ ...prompt.message,
186
+ tools: mergedTools,
187
+ ...(mergedTools.length > 0
188
+ ? { tool_choice: (_d = prompt.message.tool_choice) !== null && _d !== void 0 ? _d : 'auto' }
189
+ : {}),
190
+ },
191
+ metadata: {
192
+ ...prompt.metadata,
193
+ toolsCount: mergedTools.length,
194
+ toolsRefreshedAt: new Date().toISOString(),
195
+ },
196
+ };
197
+ }
198
+ catch (error) {
199
+ if (this.enableLogging) {
200
+ console.error('[Agent] Failed to refresh tools:', error);
201
+ }
202
+ return prompt;
203
+ }
204
+ }
205
+ mergeTools(existingTools, refreshedTools) {
206
+ var _a, _b;
207
+ const mergedTools = new Map();
208
+ for (const tool of refreshedTools) {
209
+ const toolName = (_a = tool.function) === null || _a === void 0 ? void 0 : _a.name;
210
+ if (toolName) {
211
+ mergedTools.set(toolName, tool);
212
+ }
213
+ }
214
+ for (const tool of existingTools) {
215
+ const toolName = (_b = tool.function) === null || _b === void 0 ? void 0 : _b.name;
216
+ if (toolName && !mergedTools.has(toolName)) {
217
+ mergedTools.set(toolName, tool);
218
+ }
219
+ }
220
+ return Array.from(mergedTools.values());
221
+ }
222
+ getAllowedToolNames(prompt) {
223
+ var _a;
224
+ const metadataAllowedTools = (_a = prompt.metadata) === null || _a === void 0 ? void 0 : _a['allowedTools'];
225
+ if (!Array.isArray(metadataAllowedTools)) {
226
+ return undefined;
227
+ }
228
+ const allowedToolNames = metadataAllowedTools.filter((toolName) => typeof toolName === 'string' && toolName.length > 0);
229
+ return allowedToolNames.length > 0 ? allowedToolNames : undefined;
230
+ }
231
+ getRecoverableResponseError(response) {
232
+ var _a, _b, _c, _d;
233
+ const reactiveLayer = this.compactionOrchestrator.getReactiveLayer();
234
+ const candidateMessages = this.collectResponseMessages(response);
235
+ const recoverableMessage = candidateMessages.find((message) => reactiveLayer.isRecoverableError(message));
236
+ if (recoverableMessage) {
237
+ return recoverableMessage;
238
+ }
239
+ const finishReasons = [
240
+ response.finish_reason,
241
+ ...((_a = response.choices) !== null && _a !== void 0 ? _a : []).map((choice) => choice.finish_reason),
242
+ ].filter((reason) => typeof reason === 'string');
243
+ const hasLengthFinishReason = finishReasons.some((reason) => reason.toLowerCase() === 'length');
244
+ const hasToolCalls = ((_c = (_b = response.tool_calls) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) > 0 ||
245
+ ((_d = response.choices) !== null && _d !== void 0 ? _d : []).some((choice) => { var _a, _b, _c; return ((_c = (_b = (_a = choice.message) === null || _a === void 0 ? void 0 : _a.tool_calls) === null || _b === void 0 ? void 0 : _b.length) !== null && _c !== void 0 ? _c : 0) > 0; });
246
+ if (hasLengthFinishReason && candidateMessages.length === 0 && !hasToolCalls) {
247
+ return 'Too many tokens or token limit reached before producing usable output.';
248
+ }
249
+ return null;
250
+ }
251
+ collectResponseMessages(response) {
252
+ var _a, _b;
253
+ const messages = [];
254
+ if (typeof response.content === 'string' && response.content.trim().length > 0) {
255
+ messages.push(response.content.trim());
256
+ }
257
+ for (const choice of (_a = response.choices) !== null && _a !== void 0 ? _a : []) {
258
+ if (typeof ((_b = choice.message) === null || _b === void 0 ? void 0 : _b.content) === 'string' &&
259
+ choice.message.content.trim().length > 0) {
260
+ messages.push(choice.message.content.trim());
261
+ }
262
+ }
263
+ return messages;
264
+ }
77
265
  }
78
266
  exports.Agent = Agent;
@@ -1,77 +1,15 @@
1
1
  import { AgentConfig, MessageModifier, PostInferenceProcessor, PostToolCallProcessor, PreInferenceProcessor, PreToolCallProcessor, ProcessedMessage } from "@codebolt/types/agent";
2
2
  import { FlatUserMessage } from "@codebolt/types/sdk";
3
- /**
4
- * Configuration options for CodeboltAgent
5
- */
3
+ import { LoopDetectionService } from "../services/LoopDetectionService";
4
+ import type { CompactionOrchestratorOptions } from "../services/compaction/types";
6
5
  export interface CodeboltAgentConfig extends AgentConfig {
7
- /**
8
- * Enable logging for debugging purposes.
9
- * Defaults to true.
10
- */
11
6
  enableLogging?: boolean;
12
- /**
13
- * Agent context to continue from.
14
- * When provided, the agent will skip initial prompt generation
15
- * and continue from where the previous agent left off.
16
- */
17
7
  context?: ProcessedMessage;
18
- /**
19
- * List of allowed tool names. If provided, only these tools will be available to the agent.
20
- * If not provided, all tools will be available.
21
- * Example: ['readFile', 'writeFile', 'executeCommand']
22
- */
23
8
  allowedTools?: string[];
9
+ compaction?: CompactionOrchestratorOptions;
10
+ loopDetectionService?: LoopDetectionService;
11
+ maxTurns?: number;
24
12
  }
25
- /**
26
- * CodeboltAgent is a high-level agent class that:
27
- * - Uses InitialPromptGenerator with configurable processors/modifiers
28
- * - Runs an agent loop with AgentStep and ResponseExecutor
29
- * - Handles tool execution and conversation flow automatically
30
- * - Is triggered via processMessage (not via onMessage listener)
31
- *
32
- * @example
33
- * ```typescript
34
- * import { CodeboltAgent } from '@codebolt/agent/unified';
35
- * import {
36
- * EnvironmentContextModifier,
37
- * CoreSystemPromptModifier,
38
- * DirectoryContextModifier,
39
- * IdeContextModifier,
40
- * AtFileProcessorModifier,
41
- * ToolInjectionModifier,
42
- * ChatHistoryMessageModifier
43
- * } from '@codebolt/agent/processor-pieces';
44
- *
45
- * const systemPrompt = `You are an AI coding assistant...`;
46
- *
47
- * const agent = new CodeboltAgent({
48
- * instructions: systemPrompt,
49
- * processors: {
50
- * messageModifiers: [
51
- * new ChatHistoryMessageModifier({ enableChatHistory: true }),
52
- * new EnvironmentContextModifier({ enableFullContext: true }),
53
- * new DirectoryContextModifier(),
54
- * new IdeContextModifier({
55
- * includeActiveFile: true,
56
- * includeOpenFiles: true,
57
- * includeCursorPosition: true,
58
- * includeSelectedText: true
59
- * }),
60
- * new CoreSystemPromptModifier({ customSystemPrompt: systemPrompt }),
61
- * new ToolInjectionModifier({ includeToolDescriptions: true }),
62
- * new AtFileProcessorModifier({ enableRecursiveSearch: true })
63
- * ],
64
- * preInferenceProcessors: [],
65
- * postInferenceProcessors: [],
66
- * preToolCallProcessors: [],
67
- * postToolCallProcessors: []
68
- * }
69
- * });
70
- *
71
- * // Process a message (triggered from graph node)
72
- * const result = await agent.processMessage(userMessage);
73
- * ```
74
- */
75
13
  export declare class CodeboltAgent {
76
14
  private readonly config;
77
15
  private readonly messageModifiers;
@@ -83,55 +21,33 @@ export declare class CodeboltAgent {
83
21
  private readonly baseSystemPrompt;
84
22
  private readonly context;
85
23
  private readonly allowedTools;
24
+ private readonly compactionOrchestrator;
25
+ private readonly loopDetectionService;
26
+ private readonly maxTurns;
86
27
  constructor(config: CodeboltAgentConfig);
87
- /**
88
- * Creates default message modifiers when none are provided
89
- */
90
28
  private createDefaultMessageModifiers;
91
- /**
92
- * Creates a default FlatUserMessage from a string
93
- */
94
29
  private createDefaultUserMessage;
95
- /**
96
- * Process a message through the agent pipeline.
97
- * This is the main entry point - triggered from graph nodes.
98
- * @param message - Either a string message or a FlatUserMessage object
99
- * @param context - Optional context from a previous agent to continue from
100
- */
101
30
  processMessage(message: string | FlatUserMessage, context?: ProcessedMessage): Promise<{
102
31
  success: boolean;
103
32
  result: any;
104
33
  context: ProcessedMessage | null;
34
+ finalMessage?: string;
105
35
  error?: string;
106
36
  }>;
107
- /**
108
- * Get the current configuration
109
- */
110
37
  getConfig(): CodeboltAgentConfig;
111
- /**
112
- * Get all message modifiers
113
- */
114
38
  getMessageModifiers(): MessageModifier[];
115
- /**
116
- * Get all pre-inference processors
117
- */
118
39
  getPreInferenceProcessors(): PreInferenceProcessor[];
119
- /**
120
- * Get all post-inference processors
121
- */
122
40
  getPostInferenceProcessors(): PostInferenceProcessor[];
123
- /**
124
- * Get all pre-tool-call processors
125
- */
126
41
  getPreToolCallProcessors(): PreToolCallProcessor[];
127
- /**
128
- * Get all post-tool-call processors
129
- */
130
42
  getPostToolCallProcessors(): PostToolCallProcessor[];
43
+ private applyCompaction;
44
+ private tryRecoverPrompt;
45
+ private refreshAvailableTools;
46
+ private mergeTools;
47
+ private getAllowedToolNames;
48
+ private getRecoverableResponseError;
49
+ private collectResponseMessages;
131
50
  }
132
- /**
133
- * Factory function to create a CodeboltAgent with common defaults
134
- */
135
51
  export declare function createCodeboltAgent(options: {
136
52
  systemPrompt: string;
137
53
  messageModifiers?: MessageModifier[];
@@ -140,4 +56,7 @@ export declare function createCodeboltAgent(options: {
140
56
  preToolCallProcessors?: PreToolCallProcessor[];
141
57
  postToolCallProcessors?: PostToolCallProcessor[];
142
58
  enableLogging?: boolean;
59
+ compaction?: CompactionOrchestratorOptions;
60
+ loopDetectionService?: LoopDetectionService;
61
+ maxTurns?: number;
143
62
  }): CodeboltAgent;