summaryrefslogtreecommitdiff
path: root/internal/executor/summary.go
blob: a942de0049d282ecbaa3c3148486512ef22d6ab4 (plain)
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
package executor

import (
	"bufio"
	"encoding/json"
	"os"
	"strings"
)

// extractSummary reads a stream-json stdout log and returns the text following
// the last "## Summary" heading found in any assistant text block.
// Returns empty string if the file cannot be read or no summary is found.
func extractSummary(stdoutPath string) string {
	f, err := os.Open(stdoutPath)
	if err != nil {
		return ""
	}
	defer f.Close()

	var last string
	scanner := bufio.NewScanner(f)
	scanner.Buffer(make([]byte, 1024*1024), 1024*1024)
	for scanner.Scan() {
		if text := summaryFromLine(scanner.Bytes()); text != "" {
			last = text
		}
	}
	return last
}

// summaryFromLine parses a single stream-json line and returns the text after
// "## Summary" if the line is an assistant text block containing that heading.
func summaryFromLine(line []byte) string {
	var event struct {
		Type    string `json:"type"`
		Message struct {
			Content []struct {
				Type string `json:"type"`
				Text string `json:"text"`
			} `json:"content"`
		} `json:"message"`
	}
	if err := json.Unmarshal(line, &event); err != nil || event.Type != "assistant" {
		return ""
	}
	for _, block := range event.Message.Content {
		if block.Type != "text" {
			continue
		}
		idx := strings.Index(block.Text, "## Summary")
		if idx == -1 {
			continue
		}
		return strings.TrimSpace(block.Text[idx+len("## Summary"):])
	}
	return ""
}