mirror of
https://github.com/andy-stack/vaultkeeper-ai.git
synced 2026-07-22 06:42:03 +00:00
- Rename toolDefinitions to aiFunctionDefinitions across all AI classes - Add aiFunctionUsageMode property to control function calling behavior - Implement provider-specific tool_choice/tool_config based on usage mode - Remove AIController and create BaseAgent base class - Update ExecutionPrompt with scope of execution guidelines - Simplify ChatArea layout update logic by removing debounce - Add naming service completion wait in ChatService - Replace console.warn with Exception.warn in InputService - Delete unused AIController.ts file - Update all tests to use new aiFunctionDefinitions property
102 lines
No EOL
5.4 KiB
TypeScript
102 lines
No EOL
5.4 KiB
TypeScript
import type { Conversation } from "Conversations/Conversation";
|
|
import type { IChatServiceCallbacks } from "../ChatService";
|
|
import { AIFunctionDefinitions } from "AIClasses/FunctionDefinitions/AIFunctionDefinitions";
|
|
import { Exception } from "Helpers/Exception";
|
|
import { AIFunction, isAIFunction } from "Enums/AIFunction";
|
|
import { AgentType } from "Enums/AgentType";
|
|
import { BaseAgent } from "./BaseAgent";
|
|
import { ExecuteWorkflowArgsSchema, type ExecuteWorkflowArgs } from "AIClasses/Schemas/AIFunctionSchemas";
|
|
import { AIFunctionResponse } from "AIClasses/FunctionDefinitions/AIFunctionResponse";
|
|
import type { AIFunctionCall } from "AIClasses/AIFunctionCall";
|
|
import { OrchestrationAgent } from "./OrchestrationAgent";
|
|
import { ConversationContent } from "Conversations/ConversationContent";
|
|
import { Role } from "Enums/Role";
|
|
import { DebugColor } from "Enums/DebugColor";
|
|
import { AIFunctionUsageMode } from "Enums/AIFunctionUsageMode";
|
|
|
|
export class MainAgent extends BaseAgent {
|
|
|
|
public async runMainAgent(conversation: Conversation, allowDestructiveActions: boolean, planningMode: boolean, callbacks: IChatServiceCallbacks) {
|
|
await this.setAgentPromptAndTools(planningMode, allowDestructiveActions);
|
|
this.debugService?.log("MainAgent", `Starting MainAgent (planningMode: ${planningMode}, destructive: ${allowDestructiveActions})`);
|
|
|
|
if (planningMode) {
|
|
this.debugService?.log("MainAgent", "Planning mode enabled - workflow execution available");
|
|
conversation.contents.push(new ConversationContent({
|
|
role: Role.User,
|
|
content: "Planning mode is enabled, you should request planned execution when appropriate or if you do not have the required tools to complete the request",
|
|
shouldDisplayContent: false
|
|
}));
|
|
}
|
|
|
|
let result = await this.runMainAgentLoop(conversation, callbacks);
|
|
|
|
while (result.planRequest && result.functionCall) {
|
|
this.debugService?.log("MainAgent", "Spawning OrchestrationAgent for planned workflow");
|
|
const orchestrationAgent = new OrchestrationAgent();
|
|
orchestrationAgent.resolveAIProvider();
|
|
const workflowResult = await orchestrationAgent.runPlannedWorkflow(result.planRequest, callbacks);
|
|
this.debugService?.log("MainAgent", "OrchestrationAgent workflow completed");
|
|
|
|
conversation.addFunctionResponse(new AIFunctionResponse(
|
|
result.functionCall.name,
|
|
workflowResult,
|
|
result.functionCall.toolId
|
|
));
|
|
|
|
await this.setAgentPromptAndTools(planningMode, allowDestructiveActions);
|
|
result = await this.runMainAgentLoop(conversation, callbacks);
|
|
}
|
|
}
|
|
|
|
// the main agent loop - may return an execution plan if the agent has requested a planned workflow
|
|
private async runMainAgentLoop(conversation: Conversation, callbacks: IChatServiceCallbacks
|
|
): Promise<{ planRequest: ExecuteWorkflowArgs | undefined, functionCall: AIFunctionCall | undefined }> {
|
|
|
|
let planRequest: ExecuteWorkflowArgs | undefined;
|
|
let planFunctionCall: AIFunctionCall | undefined;
|
|
|
|
await this.runAgentLoop(AgentType.Main, conversation, callbacks, async functionCall => {
|
|
const functionCallName = functionCall.name;
|
|
if (isAIFunction(functionCallName, AIFunction.ExecuteWorkflow)) {
|
|
this.debugService?.log("MainAgent", "ExecuteWorkflow function detected - transitioning to orchestration");
|
|
const parseResult = ExecuteWorkflowArgsSchema.safeParse(functionCall.arguments);
|
|
if (!parseResult.success) {
|
|
conversation.addFunctionResponse(new AIFunctionResponse(
|
|
functionCallName,
|
|
{ error: `Invalid arguments for ${AIFunction.ExecuteWorkflow}: ${parseResult.error.message}` },
|
|
functionCall.toolId
|
|
));
|
|
return { shouldExit: false };
|
|
}
|
|
planRequest = parseResult.data;
|
|
planFunctionCall = functionCall;
|
|
this.updateThought(functionCall, callbacks);
|
|
return { shouldExit: true };
|
|
}
|
|
|
|
this.debugService?.log("MainAgent", `Executing function: ${functionCall.name}`);
|
|
this.updateThought(functionCall, callbacks);
|
|
const functionResponse = await this.aiFunctionService.performAIFunction(functionCall);
|
|
conversation.addFunctionResponse(functionResponse);
|
|
return { shouldExit: false };
|
|
});
|
|
return { planRequest: planRequest, functionCall: planFunctionCall };
|
|
}
|
|
|
|
private async setAgentPromptAndTools(planningMode: boolean, allowDestructiveActions: boolean): Promise<void> {
|
|
if (!this.ai) { // this shouldn't ever happen
|
|
Exception.throw("Error: No AI provider has been set!");
|
|
}
|
|
this.ai.agentType = AgentType.Main;
|
|
this.ai.aiFunctionUsageMode = AIFunctionUsageMode.Auto;
|
|
this.ai.systemPrompt = this.aiPrompt.systemInstruction();
|
|
this.ai.userInstruction = await this.aiPrompt.userInstruction();
|
|
this.ai.aiFunctionDefinitions = AIFunctionDefinitions.agentDefinitions(allowDestructiveActions, planningMode);
|
|
}
|
|
|
|
protected override setDebugColor(): void {
|
|
this.debugService?.setDebugColor(DebugColor.BLUE);
|
|
}
|
|
|
|
} |