fix(tooling): surface non-executable tool-use warnings
This commit is contained in:
@@ -49,6 +49,11 @@ interface LoopMessage {
|
||||
content: string | unknown[];
|
||||
}
|
||||
|
||||
interface PseudoToolUse {
|
||||
name?: string;
|
||||
id?: string;
|
||||
}
|
||||
|
||||
export class NativeAgent {
|
||||
private modelClient: ModelClient | ModelRouter;
|
||||
private systemPrompt: string;
|
||||
@@ -224,11 +229,14 @@ export class NativeAgent {
|
||||
const wantsToolUse = (response.stopReason === 'tool_use' || response.stopReason === 'tool_calls')
|
||||
&& response.toolCalls && response.toolCalls.length > 0;
|
||||
if (!wantsToolUse) {
|
||||
let finalContent = response.content;
|
||||
const pseudoToolUse = this.extractPseudoToolUse(response.content);
|
||||
let finalContent = pseudoToolUse
|
||||
? this.buildPseudoToolUseWarning(response.content, pseudoToolUse)
|
||||
: response.content;
|
||||
if (response.thinkingContent) {
|
||||
finalContent = `<thinking>\n${response.thinkingContent}\n</thinking>\n\n${response.content}`;
|
||||
finalContent = `<thinking>\n${response.thinkingContent}\n</thinking>\n\n${finalContent}`;
|
||||
}
|
||||
const assistantMsg: Message = { role: 'assistant', content: response.content };
|
||||
const assistantMsg: Message = { role: 'assistant', content: finalContent };
|
||||
this.addToHistory(assistantMsg);
|
||||
return finalContent;
|
||||
}
|
||||
@@ -524,4 +532,32 @@ export class NativeAgent {
|
||||
private isAbortError(error: unknown): boolean {
|
||||
return error instanceof Error && error.name === 'AbortError';
|
||||
}
|
||||
|
||||
private extractPseudoToolUse(content: string): PseudoToolUse | null {
|
||||
if (!content) {
|
||||
return null;
|
||||
}
|
||||
if (!/"type"\s*:\s*"tool_use"/.test(content)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const nameMatch = content.match(/"name"\s*:\s*"([^"]+)"/);
|
||||
const idMatch = content.match(/"id"\s*:\s*"([^"]+)"/);
|
||||
return {
|
||||
name: nameMatch?.[1],
|
||||
id: idMatch?.[1],
|
||||
};
|
||||
}
|
||||
|
||||
private buildPseudoToolUseWarning(rawContent: string, pseudo: PseudoToolUse): string {
|
||||
const toolName = pseudo.name ?? 'unknown';
|
||||
const toolId = pseudo.id ?? 'unknown';
|
||||
return [
|
||||
'Tool call was emitted as plain text and was not executed.',
|
||||
`Tool: ${toolName} (id: ${toolId})`,
|
||||
'This usually means the current model/backend did not return structured tool metadata.',
|
||||
'Original assistant output:',
|
||||
rawContent,
|
||||
].join('\n');
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user