Skip to content

Commit 4720488

Browse files
committed
feat: Refactor sampling and workflow executors for improved clarity and maintainability; enhance argument handling and logging
1 parent 42b2570 commit 4720488

File tree

7 files changed

+140
-135
lines changed

7 files changed

+140
-135
lines changed

packages/core/src/executors/sampling/agentic-sampling-executor.ts

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -18,23 +18,23 @@ export class SamplingExecutor extends BaseSamplingExecutor {
1818
allToolNames: string[],
1919
toolNameToDetailList: [string, ExternalTool][],
2020
server: ComposableMCPServer,
21-
config?: SamplingConfig,
21+
config?: SamplingConfig
2222
) {
2323
super(
2424
name,
2525
description,
2626
allToolNames,
2727
toolNameToDetailList,
2828
server,
29-
config,
29+
config
3030
);
3131

3232
// Create AgenticExecutor for tool execution
3333
this.agenticExecutor = new AgenticExecutor(
3434
name,
3535
allToolNames,
3636
toolNameToDetailList as [string, unknown][],
37-
server,
37+
server
3838
);
3939
}
4040

@@ -65,7 +65,7 @@ export class SamplingExecutor extends BaseSamplingExecutor {
6565

6666
executeSampling(
6767
args: Record<string, unknown>,
68-
schema: Record<string, unknown>,
68+
schema: Record<string, unknown>
6969
) {
7070
const validationResult = this.validateSchema(args, schema);
7171
if (!validationResult.valid) {
@@ -85,30 +85,30 @@ export class SamplingExecutor extends BaseSamplingExecutor {
8585
const createArgsDef = createArgsDefFactory(
8686
this.name,
8787
this.allToolNames,
88-
this.buildDepGroups(),
88+
this.buildDepGroups()
8989
);
9090

9191
const agenticSchema = createArgsDef.forAgentic(
9292
this.toolNameToDetailList as [string, unknown][],
93-
true,
93+
true
9494
);
9595

9696
const systemPrompt = this.buildSystemPrompt(
9797
args.userRequest as string,
98-
agenticSchema,
98+
agenticSchema
9999
);
100-
return this.runSamplingLoop(systemPrompt, agenticSchema);
100+
return this.runSamplingLoop(() => systemPrompt, agenticSchema);
101101
}
102102

103103
protected async processAction(
104104
parsedData: Record<string, unknown>,
105-
schema: Record<string, unknown>,
105+
schema: Record<string, unknown>
106106
): Promise<CallToolResult> {
107107
// Define the expected tool call data structure
108108
const toolCallData = parsedData;
109109

110110
if (toolCallData.action === "complete") {
111-
const reasoning = toolCallData.reasoning as string || "Task completed";
111+
const reasoning = (toolCallData.reasoning as string) || "Task completed";
112112
return this.createCompletionResult(reasoning);
113113
}
114114

@@ -118,25 +118,24 @@ export class SamplingExecutor extends BaseSamplingExecutor {
118118

119119
const toolResult = await this.agenticExecutor.execute(
120120
toolCallData,
121-
schema,
121+
schema
122122
);
123123

124124
// Extract result text
125-
const resultText = toolResult.content
126-
?.filter((content) => content.type === "text")
127-
?.map((content) => content.text)
128-
?.join("\n") || "No result";
125+
const resultText =
126+
toolResult.content
127+
?.filter((content) => content.type === "text")
128+
?.map((content) => content.text)
129+
?.join("\n") || "No result";
129130

130131
// Add conversation history updates
131-
this.conversationHistory.push(
132-
{
133-
role: "assistant",
134-
content: {
135-
type: "text",
136-
text: resultText,
137-
},
132+
this.conversationHistory.push({
133+
role: "assistant",
134+
content: {
135+
type: "text",
136+
text: resultText,
138137
},
139-
);
138+
});
140139

141140
return toolResult;
142141
} catch (error) {
@@ -147,21 +146,23 @@ export class SamplingExecutor extends BaseSamplingExecutor {
147146

148147
private buildSystemPrompt(
149148
userRequest: string,
150-
agenticSchema: Record<string, unknown>,
149+
agenticSchema: Record<string, unknown>
151150
): string {
152-
const toolList = this.allToolNames.map((name) => {
153-
const tool = this.toolNameToDetailList.find(([toolName]) =>
154-
toolName === name
155-
);
156-
const toolSchema = this.server.getInternalToolSchema(name);
157-
158-
if (tool && tool[1]) {
159-
return `- ${name}: ${tool[1].description || `Tool: ${name}`}`;
160-
} else if (toolSchema) {
161-
return `- ${name}: ${toolSchema.description}`;
162-
}
163-
return `- ${name}`;
164-
}).join("\n");
151+
const toolList = this.allToolNames
152+
.map((name) => {
153+
const tool = this.toolNameToDetailList.find(
154+
([toolName]) => toolName === name
155+
);
156+
const toolSchema = this.server.getInternalToolSchema(name);
157+
158+
if (tool && tool[1]) {
159+
return `- ${name}: ${tool[1].description || `Tool: ${name}`}`;
160+
} else if (toolSchema) {
161+
return `- ${name}: ${toolSchema.description}`;
162+
}
163+
return `- ${name}`;
164+
})
165+
.join("\n");
165166

166167
// Build the complete schema using forAgentic
167168

packages/core/src/executors/sampling/base-sampling-executor.ts

Lines changed: 39 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -75,10 +75,10 @@ export abstract class BaseSamplingExecutor {
7575
const response = await this.server.createMessage({
7676
systemPrompt: systemPrompt(),
7777
messages: this.conversationHistory,
78-
maxTokens: 9999,
78+
maxTokens: Number.MAX_SAFE_INTEGER,
7979
});
8080

81-
const responseContent = response.content.text as string || "{}";
81+
const responseContent = (response.content.text as string) || "{}";
8282

8383
// Parse JSON response
8484
let parsedData: Record<string, unknown>;
@@ -90,13 +90,30 @@ export abstract class BaseSamplingExecutor {
9090
continue;
9191
}
9292

93+
if (parsedData) {
94+
this.conversationHistory.push({
95+
role: "assistant",
96+
content: {
97+
type: "text",
98+
text: `Executing with arguments: ${
99+
JSON.stringify(
100+
parsedData,
101+
null,
102+
2,
103+
)
104+
}`,
105+
},
106+
});
107+
}
108+
93109
// Process the parsed data using subclass implementation
94110
const result = await this.processAction(parsedData, schema, state);
111+
this.logIterationProgress(parsedData, result);
95112

96113
if (result.isError) {
97114
// If processing resulted in an error, add to conversation history
98115
this.conversationHistory.push({
99-
role: "assistant",
116+
role: "user",
100117
content: {
101118
type: "text",
102119
text: result.content[0].text as string,
@@ -108,13 +125,6 @@ export abstract class BaseSamplingExecutor {
108125
if (result.isComplete) {
109126
return result;
110127
}
111-
112-
// Add result to conversation history if not complete
113-
if (result.conversationUpdate) {
114-
this.conversationHistory.push(
115-
...result.conversationUpdate as ConversationMessage[],
116-
);
117-
}
118128
}
119129

120130
// Reached maximum iterations
@@ -208,58 +218,40 @@ ${text}
208218

209219
let details = "\n\n**Detailed Conversation History:**";
210220

211-
this.conversationHistory.forEach((message, index) => {
212-
details += `\n\n**Message ${index + 1} (${message.role}):**\n`;
213-
221+
this.conversationHistory.forEach((message) => {
214222
if (message.role === "assistant") {
215223
// Try to parse JSON and format nicely
216224
try {
217225
const parsed = JSON.parse(message.content.text);
218-
details += "```json\n" + JSON.stringify(parsed, null, 2) + "\n```";
226+
details += "\n```json\n" + JSON.stringify(parsed, null, 2) + "\n```";
219227
} catch {
220228
// Not JSON, show as text
221-
details += "```\n" + message.content.text + "\n```";
229+
details += "\n```\n" + message.content.text + "\n```";
222230
}
223231
} else {
224232
// User message
225-
details += "```\n" + message.content.text + "\n```";
233+
details += "\n```\n" + message.content.text + "\n```";
226234
}
227235
});
228236

229-
// Add summary
230-
const toolsUsed = new Set<string>();
231-
let errorCount = 0;
232-
233-
for (const message of this.conversationHistory) {
234-
if (message.role === "assistant") {
235-
try {
236-
const parsed = JSON.parse(message.content.text);
237-
if (parsed.action && parsed.action !== "complete") {
238-
toolsUsed.add(parsed.action);
239-
}
240-
} catch {
241-
if (
242-
message.content.text.includes("JSON parsing failed") ||
243-
message.content.text.toLowerCase().includes("error")
244-
) {
245-
errorCount++;
246-
}
247-
}
248-
}
249-
}
250-
251-
details += "\n\n**Summary:**";
252-
details += `\n- Total messages: ${this.conversationHistory.length}`;
253-
if (toolsUsed.size > 0) {
254-
details += `\n- Tools used: ${Array.from(toolsUsed).join(", ")}`;
255-
}
256-
if (errorCount > 0) {
257-
details += `\n- Errors encountered: ${errorCount}`;
258-
}
259-
260237
return details;
261238
}
262239

240+
protected logIterationProgress(
241+
parsedData: Record<string, unknown>,
242+
result: CallToolResult,
243+
): void {
244+
// Optional: Log iteration progress for debugging
245+
console.log(
246+
`Iteration ${this.currentIteration + 1}/${this.maxIterations}:`,
247+
{
248+
parsedData,
249+
isError: result.isError,
250+
isComplete: result.isComplete,
251+
},
252+
);
253+
}
254+
263255
// Abstract methods that subclasses must implement
264256
protected abstract processAction<TState>(
265257
parsedData: Record<string, unknown>,

0 commit comments

Comments
 (0)