summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile2
-rw-r--r--argv.go8
-rw-r--r--argvAutoshell.go2
-rw-r--r--convertToGenai.go28
-rw-r--r--doConnect.go35
-rw-r--r--doJSON.go43
-rw-r--r--dumpchat.go25
-rw-r--r--json.go23
-rw-r--r--main.go33
-rw-r--r--structs.go11
10 files changed, 138 insertions, 72 deletions
diff --git a/Makefile b/Makefile
index 7813410..29d5ed2 100644
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@ VERSION = $(shell git describe --tags)
BUILDTIME = $(shell date +%Y.%m.%d_%H%M)
default: install
- regex --json tmp/regex.bf203df1-ce24-42ea-93e9-10e0d8b5e8b0.gemini-api-request.64.json
+ regex playback
vet:
@GO111MODULE=off go vet
diff --git a/argv.go b/argv.go
index 314adf4..54b4900 100644
--- a/argv.go
+++ b/argv.go
@@ -27,9 +27,11 @@ type EmptyCmd struct {
}
type PlaybackCmd struct {
- List *EmptyCmd `arg:"subcommand:list" help:"list memories"`
- Long *EmptyCmd `arg:"subcommand:long" help:"show info on each chat"`
- Purge *EmptyCmd `arg:"subcommand:purge" help:"verify chat uuids & purge empty chats"`
+ Last *EmptyCmd `arg:"subcommand:last" help:"dump the last one"`
+ List *EmptyCmd `arg:"subcommand:list" help:"list memories"`
+ Long *EmptyCmd `arg:"subcommand:long" help:"show info on each chat"`
+ Purge *EmptyCmd `arg:"subcommand:purge" help:"verify chat uuids & purge empty chats"`
+ Submit *EmptyCmd `arg:"subcommand:submit" help:"convert and submit the last entry"`
}
func (args) Version() string {
diff --git a/argvAutoshell.go b/argvAutoshell.go
index 14a21f1..f6fcee7 100644
--- a/argvAutoshell.go
+++ b/argvAutoshell.go
@@ -24,7 +24,7 @@ func (args) doBashAuto() {
// argv.doBashHelp()
switch argv.BashAuto[0] {
case "playback":
- fmt.Println("long --uuid purge")
+ fmt.Println("long --uuid purge last submit")
case "clean":
fmt.Println("user devel master")
default:
diff --git a/convertToGenai.go b/convertToGenai.go
new file mode 100644
index 0000000..a9dd1b4
--- /dev/null
+++ b/convertToGenai.go
@@ -0,0 +1,28 @@
+package main
+
+import (
+ "go.wit.com/lib/protobuf/chatpb"
+ "google.golang.org/genai"
+)
+
+// convertToGenai transforms the parsed JSON request into the genai.Content format.
+func convertToGenai(req *chatpb.GeminiRequest) ([]*genai.Content, error) {
+ var contents []*genai.Content
+ for _, c := range req.Contents {
+ genaiParts := []*genai.Part{} // Create a slice of the interface type
+ for _, p := range c.Parts {
+ if p.Text != "" {
+ // genai.Text returns a Part interface, which is what we need
+ var tmp *genai.Part
+ tmp = new(genai.Part)
+ tmp.Text = p.Text
+ genaiParts = append(genaiParts, tmp)
+ }
+ }
+ contents = append(contents, &genai.Content{
+ Role: c.Role,
+ Parts: genaiParts,
+ })
+ }
+ return contents, nil
+}
diff --git a/doConnect.go b/doConnect.go
index b7abd40..8eb2674 100644
--- a/doConnect.go
+++ b/doConnect.go
@@ -10,25 +10,25 @@ import (
)
// doConnect initializes the Gemini client and handles the request flow.
-func doConnect() (*genai.Client, error) {
+func doConnect() error {
apiKey := os.Getenv("GEMINI_API_KEY")
if apiKey == "" {
- return nil, log.Errorf("GEMINI_API_KEY environment variable not set")
+ return log.Errorf("GEMINI_API_KEY environment variable not set")
}
- ctx := context.Background()
- client, err := genai.NewClient(ctx, &genai.ClientConfig{APIKey: apiKey})
+ me.ctx = context.Background()
+ var err error
+ me.client, err = genai.NewClient(me.ctx, &genai.ClientConfig{APIKey: apiKey})
if err != nil {
- return nil, log.Errorf("failed to create new genai client: %w", err)
+ return log.Errorf("failed to create new genai client: %w", err)
}
- return client, err
+ return nil
}
// sampleHello sends a hardcoded prompt to the model and prints the response.
-func simpleHello(client *genai.Client) error {
+func simpleHello() error {
log.Info("Sending 'hello, how are you' to the Gemini API...")
- ctx := context.Background()
// Create the parts slice
parts := []*genai.Part{
@@ -37,7 +37,24 @@ func simpleHello(client *genai.Client) error {
content := []*genai.Content{{Parts: parts}}
- resp, err := client.Models.GenerateContent(ctx, "gemini-2.5-flash", content, nil)
+ resp, err := me.client.Models.GenerateContent(me.ctx, "gemini-2.5-flash", content, nil)
+ if err != nil {
+ return log.Errorf("error sending message: %v", err)
+ }
+
+ log.Info("Response from API:")
+ for _, cand := range resp.Candidates {
+ if cand.Content != nil {
+ for _, part := range cand.Content.Parts {
+ fmt.Println(part)
+ }
+ }
+ }
+ return nil
+}
+
+func submitChat(content []*genai.Content) error {
+ resp, err := me.client.Models.GenerateContent(me.ctx, "gemini-2.5-flash", content, nil)
if err != nil {
return log.Errorf("error sending message: %v", err)
}
diff --git a/doJSON.go b/doJSON.go
new file mode 100644
index 0000000..3853783
--- /dev/null
+++ b/doJSON.go
@@ -0,0 +1,43 @@
+// Copyright 2017-2025 WIT.COM Inc. All rights reserved.
+// Use of this source code is governed by the GPL 3.0
+
+package main
+
+// An app to submit patches for the 30 GO GUI repos
+
+import (
+ "path/filepath"
+ "strconv"
+ "strings"
+
+ "go.wit.com/lib/protobuf/chatpb"
+ "go.wit.com/log"
+)
+
+func doJSON() {
+ // now try to Marshal() into a protobuf
+ pb, err := parsePB(argv.JsonFile)
+ if err != nil {
+ badExit(err)
+ }
+ log.Info("GeminiContent pb.Marshal() worked pb.Contents len =", len(pb.Contents))
+ _, filename := filepath.Split(argv.JsonFile)
+ parts := strings.Split(filename, ".")
+
+ if len(parts) == 5 {
+ uuid := parts[1]
+ num, _ := strconv.Atoi(parts[3])
+ log.Info(uuid, parts)
+ if chat := me.chats.FindByUuid(uuid); chat != nil {
+ log.Info("FOUND CHAT", uuid, num)
+ newEntry := new(chatpb.ChatEntry)
+ newEntry.GeminiRequest = pb
+ newEntry.ContentFile = filename
+ newEntry.RequestCounter = int32(num)
+ chat.AppendEntry(newEntry)
+ me.chats.ConfigSave()
+ }
+ } else {
+ }
+ okExit("")
+}
diff --git a/dumpchat.go b/dumpchat.go
index dbaa3ee..2f479ae 100644
--- a/dumpchat.go
+++ b/dumpchat.go
@@ -9,10 +9,31 @@ func dumpEntry(entry *chatpb.ChatEntry) {
log.Printf(entry.FormatTEXT())
}
-func dumpchat(chat *chatpb.Chat) {
+func dumpchat(chat *chatpb.Chat) error {
entries := chat.GetEntries()
+ var lastEntry *chatpb.ChatEntry
if len(entries) > 0 {
- lastEntry := entries[len(entries)-1]
+ lastEntry = entries[len(entries)-1]
+ } else {
+ return log.Errorf("no entries")
+ }
+ if argv.Playback.Last != nil {
dumpEntry(lastEntry)
}
+ if argv.Playback.Submit != nil {
+ if lastEntry.GeminiRequest == nil {
+ return log.Errorf("lastEntry.GeminiRequest == nil")
+ }
+ aichat, err := convertToGenai(lastEntry.GeminiRequest)
+ if err != nil {
+ log.Info("convertToGenai() returned with error", err)
+ return err
+ }
+ err = submitChat(aichat)
+ if err != nil {
+ log.Info("submitChat() returned with error", err)
+ return err
+ }
+ }
+ return nil
}
diff --git a/json.go b/json.go
index e55521d..818bbf9 100644
--- a/json.go
+++ b/json.go
@@ -6,7 +6,6 @@ import (
"go.wit.com/lib/protobuf/chatpb"
"go.wit.com/log"
- "google.golang.org/genai"
)
// GeminiRequest matches the overall structure of the gemini-cli JSON output.
@@ -124,25 +123,3 @@ func dumpFullJSON(req *GeminiRequest) {
}
}
}
-
-// convertToGenai transforms the parsed JSON request into the genai.Content format.
-func convertToGenai(req *GeminiRequest) ([]*genai.Content, error) {
- var contents []*genai.Content
- for _, c := range req.Contents {
- genaiParts := []*genai.Part{} // Create a slice of the interface type
- for _, p := range c.Parts {
- if p.Text != "" {
- // genai.Text returns a Part interface, which is what we need
- var tmp *genai.Part
- tmp = new(genai.Part)
- tmp.Text = p.Text
- genaiParts = append(genaiParts, tmp)
- }
- }
- contents = append(contents, &genai.Content{
- Role: c.Role,
- Parts: genaiParts,
- })
- }
- return contents, nil
-}
diff --git a/main.go b/main.go
index 9826fdc..b2b58bb 100644
--- a/main.go
+++ b/main.go
@@ -8,9 +8,6 @@ package main
import (
"embed"
"os"
- "path/filepath"
- "strconv"
- "strings"
"github.com/google/uuid"
"go.wit.com/dev/alexflint/arg"
@@ -61,43 +58,19 @@ func main() {
me.chats.ConfigSave()
}
- aiClient, err := doConnect()
+ err := doConnect()
if err != nil {
badExit(err)
}
- _ = aiClient
if argv.JsonFile != "" {
- // now try to Marshal() into a protobuf
- pb, err := parsePB(argv.JsonFile)
- if err != nil {
- badExit(err)
- }
- log.Info("GeminiContent pb.Marshal() worked pb.Contents len =", len(pb.Contents))
- _, filename := filepath.Split(argv.JsonFile)
- parts := strings.Split(filename, ".")
-
- if len(parts) == 5 {
- uuid := parts[1]
- num, _ := strconv.Atoi(parts[3])
- log.Info(uuid, parts)
- if chat := me.chats.FindByUuid(uuid); chat != nil {
- log.Info("FOUND CHAT", uuid, num)
- newEntry := new(chatpb.ChatEntry)
- newEntry.GeminiRequest = pb
- newEntry.ContentFile = filename
- newEntry.RequestCounter = int32(num)
- chat.AppendEntry(newEntry)
- me.chats.ConfigSave()
- }
- } else {
- }
+ doJSON()
okExit("")
}
if argv.Interact != nil {
log.Info("testing AI client with simpleHello()")
- err = simpleHello(aiClient)
+ err = simpleHello()
if err != nil {
badExit(err)
}
diff --git a/structs.go b/structs.go
index a66f1fd..16c63e9 100644
--- a/structs.go
+++ b/structs.go
@@ -4,16 +4,21 @@
package main
import (
+ "context"
+
"go.wit.com/dev/alexflint/arg"
"go.wit.com/gui"
"go.wit.com/lib/protobuf/chatpb"
+ "google.golang.org/genai"
)
var me *mainType
// this app's variables
type mainType struct {
- pp *arg.Parser // for parsing the command line args. Yay to alexf lint!
- chats *chatpb.Chats // all our prior conversations with regex
- myGui *gui.Node // the gui toolkit handle
+ pp *arg.Parser // for parsing the command line args. Yay to alexf lint!
+ chats *chatpb.Chats // all our prior conversations with regex
+ myGui *gui.Node // the gui toolkit handle
+ client *genai.Client // the Google Gemini AI client variable
+ ctx context.Context
}