refactor: migrate agent system from XML tool calling to OpenAI SDK with native function calling
- Replace custom XML-based tool parsing (XMLToolExecutor) with OpenAI SDK's native tool_calls via `openai` npm package (dangerouslyAllowBrowser) - Consolidate 4 LLM providers (OpenAI, Claude, Gemini, ClaudeOpenRouter) into a single OpenAI SDK-based LLMProvider compatible with any OpenAI-style API (OpenAI, OpenRouter, Ollama, vLLM) - Move agentic tool execution loop from ChatBox into AgentCore - Update Message type to support tool roles, tool_calls, and tool_call_id - Update system prompt to remove XML formatting instructions (~45% smaller) - Remove AttemptCompletionTool (replaced by stop_reason detection), ThinkTool, and ThinkingTool - Polish tool descriptions for OpenAI function calling schema compliance - Normalize base URLs by stripping /chat/completions suffix
This commit is contained in:
@@ -2,50 +2,73 @@
|
||||
* Manages the state of an agent conversation
|
||||
*/
|
||||
|
||||
/**
|
||||
* Tool call info attached to assistant messages (OpenAI function calling format)
|
||||
*/
|
||||
export interface ToolCall {
|
||||
id: string;
|
||||
type: 'function';
|
||||
function: {
|
||||
name: string;
|
||||
arguments: string; // JSON string of parameters
|
||||
};
|
||||
}
|
||||
|
||||
export interface Message {
|
||||
id: string;
|
||||
role: 'user' | 'assistant';
|
||||
content: string;
|
||||
role: 'user' | 'assistant' | 'tool';
|
||||
content: string | null;
|
||||
timestamp: number;
|
||||
tool_calls?: ToolCall[]; // present on assistant messages when LLM invokes tools
|
||||
tool_call_id?: string; // present on tool-result messages, links back to ToolCall.id
|
||||
}
|
||||
|
||||
export class AgentState {
|
||||
private messages: Message[] = [];
|
||||
private conversationId: string;
|
||||
private isWorkingOnTask: boolean = false;
|
||||
|
||||
|
||||
constructor(conversationId?: string, isWorkingOnTask: boolean = false) {
|
||||
this.conversationId = conversationId || this.generateConversationId();
|
||||
this.isWorkingOnTask = isWorkingOnTask;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Add a message to the conversation
|
||||
*/
|
||||
addMessage(role: 'user' | 'assistant', content: string): string {
|
||||
addMessage(
|
||||
role: 'user' | 'assistant' | 'tool',
|
||||
content: string | null,
|
||||
options?: { tool_calls?: ToolCall[]; tool_call_id?: string }
|
||||
): string {
|
||||
const message: Message = {
|
||||
id: this.generateMessageId(),
|
||||
role,
|
||||
content,
|
||||
timestamp: Date.now()
|
||||
timestamp: Date.now(),
|
||||
...(options?.tool_calls ? { tool_calls: options.tool_calls } : {}),
|
||||
...(options?.tool_call_id ? { tool_call_id: options.tool_call_id } : {}),
|
||||
};
|
||||
|
||||
|
||||
this.messages.push(message);
|
||||
return message.id;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Update the content of a message by ID
|
||||
*/
|
||||
updateMessage(messageId: string, content: string): boolean {
|
||||
updateMessage(messageId: string, content: string | null, options?: { tool_calls?: ToolCall[] }): boolean {
|
||||
const messageIndex = this.messages.findIndex(msg => msg.id === messageId);
|
||||
if (messageIndex !== -1) {
|
||||
this.messages[messageIndex].content = content;
|
||||
if (options?.tool_calls) {
|
||||
this.messages[messageIndex].tool_calls = options.tool_calls;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove a message by ID
|
||||
*/
|
||||
@@ -57,46 +80,46 @@ export class AgentState {
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Remove the last N messages
|
||||
*/
|
||||
removeLastMessages(count: number): void {
|
||||
this.messages.splice(-count, count);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get all messages in the conversation
|
||||
*/
|
||||
getMessages(): Message[] {
|
||||
return [...this.messages];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the conversation ID
|
||||
*/
|
||||
getConversationId(): string {
|
||||
return this.conversationId;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Clear all messages
|
||||
*/
|
||||
clearMessages(): void {
|
||||
this.messages = [];
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the last N messages
|
||||
*/
|
||||
getRecentMessages(count: number): Message[] {
|
||||
return this.messages.slice(-count);
|
||||
}
|
||||
|
||||
|
||||
private generateConversationId(): string {
|
||||
return `conv_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
|
||||
}
|
||||
|
||||
|
||||
private generateMessageId(): string {
|
||||
return `msg_${Date.now()}_${Math.random().toString(36).substring(2, 15)}`;
|
||||
}
|
||||
@@ -109,4 +132,4 @@ export class AgentState {
|
||||
setIsWorkingOnTask(isWorkingOnTask: boolean): void {
|
||||
this.isWorkingOnTask = isWorkingOnTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user