๐Ÿ“ฆ Kong / volcano-sdk

๐Ÿ“„ progress.subagent.e2e.test.ts ยท 62 lines
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62import { describe, it, expect } from 'vitest';
import { agent, llmOpenAI } from '../src/volcano-sdk.js';

describe('Sub-agent progress with structured logs (e2e)', () => {
  it('shows correct step numbering for sub-agents (Step 2/3, Step 3/3)', { timeout: 30000 }, async () => {
    if (!process.env.OPENAI_API_KEY) throw new Error('OPENAI_API_KEY required');

    const llm = llmOpenAI({ 
      apiKey: process.env.OPENAI_API_KEY!, 
      model: 'gpt-4o-mini',
      options: { max_completion_tokens: 32, temperature: 0, top_p: 1 }
    });

    // Define sub-agents with progress
    const summarizer = agent({ llm })
      .then({ prompt: "Summarize in one word" });

    const formalizer = agent({ llm })
      .then({ prompt: "Make it formal" });

    const logs: string[] = [];
    const originalLog = console.log;
    const originalWrite = process.stdout.write.bind(process.stdout);

    console.log = (...args: any[]) => { logs.push(args.join(' ')); originalLog(...args); };
    process.stdout.write = (chunk: any): boolean => { logs.push(String(chunk)); return originalWrite(chunk); };

    try {
      await agent({ llm })
        .then({ prompt: "Text: 'Hello World'" })
        .runAgent(summarizer)
        .runAgent(formalizer)
        .run();
    } finally {
      console.log = originalLog;
      process.stdout.write = originalWrite;
    }

    const output = logs.join('');

    // CRITICAL: Verify parent shows header with structured log
    expect(output).toMatch(/\[.*agent="untitled" status=init\] ๐ŸŒ‹ running Volcano agent/);
    
    // CRITICAL: Verify each step is numbered correctly (each agent numbers its own steps from 1)
    expect(output).toMatch(/\[.*agent="untitled" step=1 status=init\] Text: 'Hello World'/);  // Parent step
    expect(output).toMatch(/\[.*agent="untitled" step=1 status=init\] Summarize in one word/);  // Second step (sub-agent 1)
    expect(output).toMatch(/\[.*agent="untitled" step=1 status=init\] Make it formal/);  // Third step (sub-agent 2)
    
    // CRITICAL: Verify sub-agents don't show duplicate headers
    const headerMatches = output.match(/๐ŸŒ‹ running Volcano agent/g);
    expect(headerMatches?.length).toBe(1);  // Only one header
    
    // CRITICAL: Verify only one final summary with structured log
    const summaryMatches = output.match(/\[.*agent="untitled" status=complete\] ๐ŸŽ‰ agent complete/g);
    expect(summaryMatches?.length).toBe(1);
    
    // CRITICAL: Verify no triple newlines
    expect(output).not.toMatch(/\n\n\n/);
  });
});