Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 1 addition & 7 deletions cmd/chat.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ const (
)

var chatCmd = &cobra.Command{
Use: "chat",
Short: "Interact with your agent.",
Long: `This cli tool allows you to debug your agent by chatting with it locally.`,
Run: agentChat,
Expand Down Expand Up @@ -74,10 +75,3 @@ func agentChat(cmd *cobra.Command, args []string) {
fmt.Println(err)
}
}

func Execute() {
err := chatCmd.Execute()
if err != nil {
os.Exit(1)
}
}
31 changes: 31 additions & 0 deletions cmd/rootCmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// rootCmd.go
package cmd

import (
"fmt"
"os"

"github.com/spf13/cobra"
)

var rootCmd = &cobra.Command{
Use: "gh-debug-cli",
Short: "A CLI tool for debugging",
Long: `This CLI tool allows you to debug your agent by chatting with it locally.`,
Run: func(cmd *cobra.Command, args []string) {
fmt.Println("Use 'gh-debug-cli --help' to see available commands")
},
}

func Execute() {
if err := rootCmd.Execute(); err != nil {
fmt.Println(err)
os.Exit(1)
}
}

func init() {
// Add subcommands to rootCmd
rootCmd.AddCommand(chatCmd)
rootCmd.AddCommand(streamCmd)
}
38 changes: 38 additions & 0 deletions cmd/stream.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// stream.go
package cmd

import (
"fmt"
"os"

"github.com/github-technology-partners/gh-debug-cli/pkg/stream"
"github.com/spf13/cobra"
)

const (
streamCmdFileFlag = "file"
)

// streamCmd represents the new command for streaming functionality
var streamCmd = &cobra.Command{
Use: "stream [file]",
Short: "Stream data to your agent",
Long: `The stream command allows you to initiate a data stream to your agent.`,
Run: agentStream,
}

func init() {
streamCmd.PersistentFlags().String(streamCmdFileFlag, "", "Parse agent responses from a file")
}

func agentStream(cmd *cobra.Command, args []string) {
fmt.Println("stream command executed successfully")

file := args[0]

err := stream.ParseFile(file)
if err != nil {
fmt.Fprintf(os.Stderr, "Error parsing file: %v\n", err)
os.Exit(1)
}
}
75 changes: 75 additions & 0 deletions pkg/stream/parse.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
package stream

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

type Choice struct {
Delta struct {
Content string `json:"content"`
} `json:"delta"`
}

type Data struct {
Choices []Choice `json:"choices"`
}

func ParseFile(filename string) error {
// Open the file
file, err := os.Open(filename)
if err != nil {
return fmt.Errorf("could not open file: %w", err)
}
defer file.Close()

scanner := bufio.NewScanner(file)
var contentBuilder strings.Builder

for scanner.Scan() {
line := scanner.Text()

// Check if the line has "data: " prefix
if strings.HasPrefix(line, "data: ") {
// Remove the "data: " prefix
line = strings.TrimPrefix(line, "data: ")
} else {
continue // skip lines without "data: "

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For now it's fine, we may want to think in the future of how to handle this for other SSE even types.

}

// Handle special cases
if line == "[DONE]" {
break // stop processing if we encounter [DONE]
}
if line == "" {
continue // skip empty data lines
}

// Parse the JSON line into our `Data` struct
var data Data
err := json.Unmarshal([]byte(line), &data)
if err != nil {
// Skip this line if JSON is incomplete or malformed
continue
Comment on lines +55 to +56

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am actually not sure if we want to silently skip this. I'd want to know if the stream is invalid somehow. You will have to deal with two special case:

  1. data: [DONE]
  2. data line being empty

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note; I see you made the updates to check for 1 and 2, but we are still silently skipping everything else. If we fail to parse any other data line it should fail and not continue.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, I misunderstood. Will make a new pr to address

}

// Extract delta.content and concatenate it
for _, choice := range data.Choices {
contentBuilder.WriteString(choice.Delta.Content)
}
}

// Check for scanner errors
if err := scanner.Err(); err != nil {
return fmt.Errorf("error reading file: %w", err)
}

// Print the final concatenated result
result := contentBuilder.String()
fmt.Println(result)
Comment on lines +70 to +72

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you need result 😉


return nil
}