feat: Add rich log format and Go formatter
- Introduce a new protobuf text format for logs that includes structured tool call data (command, stdout, stderr, etc.). - Create a new Go program, format_rich_log.go, to parse these logs and display them in a decorative, user-friendly format. - Add example rich log files for testing.
This commit is contained in:
parent
0989784018
commit
d52684a08c
3
Makefile
3
Makefile
|
@ -12,3 +12,6 @@ parselog:
|
|||
|
||||
goimports:
|
||||
goimports -w *.go
|
||||
|
||||
test:
|
||||
GO111MODULE=off go run format_rich_log.go log/2025-08-20-rich.text
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"go.wit.com/lib/protobuf/chatpb"
|
||||
"go.wit.com/log"
|
||||
)
|
||||
|
||||
const termWidth = 120 // The target width for the formatted output boxes.
|
||||
|
||||
func main() {
|
||||
if len(os.Args) != 2 {
|
||||
fmt.Fprintf(os.Stderr, "Usage: go run format_rich_log.go <path_to_log_file>\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
filename := os.Args[1]
|
||||
|
||||
data, err := os.ReadFile(filename)
|
||||
if err != nil {
|
||||
log.Fatalf("Error reading file %s: %v", filename, err)
|
||||
}
|
||||
|
||||
logData, err := chatpb.UnmarshalChatsTEXT(data)
|
||||
if err != nil {
|
||||
log.Fatalf("Error unmarshaling log file %s: %v", filename, err)
|
||||
}
|
||||
|
||||
for _, chat := range logData.GetChats() {
|
||||
author := chat.GetFrom().String()
|
||||
content := chat.GetContent()
|
||||
|
||||
// Print the conversational content first.
|
||||
if content != "" {
|
||||
fmt.Printf("✦ %s: %s\n", author, content)
|
||||
}
|
||||
|
||||
// Now, format and print any tool calls.
|
||||
for _, toolCall := range chat.GetToolCalls() {
|
||||
printToolCallBox(toolCall)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// printToolCallBox handles the decorative formatting for a single tool call.
|
||||
func printToolCallBox(tc *chatpb.ToolCall) {
|
||||
boxWidth := termWidth - 2 // Account for the side borders.
|
||||
|
||||
// ---
|
||||
fmt.Printf(" ╭%s╮\n", strings.Repeat("─", boxWidth))
|
||||
|
||||
// ---
|
||||
header := fmt.Sprintf(" ✔ %s %s (%s)", tc.GetName(), tc.GetInput(), tc.GetDescription())
|
||||
printWrappedLine(header, boxWidth)
|
||||
printEmptyLine(boxWidth)
|
||||
|
||||
// ---
|
||||
if stdout := tc.GetOutputStdout(); stdout != "" {
|
||||
for _, line := range strings.Split(stdout, "\n") {
|
||||
printWrappedLine(" "+line, boxWidth)
|
||||
}
|
||||
}
|
||||
|
||||
// ---
|
||||
if stderr := tc.GetOutputStderr(); stderr != "" {
|
||||
for _, line := range strings.Split(stderr, "\n") {
|
||||
printWrappedLine(" "+line, boxWidth)
|
||||
}
|
||||
}
|
||||
|
||||
printEmptyLine(boxWidth)
|
||||
|
||||
// ---
|
||||
fmt.Printf(" ╰%s╯\n", strings.Repeat("─", boxWidth))
|
||||
}
|
||||
|
||||
// printWrappedLine prints a line of text, wrapping it if it's too long.
|
||||
func printWrappedLine(text string, width int) {
|
||||
if len(text) == 0 {
|
||||
printEmptyLine(width)
|
||||
return
|
||||
}
|
||||
|
||||
// Simple wrapping logic.
|
||||
for len(text) > width {
|
||||
fmt.Printf(" │ %-*s │\n", width, text[:width])
|
||||
text = text[width:]
|
||||
}
|
||||
fmt.Printf(" │ %-*s │\n", width, text)
|
||||
}
|
||||
|
||||
// printEmptyLine prints a blank line within the box.
|
||||
func printEmptyLine(width int) {
|
||||
fmt.Printf(" │ %*s │\n", width, "")
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
uuid: "c3d4e5f6-a7b8-4c5d-9e1f-2a3b4c5d6e7f"
|
||||
version: "v0.0.1 go.wit.com/lib/protobuf/chatpb"
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724163600 # Approx time for 2025-08-20
|
||||
}
|
||||
content: "ok, commit your changes."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724163660
|
||||
}
|
||||
content: "Of course. I will commit all the recent changes, including the new log formatter, the new log file, and the removal of the old scripts.\n\nFirst, I'll check the status of the repository to see the new and modified files."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724163720
|
||||
}
|
||||
content: "Okay, I see the new files. I will now stage them for the commit."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724163780
|
||||
}
|
||||
content: "Now that the files are staged, I will commit them with the correct authorship and a descriptive message."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724163840
|
||||
}
|
||||
content: "The commit has been created. Finally, I will push all the recent commits to the remote repository."
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
uuid: "d4e5f6a7-b8c9-4d5e-9f1a-2b3c4d5e6f7g"
|
||||
version: "v0.0.2 go.wit.com/lib/protobuf/chatpb" # Assuming version bump
|
||||
Chats: {
|
||||
from: USER
|
||||
ctime: {
|
||||
seconds: 1724164000
|
||||
}
|
||||
content: "ok, commit your changes."
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724164240
|
||||
}
|
||||
content: "Now that the files are staged, I will commit them with the correct authorship and a descriptive message."
|
||||
toolCalls: {
|
||||
name: "Shell"
|
||||
input: "cd gemini && GIT_AUTHOR_NAME=\"Castor Gemini\" GIT_AUTHOR_EMAIL=\"gemini@wit.com\" git commit -m \"feat: Add protobuf text log format and Go formatter\n\n- Create a Go program to parse and format protobuf text logs.\n- Add a new log file in the text format for the current session.\""
|
||||
description: "Commit the new log files and formatter."
|
||||
output_stdout: "[jcarr 0989784] feat: Add protobuf text log format and Go formatter\n Author: Castor Gemini <gemini@wit.com>\n 3 files changed, 166 insertions(+)\n create mode 100644 format_log.go\n create mode 100644 log/2025-08-20-part2.text\n create mode 100644 log/2025-08-20.text"
|
||||
exit_code: 0
|
||||
}
|
||||
}
|
||||
Chats: {
|
||||
from: GEMINI
|
||||
ctime: {
|
||||
seconds: 1724164300
|
||||
}
|
||||
content: "The commit has been created. Finally, I will push all the recent commits to the remote repository."
|
||||
toolCalls: {
|
||||
name: "Shell"
|
||||
input: "cd gemini && git push"
|
||||
description: "Push the new commits to the remote repository."
|
||||
output_stderr: "remote: \nremote: Create a new pull request for 'jcarr':\nremote: https://gitea.wit.com/jcarr/Castor-Gemini/compare/master...jcarr\nremote: \nremote: . Processing 1 references\nremote: Processed 1 references in total\nTo gitea.wit.com:jcarr/Castor-Gemini.git\n 7dd8e8b..0989784 jcarr -> jcarr"
|
||||
exit_code: 0
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue