@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.
- package/README.md +118 -153
- package/dist/index.d.ts +2 -0
- package/dist/index.js +41 -0
- package/dist/processor-pieces/messageModifiers/chatHistoryMessageModifier.js +2 -4
- package/dist/processor-pieces/messageModifiers/contextAssemblyModifier.d.ts +81 -0
- package/dist/processor-pieces/messageModifiers/contextAssemblyModifier.js +316 -0
- package/dist/processor-pieces/messageModifiers/coreSystemPromptModifier.js +2 -19
- package/dist/processor-pieces/messageModifiers/directoryContextModifier.js +2 -6
- package/dist/processor-pieces/messageModifiers/environmentContextModifier.js +2 -7
- package/dist/processor-pieces/messageModifiers/ideContextModifier.js +2 -21
- package/dist/processor-pieces/messageModifiers/index.d.ts +3 -0
- package/dist/processor-pieces/messageModifiers/index.js +7 -1
- package/dist/processor-pieces/messageModifiers/toolInjectionModifier.js +2 -1
- package/dist/processor-pieces/postToolCallProcessors/conversationCompactorModifier.d.ts +34 -5
- package/dist/processor-pieces/postToolCallProcessors/conversationCompactorModifier.js +374 -89
- package/dist/processor-pieces/preInferenceProcessors/chatCompressionModifier.d.ts +3 -0
- package/dist/processor-pieces/preInferenceProcessors/chatCompressionModifier.js +50 -27
- package/dist/unified/agent/agent.d.ts +10 -0
- package/dist/unified/agent/agent.js +198 -10
- package/dist/unified/agent/codeboltAgent.d.ts +19 -100
- package/dist/unified/agent/codeboltAgent.js +209 -109
- package/dist/unified/base/agentStep.js +17 -17
- package/dist/unified/base/initialPromptGenerator.js +13 -31
- package/dist/unified/base/promptContext.d.ts +13 -0
- package/dist/unified/base/promptContext.js +213 -0
- package/dist/unified/base/responseExecutor.d.ts +7 -19
- package/dist/unified/base/responseExecutor.js +280 -259
- package/dist/unified/index.d.ts +9 -0
- package/dist/unified/index.js +20 -13
- package/dist/unified/services/CompressionCoordinator.d.ts +67 -0
- package/dist/unified/services/CompressionCoordinator.js +214 -0
- package/dist/unified/services/compaction/autoCompact.d.ts +52 -0
- package/dist/unified/services/compaction/autoCompact.js +294 -0
- package/dist/unified/services/compaction/compactionOrchestrator.d.ts +78 -0
- package/dist/unified/services/compaction/compactionOrchestrator.js +230 -0
- package/dist/unified/services/compaction/contextCollapse.d.ts +63 -0
- package/dist/unified/services/compaction/contextCollapse.js +291 -0
- package/dist/unified/services/compaction/microCompact.d.ts +34 -0
- package/dist/unified/services/compaction/microCompact.js +195 -0
- package/dist/unified/services/compaction/postCompactCleanup.d.ts +15 -0
- package/dist/unified/services/compaction/postCompactCleanup.js +37 -0
- package/dist/unified/services/compaction/reactiveCompact.d.ts +65 -0
- package/dist/unified/services/compaction/reactiveCompact.js +301 -0
- package/dist/unified/services/compaction/snipCompact.d.ts +31 -0
- package/dist/unified/services/compaction/snipCompact.js +124 -0
- package/dist/unified/services/compaction/types.d.ts +66 -0
- package/dist/unified/services/compaction/types.js +39 -0
- package/package.json +25 -29
|
@@ -51,19 +51,8 @@ function isFunctionResponse(message) {
|
|
|
51
51
|
}
|
|
52
52
|
return false;
|
|
53
53
|
}
|
|
54
|
-
|
|
55
|
-
|
|
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
|
-
|
|
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
|
-
|
|
123
|
-
const
|
|
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
|
|
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 *
|
|
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(
|
|
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(
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
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;
|