housekeeping: remove unused execution agent code and clean up orchestration flow

- Remove unused agentExecutionDefinitions and gatedDefinitions methods
- Delete obsolete CreatePlan.ts (replaced by ExecuteWorkflow.ts)
- Rename PlanningAgentSystemPrompt to PlanningPrompt for consistency
- Fix orchestration agent promise returns and replan flag handling
- Make saveConversation calls async throughout AIController
- Simplify vault cache delete event handling
- Change debug logging from console.log to console.debug
- Fix function name references in execution and main agents
This commit is contained in:
Andrew Beal 2026-01-29 12:26:41 +00:00
parent ac5755d702
commit 32c478249b
11 changed files with 36 additions and 59 deletions

View file

@ -12,10 +12,8 @@ import { SubmitPlan } from "./Functions/SubmitPlan";
import { CancelPlan } from "./Functions/CancelPlan";
import { AskUserQuestionPlanning } from "./Functions/AskUserQuestionPlanning";
import { CompletePlan } from "./Functions/CompletePlan";
import { AskUserQuestionExecution } from "./Functions/AskUserQuestionExecution";
import { ContinuePlanExecution } from "./Functions/ContinuePlanExecution";
import { CompleteTask } from "./Functions/CompleteTask";
import { ExecuteWorkflow } from "./Functions/CreatePlan";
import { ExecuteWorkflow } from "./Functions/ExecuteWorkflow";
export abstract class AIFunctionDefinitions {
@ -61,29 +59,6 @@ export abstract class AIFunctionDefinitions {
return [...this.agentDefinitions(true, false), CompleteTask];
}
public static agentExecutionDefinitions() {
this.isGated = false;
return [
SearchVaultFiles,
ReadVaultFiles,
ListVaultFiles,
WriteVaultFile,
PatchVaultFile,
DeleteVaultFiles,
MoveVaultFiles,
AskUserQuestionExecution,
CompletePlan
];
}
public static gatedDefinitions() {
this.isGated = true;
return [
ContinuePlanExecution,
CompleteStep
];
}
public static compactSummaryForPlanningAgent(): string {
return this.definitionsList.map(definition => {
// Extract first line of description as brief purpose

View file

@ -3,7 +3,7 @@ import { Services } from "Services/Services";
import { SystemInstruction } from "./SystemPrompt";
import type { FileSystemService } from "Services/FileSystemService";
import type { SettingsService } from "Services/SettingsService";
import { PlanningAgentSystemPrompt } from "AIPrompts/PlanningAgentSystemPrompt";
import { PlanningPrompt } from "AIPrompts/PlanningPrompt";
import { ExecutionPrompt } from "./ExecutionPrompt";
import { OrchestrationPrompt } from "./OrchestrationPrompt";
@ -34,7 +34,7 @@ export class AIPrompt implements IPrompt {
}
public planningInstruction(): string {
return PlanningAgentSystemPrompt;
return PlanningPrompt;
}
public executionInstruction(): string {

View file

@ -1,6 +1,6 @@
import { AIFunctionDefinitions } from "AIClasses/FunctionDefinitions/AIFunctionDefinitions";
export const PlanningAgentSystemPrompt: string = `
export const PlanningPrompt: string = `
# Obsidian Vault Planning Agent
You are a specialized planning agent within a multi-agent Obsidian vault assistant system. Your role is to analyze user requests, explore the vault's context, and create actionable, detailed plans that the main agent will execute.

View file

@ -45,7 +45,7 @@ export class AIController {
this.debugService?.log("AgentLoop", `Starting ${agentType} agent loop`);
let response = await this.streamRequestResponse(agentType, this.ensureCorrectConversationStructure(conversation), callbacks);
this.saveConversation(agentType, conversation);
await this.saveConversation(agentType, conversation);
while (response.functionCall || response.shouldContinue) {
if (response.functionCall) {
@ -53,7 +53,7 @@ export class AIController {
const result = await handleFunctionCall(response.functionCall);
if (result.shouldExit) {
this.debugService?.log("AgentLoop", `${agentType} exiting loop (shouldExit: true)`);
this.saveConversation(agentType, conversation);
await this.saveConversation(agentType, conversation);
return;
}
} else {
@ -62,7 +62,7 @@ export class AIController {
response = await this.streamRequestResponse(agentType, this.ensureCorrectConversationStructure(conversation), callbacks);
this.saveConversation(agentType, conversation);
await this.saveConversation(agentType, conversation);
}
this.debugService?.log("AgentLoop", `${agentType} agent loop completed`);
}

View file

@ -121,11 +121,13 @@ export class AIFunctionService {
return new AIFunctionResponse(functionCall.name, {}, functionCall.toolId)
// multi-agent functions are handled elsewhere - this shouldn't really ever get hit
case AIFunction.CreatePlan:
case AIFunction.ExecuteWorkflow:
case AIFunction.ContinuePlanExecution:
case AIFunction.Replan:
case AIFunction.SubmitPlan:
case AIFunction.AskUserQuestionPlanning:
case AIFunction.AskUserQuestionExecution:
case AIFunction.CompleteTask:
case AIFunction.CompleteStep:
case AIFunction.CompletePlan:
case AIFunction.CancelPlan: {

View file

@ -62,7 +62,7 @@ export class ExecutionAgent extends AIController {
return { shouldExit: true };
}
this.debugService?.log("ExecutionAgent", `Executing function: ${functionCallName}`);
this.debugService?.log("ExecutionAgent", `Executing function: ${functionCall.name}`);
this.updateThought(functionCall, callbacks);
const functionResponse = await this.aiFunctionService.performAIFunction(functionCall);
this.conversation.addFunctionResponse(functionResponse);

View file

@ -74,7 +74,7 @@ export class MainAgent extends AIController {
return { shouldExit: true };
}
this.debugService?.log("MainAgent", `Executing function: ${functionCallName}`);
this.debugService?.log("MainAgent", `Executing function: ${functionCall.name}`);
this.updateThought(functionCall, callbacks);
const functionResponse = await this.aiFunctionService.performAIFunction(functionCall);
conversation.addFunctionResponse(functionResponse);

View file

@ -31,13 +31,16 @@ export class OrchestrationAgent extends AIController {
const planningAgent = new PlanningAgent();
planningAgent.resolveAIProvider();
let planCompleted = false;
let isReplan = false;
while (!planCompleted) {
callbacks.onPlanReset();
callbacks.onPlanningStarted();
this.debugService?.log("OrchestrationAgent", "Spawning PlanningAgent to generate execution plan");
const executionPlan = await planningAgent.runPlanningAgent(planningConversation, callbacks, false);
const executionPlan = await planningAgent.runPlanningAgent(planningConversation, callbacks, isReplan);
callbacks.onPlanningFinished();
if (!executionPlan) {
@ -45,6 +48,7 @@ export class OrchestrationAgent extends AIController {
return { message: Copy.PlanningFailedNoSteps };
}
this.debugService?.log("OrchestrationAgent", `Execution plan received with ${executionPlan.executionSteps.length} steps`);
callbacks.onPlanUpdate(executionPlan);
let currentStepIndex = 0;
@ -109,6 +113,7 @@ export class OrchestrationAgent extends AIController {
planCompleted = true;
}
}
isReplan = true;
}
this.debugService?.log("OrchestrationAgent", "Planned workflow completed - requesting summary");
@ -143,7 +148,7 @@ export class OrchestrationAgent extends AIController {
{ message: Copy.OrchestrationToolDenial },
functionCall.toolId
));
return { shouldExit: false };
return Promise.resolve({ shouldExit: false });
}
if (isAIFunction(functionCallName, AIFunction.CompleteStep)) {
@ -154,7 +159,7 @@ export class OrchestrationAgent extends AIController {
{ error: `Invalid arguments for ${AIFunction.CompleteStep}: ${parseResult.error.message}` },
functionCall.toolId
));
return { shouldExit: false };
return Promise.resolve({ shouldExit: false });
}
if (!parseResult.data.confirm_completion) {
planningConversation.addFunctionResponse(new AIFunctionResponse(
@ -162,7 +167,7 @@ export class OrchestrationAgent extends AIController {
{ error: "Confirmation was false, no action taken" },
functionCall.toolId
));
return { shouldExit: false };
return Promise.resolve({ shouldExit: false });
}
this.debugService?.log("Orchestration", `CompleteStep called (confirmed: ${parseResult.data.confirm_completion})`);
planningConversation.addFunctionResponse(new AIFunctionResponse(
@ -171,7 +176,7 @@ export class OrchestrationAgent extends AIController {
functionCall.toolId
));
orchestrationResult = new OrchestrationResult({ continue: true, continueContext: parseResult.data.context_for_next_step });
return { shouldExit: true }
return Promise.resolve({ shouldExit: true });
}
if (isAIFunction(functionCallName, AIFunction.CompletePlan)) {
@ -182,7 +187,7 @@ export class OrchestrationAgent extends AIController {
{ error: `Invalid arguments for ${AIFunction.CompletePlan}: ${parseResult.error.message}` },
functionCall.toolId
));
return { shouldExit: false };
return Promise.resolve({ shouldExit: false });
}
if (!parseResult.data.confirm_completion) {
planningConversation.addFunctionResponse(new AIFunctionResponse(
@ -190,7 +195,7 @@ export class OrchestrationAgent extends AIController {
{ error: "Confirmation was false, no action taken" },
functionCall.toolId
));
return { shouldExit: false };
return Promise.resolve({ shouldExit: false });
}
this.debugService?.log("Orchestration", `CompletePlan called (confirmed: ${parseResult.data.confirm_completion})`);
planningConversation.addFunctionResponse(new AIFunctionResponse(
@ -199,7 +204,7 @@ export class OrchestrationAgent extends AIController {
functionCall.toolId
));
orchestrationResult = new OrchestrationResult({ complete: true });
return { shouldExit: true }
return Promise.resolve({ shouldExit: true });
}
if (isAIFunction(functionCallName, AIFunction.Replan)) {
@ -210,7 +215,7 @@ export class OrchestrationAgent extends AIController {
{ error: `Invalid arguments for ${AIFunction.Replan}: ${parseResult.error.message}` },
functionCall.toolId
));
return { shouldExit: false };
return Promise.resolve({ shouldExit: false });
}
this.debugService?.log("Orchestration", `Replan requested: ${parseResult.data.context}`);
planningConversation.addFunctionResponse(new AIFunctionResponse(
@ -219,7 +224,7 @@ export class OrchestrationAgent extends AIController {
functionCall.toolId
));
orchestrationResult = new OrchestrationResult({ replan: true, replanContext: parseResult.data.context });
return { shouldExit: true }
return Promise.resolve({ shouldExit: false });
}
if (isAIFunction(functionCallName, AIFunction.CancelPlan)) {
@ -230,7 +235,7 @@ export class OrchestrationAgent extends AIController {
{ error: `Invalid arguments for ${AIFunction.CancelPlan}: ${parseResult.error.message}` },
functionCall.toolId
));
return { shouldExit: false };
return Promise.resolve({ shouldExit: false });
}
this.debugService?.log("Orchestration", `Plan cancellation requested: ${parseResult.data.context}`);
planningConversation.addFunctionResponse(new AIFunctionResponse(
@ -239,10 +244,10 @@ export class OrchestrationAgent extends AIController {
functionCall.toolId
));
orchestrationResult = new OrchestrationResult({ abort: true, abortContext: parseResult.data.context });
return { shouldExit: true }
return Promise.resolve({ shouldExit: true });
}
return { shouldExit: false };
return Promise.resolve({ shouldExit: false });
});
if (!orchestrationResult) {
@ -261,7 +266,7 @@ export class OrchestrationAgent extends AIController {
return input.goal + context;
}
private async setAgentPromptAndTools(): Promise<void> {
private setAgentPromptAndTools(): void {
if (!this.ai) { // this shouldn't ever happen
Exception.throw("Error: No AI provider has been set!");
}

View file

@ -9,7 +9,7 @@ export class DebugService {
}
public log(level: string, message: string): void {
console.log(`%c${level}: ${message}`, `color:${this.debugColor};`);
console.debug(`%c${level}: ${message}`, `color:${this.debugColor};`);
}
}

View file

@ -106,12 +106,9 @@ export class VaultCacheService {
break;
case FileEvent.Delete:
if (shouldCacheOldPath) {
this.wikiLinks.removeWikiLink(file);
this.files.delete(args.oldPath);
const orphanedTags = this.mapping.deleteFromMapping(args.oldPath);
orphanedTags.forEach(tag => this.tags.delete(tag));
}
this.wikiLinks.removeWikiLink(file);
this.files.delete(file.path);
this.mapping.deleteFromMapping(file.path).forEach(tag => this.tags.delete(tag));
break;
}
this.fuzzySortPrepareTags();
@ -134,9 +131,7 @@ export class VaultCacheService {
break;
case FileEvent.Delete:
if (shouldCacheOldPath) {
this.folders.delete(args.oldPath);
}
this.folders.delete(file.path);
break;
case FileEvent.Modify: