From b221e7a95cc27c8b0b17c7322bea02b88888e033 Mon Sep 17 00:00:00 2001 From: Jeff Carr Date: Thu, 21 Aug 2025 12:30:36 -0500 Subject: [PATCH] add ConfigSave() --- argv.go | 5 +- argvAutoshell.go | 37 +-------------- format_rich_log.go | 112 +++++++++++++++++++++++++++++++++++++++++++++ main.go | 15 +++--- 4 files changed, 126 insertions(+), 43 deletions(-) create mode 100644 format_rich_log.go diff --git a/argv.go b/argv.go index 38a01f6..d1ce699 100644 --- a/argv.go +++ b/argv.go @@ -10,8 +10,9 @@ package main var argv args type args struct { + Add *EmptyCmd `arg:"subcommand:add" help:"add a conversation"` + Format *EmptyCmd `arg:"subcommand:format" help:"add a conversation"` Playback *PlaybackCmd `arg:"subcommand:playback" help:"dump your prior conversations to the terminal'"` - Add *EmptyCmd `arg:"subcommand:add" help:"add a conversation"` Force bool `arg:"--force" help:"try to strong arm things"` Verbose bool `arg:"--verbose" help:"show more output"` Bash bool `arg:"--bash" help:"generate bash completion"` @@ -22,7 +23,7 @@ type EmptyCmd struct { } type PlaybackCmd struct { - List *EmptyCmd `arg:"subcommand:list" help:"list memories"` + List *EmptyCmd `arg:"subcommand:list" help:"list memories"` Force bool `arg:"--all" help:"try to strong arm things"` } diff --git a/argvAutoshell.go b/argvAutoshell.go index a1a426f..912d799 100644 --- a/argvAutoshell.go +++ b/argvAutoshell.go @@ -30,7 +30,7 @@ func (args) doBashAuto() { default: if argv.BashAuto[0] == ARGNAME { // list the subcommands here - fmt.Println("playback add") + fmt.Println("add format playback") } } os.Exit(0) @@ -51,43 +51,10 @@ func (args) doBashHelp() { return } fmt.Fprintln(os.Stderr, "") - fmt.Fprintln(os.Stderr, "hello world") + fmt.Fprintln(os.Stderr, "something went wrong with the GO args package") fmt.Fprintln(os.Stderr, "") } -/* -// complete -F forge --bash forge -func (args) doBash() { - fmt.Println("# add this in your bashrc:") - fmt.Println("") - fmt.Println("# todo: add this to go-arg as a 'hidden' go-arg option --bash") - fmt.Println("#") - fmt.Println("# todo: can this output work/parse with:") - fmt.Println("# complete -C `" + ARGNAME + " --bash` " + ARGNAME) - fmt.Println("") - fmt.Println("_" + ARGNAME + "_complete()") - fmt.Println("{") - fmt.Println(" # sets local to this func vars") - fmt.Println(" local cur prev all") - fmt.Println(" cur=${COMP_WORDS[COMP_CWORD]}") - fmt.Println(" prev=${COMP_WORDS[COMP_CWORD-1]}") - fmt.Println(" all=${COMP_WORDS[@]}") - fmt.Println("") - fmt.Println(" # this is where we generate the go-arg output") - fmt.Println(" GOARGS=$(" + ARGNAME + " --auto-complete $prev \\'$cur\\' $all)") - fmt.Println("") - fmt.Println(" # this compares the command line input from the user") - fmt.Println(" # to whatever strings we output") - fmt.Println(" COMPREPLY=( $(compgen -W \"$GOARGS\" -- $cur) ) # THIS WORKS") - fmt.Println(" return 0") - fmt.Println("}") - fmt.Println("complete -F _" + ARGNAME + "_complete " + ARGNAME) - fmt.Println("") - fmt.Println("# copy and paste the above into your bash shell should work") - os.Exit(0) -} -*/ - // complete -F forge --bash forge func (args) doBash() { fmt.Println("# add this in your bashrc:") diff --git a/format_rich_log.go b/format_rich_log.go new file mode 100644 index 0000000..ddf75bf --- /dev/null +++ b/format_rich_log.go @@ -0,0 +1,112 @@ +package main + +import ( + "fmt" + "os" + "path/filepath" + "strings" + + "go.wit.com/lib/protobuf/chatpb" + "go.wit.com/log" +) + +const termWidth = 120 // The target width for the formatted output boxes. + +func formatRichLog(filename string) *chatpb.Chats { + 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() + + // Handle content: prefer content_file, fallback to content. + var content string + if contentFile := chat.GetContentFile(); contentFile != "" { + // Construct the full path relative to the log file's directory. + logDir := filepath.Dir(filename) + contentPath := filepath.Join(logDir, contentFile) + + contentBytes, err := os.ReadFile(contentPath) + if err != nil { + content = fmt.Sprintf("--- ERROR: Could not read content file %s: %v ---", contentPath, err) + } else { + content = string(contentBytes) + } + } else { + // Fallback for older log formats. + content = chat.GetContent() + } + + // Print the conversational content first. + if content != "" { + // Trim trailing newlines for cleaner output. + fmt.Printf("✦ %s: %s\n", author, strings.TrimSpace(content)) + } + + // Now, format and print any tool calls. + for _, toolCall := range chat.GetToolCalls() { + printToolCallBox(toolCall) + } + } + + return logData +} + +// printToolCallBox handles the decorative formatting for a single tool call. +func printToolCallBox(tc *chatpb.ToolCall) { + boxWidth := termWidth - 2 // Account for the side borders. + + // --- Top Border --- + fmt.Printf(" ╭%s╮\n", strings.Repeat("─", boxWidth)) + + // --- Header Line --- + header := fmt.Sprintf(" ✔ %s %s (%s)", tc.GetName(), tc.GetInput(), tc.GetDescription()) + printWrappedLine(header, boxWidth) + printEmptyLine(boxWidth) + + // --- Stdout --- + if stdout := tc.GetOutputStdout(); stdout != "" { + for _, line := range strings.Split(stdout, "\n") { + printWrappedLine(" "+line, boxWidth) + } + } + + // --- Stderr --- + if stderr := tc.GetOutputStderr(); stderr != "" { + for _, line := range strings.Split(stderr, "\n") { + printWrappedLine(" "+line, boxWidth) + } + } + + printEmptyLine(boxWidth) + + // --- Bottom Border --- + 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, "") +} diff --git a/main.go b/main.go index 5d9585f..ac443c6 100644 --- a/main.go +++ b/main.go @@ -55,18 +55,21 @@ func main() { os.Exit(0) } - if argv.Playback != nil { - log.Info("do playback here") - okExit("") - } - if argv.Add != nil { log.Info("add new conversation to protobuf") okExit("") } + if argv.Playback != nil { + log.Info("do playback here") + pb := formatRichLog("log/2025-08-20-final.text") + pb.ConfigSave() + okExit("") + } + log.Info("trying chatpb") - chatpb.TestChat() + pb := chatpb.ExampleChat() + pb.ConfigSave() // if opening the GUI, always check git for dirty repos log.Info("open the gui here")