@codebolt/codeboltjs 2.0.13 → 2.0.16
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/dist/agentlib/agent.js +3 -7
- package/dist/agentlib/followupquestionbuilder.d.ts +75 -0
- package/dist/agentlib/followupquestionbuilder.js +193 -0
- package/dist/agentlib/llmoutputhandler.d.ts +102 -0
- package/dist/agentlib/llmoutputhandler.js +451 -0
- package/dist/agentlib/promptbuilder.d.ts +171 -17
- package/dist/agentlib/promptbuilder.js +367 -49
- package/dist/agentlib/systemprompt.js +3 -3
- package/dist/agentlib/usermessage.d.ts +1 -1
- package/dist/agentlib/usermessage.js +5 -1
- package/dist/core/Codebolt.d.ts +52 -20
- package/dist/core/Codebolt.js +43 -1
- package/dist/core/messageManager.d.ts +0 -1
- package/dist/core/messageManager.js +4 -2
- package/dist/core/websocket.js +27 -1
- package/dist/modules/llm.d.ts +23 -3
- package/dist/modules/llm.js +20 -3
- package/dist/modules/project.d.ts +3 -3
- package/dist/modules/project.js +1 -1
- package/dist/modules/state.d.ts +5 -3
- package/dist/modules/state.js +2 -0
- package/dist/modules/task.d.ts +126 -11
- package/dist/modules/task.js +262 -20
- package/dist/notificationfunctions/agent.d.ts +48 -0
- package/dist/notificationfunctions/agent.js +115 -0
- package/dist/notificationfunctions/browser.d.ts +60 -0
- package/dist/notificationfunctions/browser.js +145 -0
- package/dist/notificationfunctions/chat.d.ts +53 -0
- package/dist/notificationfunctions/chat.js +125 -0
- package/dist/notificationfunctions/codeutils.d.ts +60 -0
- package/dist/notificationfunctions/codeutils.js +145 -0
- package/dist/notificationfunctions/crawler.d.ts +59 -0
- package/dist/notificationfunctions/crawler.js +159 -0
- package/dist/notificationfunctions/dbmemory.d.ts +50 -0
- package/dist/notificationfunctions/dbmemory.js +132 -0
- package/dist/notificationfunctions/fs.d.ts +125 -0
- package/dist/notificationfunctions/fs.js +472 -0
- package/dist/notificationfunctions/git.d.ts +174 -0
- package/dist/notificationfunctions/git.js +521 -0
- package/dist/notificationfunctions/history.d.ts +38 -0
- package/dist/notificationfunctions/history.js +97 -0
- package/dist/notificationfunctions/index.d.ts +79 -0
- package/dist/notificationfunctions/index.js +102 -0
- package/dist/notificationfunctions/llm.d.ts +39 -0
- package/dist/notificationfunctions/llm.js +99 -0
- package/dist/notificationfunctions/mcp.d.ts +67 -0
- package/dist/notificationfunctions/mcp.js +192 -0
- package/dist/notificationfunctions/search.d.ts +50 -0
- package/dist/notificationfunctions/search.js +146 -0
- package/dist/notificationfunctions/system.d.ts +25 -0
- package/dist/notificationfunctions/system.js +59 -0
- package/dist/notificationfunctions/terminal.d.ts +26 -0
- package/dist/notificationfunctions/terminal.js +64 -0
- package/dist/notificationfunctions/todo.d.ts +63 -0
- package/dist/notificationfunctions/todo.js +164 -0
- package/dist/notificationfunctions/utils.d.ts +81 -0
- package/dist/notificationfunctions/utils.js +177 -0
- package/dist/types/InternalTypes.d.ts +1 -0
- package/dist/types/commonTypes.d.ts +26 -3
- package/dist/types/index.d.ts +2 -2
- package/dist/types/libFunctionTypes.d.ts +80 -3
- package/dist/types/notificationFunctions/agent.d.ts +8 -0
- package/dist/types/notificationFunctions/agent.js +2 -0
- package/dist/types/notificationFunctions/browser.d.ts +10 -0
- package/dist/types/notificationFunctions/browser.js +2 -0
- package/dist/types/notificationFunctions/chat.d.ts +10 -0
- package/dist/types/notificationFunctions/chat.js +2 -0
- package/dist/types/notificationFunctions/codeutils.d.ts +10 -0
- package/dist/types/notificationFunctions/codeutils.js +2 -0
- package/dist/types/notificationFunctions/crawler.d.ts +10 -0
- package/dist/types/notificationFunctions/crawler.js +2 -0
- package/dist/types/notificationFunctions/dbmemory.d.ts +9 -0
- package/dist/types/notificationFunctions/dbmemory.js +2 -0
- package/dist/types/notificationFunctions/fs.d.ts +27 -0
- package/dist/types/notificationFunctions/fs.js +2 -0
- package/dist/types/notificationFunctions/git.d.ts +29 -0
- package/dist/types/notificationFunctions/git.js +2 -0
- package/dist/types/notificationFunctions/history.d.ts +10 -0
- package/dist/types/notificationFunctions/history.js +2 -0
- package/dist/types/notificationFunctions/index.d.ts +0 -0
- package/dist/types/notificationFunctions/index.js +1 -0
- package/dist/types/notificationFunctions/llm.d.ts +10 -0
- package/dist/types/notificationFunctions/llm.js +2 -0
- package/dist/types/notificationFunctions/mcp.d.ts +16 -0
- package/dist/types/notificationFunctions/mcp.js +2 -0
- package/dist/types/notificationFunctions/search.d.ts +11 -0
- package/dist/types/notificationFunctions/search.js +2 -0
- package/dist/types/notificationFunctions/system.d.ts +7 -0
- package/dist/types/notificationFunctions/system.js +2 -0
- package/dist/types/notificationFunctions/terminal.d.ts +7 -0
- package/dist/types/notificationFunctions/terminal.js +2 -0
- package/dist/types/notificationFunctions/todo.d.ts +11 -0
- package/dist/types/notificationFunctions/todo.js +2 -0
- package/dist/types/notifications/agent.d.ts +31 -0
- package/dist/types/notifications/agent.js +3 -0
- package/dist/types/notifications/browser.d.ts +53 -0
- package/dist/types/notifications/browser.js +3 -0
- package/dist/types/notifications/chat.d.ts +37 -0
- package/dist/types/notifications/chat.js +3 -0
- package/dist/types/notifications/codeutils.d.ts +55 -0
- package/dist/types/notifications/codeutils.js +3 -0
- package/dist/types/notifications/crawler.d.ts +55 -0
- package/dist/types/notifications/crawler.js +3 -0
- package/dist/types/notifications/dbmemory.d.ts +31 -0
- package/dist/types/notifications/dbmemory.js +3 -0
- package/dist/types/notifications/fs.d.ts +180 -0
- package/dist/types/notifications/fs.js +3 -0
- package/dist/types/notifications/git.d.ts +205 -0
- package/dist/types/notifications/git.js +3 -0
- package/dist/types/notifications/history.d.ts +32 -0
- package/dist/types/notifications/history.js +3 -0
- package/dist/types/notifications/llm.d.ts +45 -0
- package/dist/types/notifications/llm.js +2 -0
- package/dist/types/notifications/mcp.d.ts +63 -0
- package/dist/types/notifications/mcp.js +3 -0
- package/dist/types/notifications/search.d.ts +47 -0
- package/dist/types/notifications/search.js +3 -0
- package/dist/types/notifications/system.d.ts +20 -0
- package/dist/types/notifications/system.js +2 -0
- package/dist/types/notifications/terminal.d.ts +17 -0
- package/dist/types/notifications/terminal.js +2 -0
- package/dist/types/notifications/todo.d.ts +60 -0
- package/dist/types/notifications/todo.js +3 -0
- package/dist/types/socketMessageTypes.d.ts +3 -0
- package/dist/utils.d.ts +3 -0
- package/dist/utils.js +7 -1
- package/package.json +3 -1
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.LLMOutputHandler = void 0;
|
|
7
|
+
const agent_1 = __importDefault(require("../modules/agent"));
|
|
8
|
+
/**
|
|
9
|
+
* Handles LLM output processing, tool execution, and completion detection.
|
|
10
|
+
* This class processes LLM responses and manages the conversation flow.
|
|
11
|
+
*/
|
|
12
|
+
class LLMOutputHandler {
|
|
13
|
+
/**
|
|
14
|
+
* Creates a new LLMOutputHandler instance.
|
|
15
|
+
*
|
|
16
|
+
* @param llmResponse - The LLM response object
|
|
17
|
+
* @param codebolt - Optional codebolt API instance
|
|
18
|
+
*/
|
|
19
|
+
constructor(llmResponse, codebolt) {
|
|
20
|
+
/** Whether the task has been completed */
|
|
21
|
+
this.completed = false;
|
|
22
|
+
/** Tool results from execution */
|
|
23
|
+
this.toolResults = [];
|
|
24
|
+
/** Next user message to be added to conversation */
|
|
25
|
+
this.nextUserMessage = null;
|
|
26
|
+
/** Whether tools have been executed */
|
|
27
|
+
this.toolsExecuted = false;
|
|
28
|
+
// Validate llmResponse structure
|
|
29
|
+
if (!llmResponse) {
|
|
30
|
+
throw new Error("LLM response is null or undefined");
|
|
31
|
+
}
|
|
32
|
+
if (!llmResponse.completion) {
|
|
33
|
+
throw new Error("LLM response completion is missing");
|
|
34
|
+
}
|
|
35
|
+
if (!llmResponse.completion.choices || !Array.isArray(llmResponse.completion.choices)) {
|
|
36
|
+
throw new Error("LLM response choices array is missing or invalid");
|
|
37
|
+
}
|
|
38
|
+
this.llmResponse = llmResponse;
|
|
39
|
+
this.codebolt = codebolt;
|
|
40
|
+
// Check if any message has tool_calls, if none do, mark as completed
|
|
41
|
+
let hasToolCalls = false;
|
|
42
|
+
try {
|
|
43
|
+
this.llmResponse.completion.choices.forEach((message) => {
|
|
44
|
+
var _a;
|
|
45
|
+
if (((_a = message.message) === null || _a === void 0 ? void 0 : _a.tool_calls) && message.message.tool_calls.length > 0) {
|
|
46
|
+
hasToolCalls = true;
|
|
47
|
+
}
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
catch (error) {
|
|
51
|
+
console.error("Error checking for tool calls:", error);
|
|
52
|
+
hasToolCalls = false;
|
|
53
|
+
}
|
|
54
|
+
// If no messages have tool_calls, mark as completed
|
|
55
|
+
if (!hasToolCalls) {
|
|
56
|
+
try {
|
|
57
|
+
this.sendMessageToUser();
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
console.error("Error sending message to user:", error);
|
|
61
|
+
}
|
|
62
|
+
this.completed = true;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Checks if the task has been completed.
|
|
67
|
+
*
|
|
68
|
+
* @returns True if the task is completed, false otherwise
|
|
69
|
+
*/
|
|
70
|
+
isCompleted() {
|
|
71
|
+
return this.completed;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Gets the tool execution results.
|
|
75
|
+
*
|
|
76
|
+
* @returns Array of tool results
|
|
77
|
+
*/
|
|
78
|
+
getToolResults() {
|
|
79
|
+
return [...this.toolResults];
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Gets the next user message to be added to conversation.
|
|
83
|
+
*
|
|
84
|
+
* @returns The next user message or null
|
|
85
|
+
*/
|
|
86
|
+
getNextUserMessage() {
|
|
87
|
+
return this.nextUserMessage;
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* Sends the assistant's message to the user interface.
|
|
91
|
+
*
|
|
92
|
+
* @returns Promise that resolves when the message is sent
|
|
93
|
+
*/
|
|
94
|
+
async sendMessageToUser() {
|
|
95
|
+
var _a, _b;
|
|
96
|
+
if (!this.llmResponse) {
|
|
97
|
+
throw new Error("LLM response not available");
|
|
98
|
+
}
|
|
99
|
+
// Handle the response structure - it might have choices or direct content
|
|
100
|
+
let messageContent = '';
|
|
101
|
+
const completion = this.llmResponse.completion;
|
|
102
|
+
if (completion && completion.choices && completion.choices.length > 0) {
|
|
103
|
+
// OpenAI-style response with choices
|
|
104
|
+
const choice = completion.choices[0];
|
|
105
|
+
if (choice.message && choice.message.content) {
|
|
106
|
+
messageContent = choice.message.content;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
else if (completion && completion.content) {
|
|
110
|
+
// Direct content response
|
|
111
|
+
messageContent = completion.content;
|
|
112
|
+
}
|
|
113
|
+
if (messageContent) {
|
|
114
|
+
(_b = (_a = this.codebolt) === null || _a === void 0 ? void 0 : _a.chat) === null || _b === void 0 ? void 0 : _b.sendMessage(messageContent, {});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Executes all tool calls found in the LLM response.
|
|
119
|
+
*
|
|
120
|
+
* @returns Promise that resolves when all tools are executed
|
|
121
|
+
*/
|
|
122
|
+
async runTools() {
|
|
123
|
+
var _a;
|
|
124
|
+
try {
|
|
125
|
+
// Validate llmResponse structure
|
|
126
|
+
if (!this.llmResponse || !this.llmResponse.completion) {
|
|
127
|
+
throw new Error("Invalid LLM response structure");
|
|
128
|
+
}
|
|
129
|
+
if (!this.llmResponse.completion.choices || !Array.isArray(this.llmResponse.completion.choices)) {
|
|
130
|
+
throw new Error("LLM response choices array is missing or invalid");
|
|
131
|
+
}
|
|
132
|
+
if (this.llmResponse.completion.choices.length === 0) {
|
|
133
|
+
console.warn("No choices found in LLM response");
|
|
134
|
+
return this.toolResults;
|
|
135
|
+
}
|
|
136
|
+
let toolResults = [];
|
|
137
|
+
let taskCompletedBlock;
|
|
138
|
+
let userRejectedToolUse = false;
|
|
139
|
+
console.log("Calling run tool: ", JSON.stringify(this.llmResponse.completion));
|
|
140
|
+
const contentBlock = this.llmResponse.completion.choices[0];
|
|
141
|
+
// Validate contentBlock structure
|
|
142
|
+
if (!contentBlock || !contentBlock.message) {
|
|
143
|
+
console.warn("Invalid content block structure");
|
|
144
|
+
return this.toolResults;
|
|
145
|
+
}
|
|
146
|
+
if ((_a = contentBlock.message) === null || _a === void 0 ? void 0 : _a.tool_calls) {
|
|
147
|
+
for (const tool of contentBlock.message.tool_calls) {
|
|
148
|
+
try {
|
|
149
|
+
const { toolInput, toolName, toolUseId } = this.getToolDetail(tool);
|
|
150
|
+
if (!userRejectedToolUse) {
|
|
151
|
+
if (toolName.includes("attempt_completion")) {
|
|
152
|
+
taskCompletedBlock = tool;
|
|
153
|
+
}
|
|
154
|
+
else {
|
|
155
|
+
let [serverName] = toolName.replace('--', ':').split(':');
|
|
156
|
+
if (serverName == 'subagent') {
|
|
157
|
+
const agentResponse = await agent_1.default.startAgent(toolName.replace("subagent--", ''), toolInput.task);
|
|
158
|
+
const [didUserReject, result] = [false, "tool result is successful"];
|
|
159
|
+
let toolResult = this.getToolResult(toolUseId, result);
|
|
160
|
+
this.toolResults.push({
|
|
161
|
+
role: "tool",
|
|
162
|
+
tool_call_id: toolResult.tool_call_id,
|
|
163
|
+
content: toolResult.content,
|
|
164
|
+
});
|
|
165
|
+
if (toolResult.userMessage) {
|
|
166
|
+
this.nextUserMessage = {
|
|
167
|
+
role: "user",
|
|
168
|
+
content: toolResult.userMessage
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
if (didUserReject) {
|
|
172
|
+
userRejectedToolUse = true;
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
else {
|
|
176
|
+
console.log("Executing tool: ", toolName, toolInput);
|
|
177
|
+
const [didUserReject, result] = await this.executeTool(toolName, toolInput);
|
|
178
|
+
console.log("Tool result: ", result);
|
|
179
|
+
// toolResults.push(this.getToolResult(toolUseId, result));
|
|
180
|
+
let toolResult = this.getToolResult(toolUseId, result);
|
|
181
|
+
console.log("tool result after parsing", toolResult);
|
|
182
|
+
this.toolResults.push({
|
|
183
|
+
role: "tool",
|
|
184
|
+
tool_call_id: toolResult.tool_call_id,
|
|
185
|
+
content: toolResult.content,
|
|
186
|
+
});
|
|
187
|
+
if (toolResult.userMessage) {
|
|
188
|
+
this.nextUserMessage = {
|
|
189
|
+
role: "user",
|
|
190
|
+
content: toolResult.userMessage
|
|
191
|
+
};
|
|
192
|
+
}
|
|
193
|
+
if (didUserReject) {
|
|
194
|
+
userRejectedToolUse = true;
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
else {
|
|
200
|
+
let toolResult = this.getToolResult(toolUseId, "Skipping tool execution due to previous tool user rejection.");
|
|
201
|
+
this.toolResults.push({
|
|
202
|
+
role: "tool",
|
|
203
|
+
tool_call_id: toolResult.tool_call_id,
|
|
204
|
+
content: toolResult.content,
|
|
205
|
+
});
|
|
206
|
+
if (toolResult.userMessage) {
|
|
207
|
+
this.nextUserMessage = {
|
|
208
|
+
role: "user",
|
|
209
|
+
content: toolResult.userMessage
|
|
210
|
+
};
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
catch (error) {
|
|
215
|
+
this.toolResults.push({
|
|
216
|
+
role: "tool",
|
|
217
|
+
tool_call_id: (tool === null || tool === void 0 ? void 0 : tool.id) || "unknown",
|
|
218
|
+
content: String(error),
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
if (taskCompletedBlock) {
|
|
224
|
+
let taskArgs = {};
|
|
225
|
+
try {
|
|
226
|
+
// Validate taskCompletedBlock structure
|
|
227
|
+
if (!taskCompletedBlock.function) {
|
|
228
|
+
throw new Error("Task completed block function is missing");
|
|
229
|
+
}
|
|
230
|
+
if (!taskCompletedBlock.function.name) {
|
|
231
|
+
throw new Error("Task completed block function name is missing");
|
|
232
|
+
}
|
|
233
|
+
// Parse arguments safely
|
|
234
|
+
const argumentsString = taskCompletedBlock.function.arguments || "{}";
|
|
235
|
+
if (typeof argumentsString !== 'string') {
|
|
236
|
+
throw new Error("Task completed block arguments must be a string");
|
|
237
|
+
}
|
|
238
|
+
taskArgs = JSON.parse(argumentsString);
|
|
239
|
+
}
|
|
240
|
+
catch (parseError) {
|
|
241
|
+
const errorMessage = parseError instanceof Error ? parseError.message : 'Unknown parsing error';
|
|
242
|
+
console.error("Failed to parse taskCompletedBlock arguments:", errorMessage);
|
|
243
|
+
taskArgs = {};
|
|
244
|
+
}
|
|
245
|
+
let [_, result] = await this.executeTool(taskCompletedBlock.function.name, taskArgs);
|
|
246
|
+
if (result === "") {
|
|
247
|
+
this.completed = true;
|
|
248
|
+
result = "The user is satisfied with the result.";
|
|
249
|
+
}
|
|
250
|
+
let toolResult = this.getToolResult((taskCompletedBlock === null || taskCompletedBlock === void 0 ? void 0 : taskCompletedBlock.id) || "unknown", result);
|
|
251
|
+
this.toolResults.push({
|
|
252
|
+
role: "tool",
|
|
253
|
+
tool_call_id: toolResult.tool_call_id,
|
|
254
|
+
content: toolResult.content,
|
|
255
|
+
});
|
|
256
|
+
if (toolResult.userMessage) {
|
|
257
|
+
this.nextUserMessage = {
|
|
258
|
+
role: "user",
|
|
259
|
+
content: toolResult.userMessage
|
|
260
|
+
};
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
// this.apiConversationHistory.push(...toolResults);
|
|
264
|
+
// if (this.nextUserMessage) {
|
|
265
|
+
// this.apiConversationHistory.push(this.nextUserMessage);
|
|
266
|
+
// }
|
|
267
|
+
let nextUserMessage = this.toolResults;
|
|
268
|
+
if (this.toolResults.length === 0) {
|
|
269
|
+
nextUserMessage = [{
|
|
270
|
+
role: "user",
|
|
271
|
+
content: [{
|
|
272
|
+
type: "text",
|
|
273
|
+
text: "If you have completed the user's task, use the attempt_completion tool. If you require additional information from the user, use the ask_followup_question tool. Otherwise, if you have not completed the task and do not need additional information, then proceed with the next step of the task. (This is an automated message, so do not respond to it conversationally.)"
|
|
274
|
+
}]
|
|
275
|
+
}];
|
|
276
|
+
}
|
|
277
|
+
return this.toolResults;
|
|
278
|
+
}
|
|
279
|
+
catch (error) {
|
|
280
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
281
|
+
console.error(`Error in runTools: ${errorMessage}`, error);
|
|
282
|
+
// Add error information to tool results for debugging
|
|
283
|
+
this.toolResults.push({
|
|
284
|
+
role: "tool",
|
|
285
|
+
tool_call_id: "error",
|
|
286
|
+
content: `Error executing tools: ${errorMessage}`
|
|
287
|
+
});
|
|
288
|
+
return this.toolResults;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Extracts tool calls from the LLM response.
|
|
293
|
+
*
|
|
294
|
+
* @returns Array of tool calls or null if none found
|
|
295
|
+
*/
|
|
296
|
+
getToolCallsFromResponse() {
|
|
297
|
+
if (!this.llmResponse)
|
|
298
|
+
return null;
|
|
299
|
+
// Check OpenAI-style response structure
|
|
300
|
+
const completion = this.llmResponse.completion;
|
|
301
|
+
if (completion && completion.choices && completion.choices.length > 0) {
|
|
302
|
+
const choice = completion.choices[0];
|
|
303
|
+
if (choice.message && choice.message.tool_calls) {
|
|
304
|
+
return choice.message.tool_calls;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
// Check direct tool_calls property
|
|
308
|
+
if (completion && completion.tool_calls) {
|
|
309
|
+
return completion.tool_calls;
|
|
310
|
+
}
|
|
311
|
+
return null;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Extracts tool details from a tool call object.
|
|
315
|
+
*
|
|
316
|
+
* @param tool - The tool call object from the LLM response
|
|
317
|
+
* @returns ToolDetails object with name, input, and ID
|
|
318
|
+
*/
|
|
319
|
+
getToolDetail(tool) {
|
|
320
|
+
try {
|
|
321
|
+
// Validate tool object
|
|
322
|
+
if (!tool) {
|
|
323
|
+
throw new Error("Tool object is null or undefined");
|
|
324
|
+
}
|
|
325
|
+
// Validate tool.function
|
|
326
|
+
if (!tool.function) {
|
|
327
|
+
throw new Error("Tool function is null or undefined");
|
|
328
|
+
}
|
|
329
|
+
// Validate tool.function.name
|
|
330
|
+
if (!tool.function.name || typeof tool.function.name !== 'string') {
|
|
331
|
+
throw new Error("Tool function name is missing or invalid");
|
|
332
|
+
}
|
|
333
|
+
// Validate tool.id
|
|
334
|
+
if (!tool.id || typeof tool.id !== 'string') {
|
|
335
|
+
throw new Error("Tool ID is missing or invalid");
|
|
336
|
+
}
|
|
337
|
+
// Parse tool arguments safely
|
|
338
|
+
let toolInput = {};
|
|
339
|
+
if (tool.function.arguments) {
|
|
340
|
+
try {
|
|
341
|
+
toolInput = JSON.parse(tool.function.arguments);
|
|
342
|
+
}
|
|
343
|
+
catch (parseError) {
|
|
344
|
+
throw new Error(`Failed to parse tool arguments: ${parseError instanceof Error ? parseError.message : 'Invalid JSON'}`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
return {
|
|
348
|
+
toolName: tool.function.name,
|
|
349
|
+
toolInput: toolInput,
|
|
350
|
+
toolUseId: tool.id
|
|
351
|
+
};
|
|
352
|
+
}
|
|
353
|
+
catch (error) {
|
|
354
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown error occurred';
|
|
355
|
+
throw new Error(`Failed to extract tool details: ${errorMessage}`);
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Executes a tool with given name and input.
|
|
360
|
+
*
|
|
361
|
+
* @param toolName - The name of the tool to execute
|
|
362
|
+
* @param toolInput - The input parameters for the tool
|
|
363
|
+
* @returns Promise with tuple [userRejected, result]
|
|
364
|
+
*/
|
|
365
|
+
async executeTool(toolName, toolInput) {
|
|
366
|
+
var _a;
|
|
367
|
+
//codebolttools--readfile
|
|
368
|
+
const [toolboxName, actualToolName] = toolName.split('--');
|
|
369
|
+
console.log("Toolbox name: ", toolboxName, "Actual tool name: ", actualToolName);
|
|
370
|
+
const data = await ((_a = this.codebolt) === null || _a === void 0 ? void 0 : _a.mcp.executeTool(toolboxName, actualToolName, toolInput));
|
|
371
|
+
console.log("Tool result: ", data);
|
|
372
|
+
return data;
|
|
373
|
+
}
|
|
374
|
+
/**
|
|
375
|
+
* Creates a tool result object from the tool execution response.
|
|
376
|
+
*
|
|
377
|
+
* @param tool_call_id - The ID of the tool call
|
|
378
|
+
* @param content - The content returned by the tool
|
|
379
|
+
* @returns ToolResult object
|
|
380
|
+
*/
|
|
381
|
+
getToolResult(tool_call_id, content) {
|
|
382
|
+
let userMessage = undefined;
|
|
383
|
+
try {
|
|
384
|
+
// Validate content before parsing
|
|
385
|
+
if (typeof content !== 'string') {
|
|
386
|
+
throw new Error("Content must be a string");
|
|
387
|
+
}
|
|
388
|
+
// Only attempt to parse if content looks like JSON
|
|
389
|
+
if (content.trim().startsWith('{') || content.trim().startsWith('[')) {
|
|
390
|
+
const parsed = JSON.parse(content);
|
|
391
|
+
console.log("Parsed Content: ", parsed);
|
|
392
|
+
if (parsed && typeof parsed === 'object' && parsed.payload && parsed.payload.content) {
|
|
393
|
+
content = `The browser action has been executed. The screenshot have been captured for your analysis. The tool response is provided in the next user message`;
|
|
394
|
+
userMessage = parsed.payload.content;
|
|
395
|
+
}
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
catch (error) {
|
|
399
|
+
const errorMessage = error instanceof Error ? error.message : 'Unknown JSON parsing error';
|
|
400
|
+
console.warn(`Failed to parse tool result content as JSON: ${errorMessage}. Using content as-is.`);
|
|
401
|
+
// Content is not valid JSON, use as-is
|
|
402
|
+
}
|
|
403
|
+
return {
|
|
404
|
+
role: "tool",
|
|
405
|
+
tool_call_id,
|
|
406
|
+
content,
|
|
407
|
+
userMessage
|
|
408
|
+
};
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* Checks if the response has tool calls.
|
|
412
|
+
*
|
|
413
|
+
* @returns True if the response contains tool calls
|
|
414
|
+
*/
|
|
415
|
+
hasToolCalls() {
|
|
416
|
+
if (!this.llmResponse)
|
|
417
|
+
return false;
|
|
418
|
+
const toolCalls = this.getToolCallsFromResponse();
|
|
419
|
+
return toolCalls !== null && toolCalls.length > 0;
|
|
420
|
+
}
|
|
421
|
+
/**
|
|
422
|
+
* Gets the assistant's message content from the response.
|
|
423
|
+
*
|
|
424
|
+
* @returns The assistant's message content or null
|
|
425
|
+
*/
|
|
426
|
+
getAssistantMessage() {
|
|
427
|
+
if (!this.llmResponse)
|
|
428
|
+
return null;
|
|
429
|
+
const completion = this.llmResponse.completion;
|
|
430
|
+
if (completion && completion.choices && completion.choices.length > 0) {
|
|
431
|
+
const choice = completion.choices[0];
|
|
432
|
+
if (choice.message && choice.message.content) {
|
|
433
|
+
return choice.message.content;
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
else if (completion && completion.content) {
|
|
437
|
+
return completion.content;
|
|
438
|
+
}
|
|
439
|
+
return null;
|
|
440
|
+
}
|
|
441
|
+
/**
|
|
442
|
+
* Resets the handler state for reuse.
|
|
443
|
+
*/
|
|
444
|
+
reset() {
|
|
445
|
+
this.completed = false;
|
|
446
|
+
this.toolResults = [];
|
|
447
|
+
this.nextUserMessage = null;
|
|
448
|
+
this.toolsExecuted = false;
|
|
449
|
+
}
|
|
450
|
+
}
|
|
451
|
+
exports.LLMOutputHandler = LLMOutputHandler;
|