Bỏ qua để đến nội dung

Luồng hoạt động

Tìm hiểu chi tiết về cách Galaxy CLI xử lý các tình huống khác nhau từ input đến output.

Galaxy CLI có 3 workflows chính:

  1. Create Project - Tạo dự án mới từ đầu
  2. Update Project - Thêm feature vào dự án hiện có
  3. Q&A Mode - Trả lời câu hỏi trực tiếp
User: "Tạo app Next.js e-commerce"
┌─────────────────────────────────────┐
│ Orchestrator: Phân tích yêu cầu │
│ → Gọi ba_it_analyze() │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ BA Agent: Analyze Requirements │
│ - Xác định type: create_project │
│ - Define tech stack │
│ - List core features │
│ - Create data models │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Orchestrator: Present Analysis (VI) │
│ "📊 Phân tích dự án..." │
│ "Bạn đồng ý?" │
└─────────────────────────────────────┘
User: "yes, làm đi"
┌─────────────────────────────────────┐
│ Orchestrator: Gọi plan_task() │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Planning Agent: Create Plan │
│ - Map features → steps │
│ - Select tools │
│ - Add test/review steps if enabled │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Orchestrator: Present Plan │
│ "📋 Implementation Plan:" │
│ "☐ Step 1: Initialize..." │
│ "☐ Step 2: Implement Feature A" │
└─────────────────────────────────────┘
User: "yes" (or auto-execute)
┌─────────────────────────────────────┐
│ Orchestrator: Execute Steps │
│ Loop through each step: │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Step 1: command_run │
│ → npx create-next-app... │
│ ☒ Completed │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Step 2: install_dependencies │
│ → Auto-detect & install │
│ ☒ Completed │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Step 3: code_generate │
│ Feature: Product Catalog │
│ → Code Gen Agent executes │
│ → Generates files │
│ ☒ Completed (created 4 files) │
└─────────────────────────────────────┘
... (repeat for each feature)
┌─────────────────────────────────────┐
│ Orchestrator: Summary │
│ "✅ All steps completed!" │
│ "Created 42 files" │
└─────────────────────────────────────┘
  1. User Input Processing

    orchestrator.handleUserInput(
    "Tạo app Next.js e-commerce"
    );
  2. BA Analysis

    const analysis = await ba_it_analyze({
    userRequest: "Tạo app Next.js e-commerce",
    currentContext: { projectPath: process.cwd() }
    });
    // Returns:
    {
    projectName: "Next.js E-commerce",
    type: "create_project",
    coreFeatures: [...],
    technicalStack: {...},
    dataModels: [...],
    apiEndpoints: [...]
    }
  3. User Confirmation

    Orchestrator presents analysis và chờ user confirm.

  4. Planning

    const plan = await plan_task({
    userContext: "Tạo app Next.js e-commerce",
    baAnalysis: analysis,
    systemContext: {
    testEnabled: false,
    reviewEnabled: false
    }
    });
    // Returns:
    {
    steps: [
    { step: 1, tool: 'command_run', action: 'Initialize' },
    { step: 2, tool: 'install_dependencies' },
    { step: 3, tool: 'code_generate', featureName: 'Feature A' },
    ...
    ]
    }
  5. Execution Loop

    for (const step of plan.steps) {
    await orchestrator.executeStep(step);
    updateProgress(step.step, 'completed');
    }
User: "Thêm authentication vào dự án"
┌─────────────────────────────────────┐
│ Orchestrator: Phân tích context │
│ → Scan project files │
│ → Gọi ba_it_analyze() │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ BA Agent: Analyze Feature │
│ - type: update_project │
│ - Analyze existing structure │
│ - Plan integration points │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Orchestrator: Present Analysis │
└─────────────────────────────────────┘
User confirms
┌─────────────────────────────────────┐
│ Planning Agent: Create Plan │
│ - Skip project initialization │
│ - Focus on feature implementation │
│ - Add integration steps │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Execute Steps │
│ - Update existing files │
│ - Create new files │
│ - Integrate with existing code │
└─────────────────────────────────────┘
steps = [
{ step: 1, tool: 'command_run',
action: 'Initialize project' },
{ step: 2, tool: 'install_dependencies' },
{ step: 3, tool: 'code_generate',
featureName: 'Feature A' },
...
]
User: "React hooks là gì?"
┌─────────────────────────────────────┐
│ Orchestrator: Direct Answer │
│ - No BA analysis needed │
│ - No planning needed │
│ - Use knowledge to answer │
└─────────────────────────────────────┘
Response: [Detailed explanation]
User: "Giải thích code này: [paste code]"
┌─────────────────────────────────────┐
│ Orchestrator: Analyze Code │
│ - Parse code structure │
│ - Identify patterns │
│ - Explain functionality │
└─────────────────────────────────────┘
Response: [Code explanation]

Orchestrator quyết định workflow dựa trên input:

function decideWorkflow(userInput: string) {
// Q&A Mode
if (isQuestion(userInput)) {
return 'qa_mode';
}
// Create Project
if (isNewProjectRequest(userInput)) {
return 'create_project';
}
// Update Project
if (isFeatureRequest(userInput)) {
return 'update_project';
}
// Analysis
if (isAnalysisRequest(userInput)) {
return 'analyze_project';
}
}
function isNewProjectRequest(input: string): boolean {
const patterns = [
/tạo.*app/i,
/create.*app/i,
/build.*project/i,
/khởi tạo.*dự án/i
];
return patterns.some(p => p.test(input));
}
function isFeatureRequest(input: string): boolean {
const patterns = [
/thêm.*feature/i,
/add.*feature/i,
/implement/i,
/tích hợp/i
];
return patterns.some(p => p.test(input));
}
interface ProgressState {
projectName: string;
currentStep: number;
totalSteps: number;
steps: Array<{
step: number;
action: string;
status: 'pending' | 'in-progress' | 'completed' | 'failed';
}>;
}
interface ConversationState {
messages: Message[];
currentPhase: 'analysis' | 'planning' | 'execution' | 'complete';
pendingConfirmation?: {
type: 'ba_analysis' | 'plan';
data: any;
};
}
async function executeStepWithRetry(
step: Step,
maxRetries: number = 3
): Promise<Result> {
let attempt = 0;
while (attempt < maxRetries) {
try {
const result = await executeStep(step);
return result;
} catch (error) {
attempt++;
if (attempt >= maxRetries) {
return {
status: 'failed',
error: error.message
};
}
// Exponential backoff
await sleep(1000 * Math.pow(2, attempt));
}
}
}
Step fails
Retry (max 3 times)
Still fails?
┌─────────────────────────────────────┐
│ Orchestrator: Ask user │
│ "Step 3 failed. Options:" │
│ 1. Retry │
│ 2. Skip │
│ 3. Abort │
└─────────────────────────────────────┘

Một số steps có thể chạy song song:

// Sequential (default)
await executeStep(step1);
await executeStep(step2);
await executeStep(step3);
// Parallel (when safe)
await Promise.all([
executeStep(step1), // Independent
executeStep(step2), // Independent
executeStep(step3) // Independent
]);
code_generate tool called
┌─────────────────────────────────────┐
│ Code Gen Agent │
│ 1. Generate code │
│ 2. Call file_write tool │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ file_write tool │
│ 1. Check if file exists │
│ 2. Create directories if needed │
│ 3. Write content │
│ 4. Calculate diff │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Return result to Code Gen Agent │
│ { isNewFile, linesAdded, ... } │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Code Gen Agent aggregates results │
│ { filesCreated: [...] } │
└─────────────────────────────────────┘
┌─────────────────────────────────────┐
│ Return to Orchestrator │
│ Update progress: ☒ Step N completed │
└─────────────────────────────────────┘

Galaxy CLI cập nhật UI real-time:

// Update todos
updateTodoStatus(stepNumber, 'in-progress');
// ☐ → ⚙
// Tool execution
showToolExecution('file_write', 'app.tsx');
// 📝 APPLY PATCH (app.tsx)
// Completion
updateTodoStatus(stepNumber, 'completed');
// ⚙ → ☒
// LLM responses stream token-by-token
for await (const chunk of llmStream) {
process.stdout.write(chunk);
}
interface Context {
conversation: Message[]; // Recent messages
project: ProjectInfo; // Current project
progress: ProgressState; // Execution state
config: UserConfig; // Settings
}
// Context pruning (keep recent + important)
function pruneContext(context: Context) {
return {
conversation: context.conversation.slice(-10),
project: context.project,
progress: context.progress,
config: context.config
};
}
// Cache BA analysis results
const cacheKey = hash(userRequest);
const cached = cache.get(cacheKey);
if (cached && !expired(cached)) {
return cached.result;
}
const result = await ba_it_analyze(userRequest);
cache.set(cacheKey, result, ttl: 3600);
// Tools loaded on-demand
async function getTool(name: string) {
if (!loadedTools[name]) {
loadedTools[name] = await import(`./tools/${name}`);
}
return loadedTools[name];
}