diff options
Diffstat (limited to 'internal/executor/summary.go')
| -rw-r--r-- | internal/executor/summary.go | 57 |
1 files changed, 57 insertions, 0 deletions
diff --git a/internal/executor/summary.go b/internal/executor/summary.go new file mode 100644 index 0000000..a942de0 --- /dev/null +++ b/internal/executor/summary.go @@ -0,0 +1,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 "" +} |
