Skip to content

Commit daccdb4

Browse files
committed
improvements
1 parent aa49d3d commit daccdb4

File tree

2 files changed

+41
-11
lines changed

2 files changed

+41
-11
lines changed

packages/mcp-client/src/Agent.ts

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,18 @@ const taskCompletionTool: ChatCompletionInputTool = {
3030
},
3131
},
3232
};
33+
const askQuestionTool: ChatCompletionInputTool = {
34+
type: "function",
35+
function: {
36+
name: "ask_question",
37+
description: "Ask a question to the user to get more info required to solve or clarify their problem.",
38+
parameters: {
39+
type: "object",
40+
properties: {},
41+
},
42+
},
43+
};
44+
const exitLoopTools = [taskCompletionTool, askQuestionTool];
3345

3446
export class Agent extends McpClient {
3547
private readonly servers: StdioServerParameters[];
@@ -66,16 +78,31 @@ export class Agent extends McpClient {
6678
content: input,
6779
});
6880

69-
let i = 0;
70-
while (
71-
!(this.messages.at(-1)?.role === "tool" && this.messages.at(-1)?.name === taskCompletionTool.function.name) &&
72-
i < MAX_NUM_TURNS
73-
) {
81+
let total = 0;
82+
let nextShouldCallTools = true;
83+
while (true) {
7484
yield* this.processSingleTurnWithTools(this.messages, {
75-
taskCompletionTool,
85+
exitLoopTools,
86+
exitIfNoTool: total > 0 && nextShouldCallTools,
7687
});
77-
i++;
78-
debug("current role", this.messages.at(-1)?.role);
88+
total++;
89+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
90+
const currentLast = this.messages.at(-1)!;
91+
debug("current role", currentLast.role);
92+
if (
93+
currentLast.role === "tool" &&
94+
currentLast.name &&
95+
exitLoopTools.map((t) => t.function.name).includes(currentLast.name)
96+
) {
97+
return;
98+
}
99+
if (currentLast.role !== "tool" && total > MAX_NUM_TURNS) {
100+
return;
101+
}
102+
if (currentLast.role !== "tool" && nextShouldCallTools) {
103+
return;
104+
}
105+
nextShouldCallTools = currentLast.role !== "tool";
79106
}
80107
}
81108
}

packages/mcp-client/src/McpClient.ts

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -71,20 +71,23 @@ export class McpClient {
7171

7272
async *processSingleTurnWithTools(
7373
messages: ChatCompletionInputMessage[],
74-
opts: { taskCompletionTool?: ChatCompletionInputTool } = {}
74+
opts: { exitLoopTools?: ChatCompletionInputTool[]; exitIfNoTool?: boolean } = {}
7575
): AsyncGenerator<ChatCompletionOutput | ChatCompletionInputMessageTool> {
7676
debug("start of single turn");
7777

7878
const response = await this.client.chatCompletion({
7979
provider: this.provider,
8080
model: this.model,
8181
messages,
82-
tools: opts.taskCompletionTool ? [...this.availableTools, opts.taskCompletionTool] : this.availableTools,
82+
tools: opts.exitLoopTools ? [...opts.exitLoopTools, ...this.availableTools] : this.availableTools,
8383
tool_choice: "auto",
8484
});
8585

8686
const toolCalls = response.choices[0].message.tool_calls;
8787
if (!toolCalls || toolCalls.length === 0) {
88+
if (opts.exitIfNoTool) {
89+
return;
90+
}
8891
messages.push({
8992
role: response.choices[0].message.role,
9093
content: response.choices[0].message.content,
@@ -101,7 +104,7 @@ export class McpClient {
101104
content: "",
102105
name: toolName,
103106
};
104-
if (toolName === opts.taskCompletionTool?.function.name) {
107+
if (opts.exitLoopTools?.map((t) => t.function.name).includes(toolName)) {
105108
messages.push(message);
106109
return yield message;
107110
}

0 commit comments

Comments
 (0)