fix: v2.22.0 - stable multi-agent workflow (API compatibility & architecture refactor)

This commit is contained in:
Wonseok Jung
2026-04-30 00:58:00 +09:00
parent 7430c91177
commit c69ba168fa
5 changed files with 195 additions and 56 deletions
+28 -30
View File
@@ -20,6 +20,7 @@ import { validatePath, sanitizeCommand } from './security';
import { TransactionManager } from './core/transaction';
import { SessionManager } from './core/session';
import { PlannerAgent, ResearcherAgent, WriterAgent } from './agents/factory';
import { AgentWorkflowManager } from './agents/AgentWorkflowManager';
import { ErrorTranslator } from './core/errorHandler';
import {
AgentExecutionError,
@@ -534,42 +535,38 @@ export class AgentExecutor {
options: any
) {
if (!this.webview) return;
this.stop(); // Abort any previous run
this.stop();
this.abortController = new AbortController();
const signal = this.abortController.signal;
this.statusBarManager.updateStatus(AgentStatus.Thinking, 'Multi-Agent Workflow Started');
this.statusBarManager.updateStatus(AgentStatus.Thinking, 'Multi-Agent Workflow Running');
this.webview.postMessage({ type: 'streamStart' });
try {
// Instantiate decoupled agents
const planner = new PlannerAgent(modelName);
const researcher = new ResearcherAgent(modelName);
const writer = new WriterAgent(modelName);
let brainContext = 'No specific context available';
try {
const activeBrain = getActiveBrainProfile();
const brainFiles = findBrainFiles(activeBrain.localBrainPath);
brainContext = `Brain: ${activeBrain.name}, Files: ${brainFiles.length}`;
} catch (ctxErr) {
logError('Failed to load brain context for agents', ctxErr);
}
// Prepare Context
const activeBrain = getActiveBrainProfile();
const brainFiles = findBrainFiles(activeBrain.localBrainPath);
const brainContext = `Brain: ${activeBrain.name}, Files: ${brainFiles.length}`;
// 워크플로우 매니저에게 실행 위임 (Strict Synchronization & Contract)
const finalReport = await AgentWorkflowManager.runStrictWorkflow(
prompt,
modelName,
brainContext,
signal,
(step, msg) => {
this.webview.postMessage({ type: 'autoContinue', value: `${step}: ${msg}` });
// 각 단계별 시작을 알림
this.webview.postMessage({ type: 'streamChunk', value: `\n\n> **[${step}]** ${msg}\n\n` });
}
);
// --- Phase 1: Planner ---
if (signal.aborted) return;
this.webview.postMessage({ type: 'autoContinue', value: 'Planner: 전략 수립 중...' });
const plan = await planner.execute(prompt, brainContext, signal);
this.webview.postMessage({ type: 'streamChunk', value: `\n\n### 📝 작업 계획 (Execution Plan)\n${plan}\n\n` });
// --- Phase 2: Researcher ---
if (signal.aborted) return;
this.webview.postMessage({ type: 'autoContinue', value: 'Researcher: 지식 검색 중...' });
const research = await researcher.execute(plan, brainContext, signal);
this.webview.postMessage({ type: 'streamChunk', value: `\n\n### 🔍 분석 결과 (Research Findings)\n*(정보 수집 및 정제 완료)*\n\n` });
// --- Phase 3: Writer ---
if (signal.aborted) return;
this.webview.postMessage({ type: 'autoContinue', value: 'Writer: 보고서 작성 중...' });
const finalReport = await writer.execute(research, prompt, signal);
if (signal.aborted) return;
this.webview.postMessage({ type: 'streamChunk', value: `\n\n--- \n\n${finalReport}` });
this.webview.postMessage({ type: 'streamEnd' });
@@ -577,16 +574,17 @@ export class AgentExecutor {
this.emitHistoryChanged();
this.statusBarManager.updateStatus(AgentStatus.Success, 'Workflow Complete');
this.webview.postMessage({ type: 'autoContinue', value: '✅ 분석이 완료되었습니다!' });
this.webview.postMessage({ type: 'autoContinue', value: '✅ 모든 분석이 성공적으로 완료되었습니다.' });
} catch (error: any) {
if (error.name === 'AbortError' || error.message?.includes('cancelled')) {
this.statusBarManager.updateStatus(AgentStatus.Idle, 'Workflow Cancelled');
return;
}
const friendly = ErrorTranslator.translate(error);
logError('Workflow failed', error);
// Clear autoContinue state by sending empty value or specific type
this.webview.postMessage({ type: 'autoContinue', value: '' });
// Format error using guideline-compliant UI (Red color scheme)
this.webview.postMessage({
type: 'error',
value: `### ${friendly.title}\n\n**상태:** ${friendly.message}\n\n**해결 방법:** ${friendly.action}`