attempts to submit data to the Gemini API
This commit is contained in:
parent
eba85c6b97
commit
4a800a7cfd
2
Makefile
2
Makefile
|
@ -2,7 +2,7 @@ VERSION = $(shell git describe --tags)
|
||||||
BUILDTIME = $(shell date +%Y.%m.%d_%H%M)
|
BUILDTIME = $(shell date +%Y.%m.%d_%H%M)
|
||||||
|
|
||||||
default: install
|
default: install
|
||||||
regex --json tmp/regex.bf203df1-ce24-42ea-93e9-10e0d8b5e8b0.gemini-api-request.64.json
|
regex playback
|
||||||
|
|
||||||
vet:
|
vet:
|
||||||
@GO111MODULE=off go vet
|
@GO111MODULE=off go vet
|
||||||
|
|
8
argv.go
8
argv.go
|
@ -27,9 +27,11 @@ type EmptyCmd struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
type PlaybackCmd struct {
|
type PlaybackCmd struct {
|
||||||
List *EmptyCmd `arg:"subcommand:list" help:"list memories"`
|
Last *EmptyCmd `arg:"subcommand:last" help:"dump the last one"`
|
||||||
Long *EmptyCmd `arg:"subcommand:long" help:"show info on each chat"`
|
List *EmptyCmd `arg:"subcommand:list" help:"list memories"`
|
||||||
Purge *EmptyCmd `arg:"subcommand:purge" help:"verify chat uuids & purge empty chats"`
|
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 {
|
func (args) Version() string {
|
||||||
|
|
|
@ -24,7 +24,7 @@ func (args) doBashAuto() {
|
||||||
// argv.doBashHelp()
|
// argv.doBashHelp()
|
||||||
switch argv.BashAuto[0] {
|
switch argv.BashAuto[0] {
|
||||||
case "playback":
|
case "playback":
|
||||||
fmt.Println("long --uuid purge")
|
fmt.Println("long --uuid purge last submit")
|
||||||
case "clean":
|
case "clean":
|
||||||
fmt.Println("user devel master")
|
fmt.Println("user devel master")
|
||||||
default:
|
default:
|
||||||
|
|
|
@ -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
|
||||||
|
}
|
35
doConnect.go
35
doConnect.go
|
@ -10,25 +10,25 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
// doConnect initializes the Gemini client and handles the request flow.
|
// doConnect initializes the Gemini client and handles the request flow.
|
||||||
func doConnect() (*genai.Client, error) {
|
func doConnect() error {
|
||||||
apiKey := os.Getenv("GEMINI_API_KEY")
|
apiKey := os.Getenv("GEMINI_API_KEY")
|
||||||
if apiKey == "" {
|
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()
|
me.ctx = context.Background()
|
||||||
client, err := genai.NewClient(ctx, &genai.ClientConfig{APIKey: apiKey})
|
var err error
|
||||||
|
me.client, err = genai.NewClient(me.ctx, &genai.ClientConfig{APIKey: apiKey})
|
||||||
if err != nil {
|
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.
|
// 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...")
|
log.Info("Sending 'hello, how are you' to the Gemini API...")
|
||||||
ctx := context.Background()
|
|
||||||
|
|
||||||
// Create the parts slice
|
// Create the parts slice
|
||||||
parts := []*genai.Part{
|
parts := []*genai.Part{
|
||||||
|
@ -37,7 +37,24 @@ func simpleHello(client *genai.Client) error {
|
||||||
|
|
||||||
content := []*genai.Content{{Parts: parts}}
|
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 {
|
if err != nil {
|
||||||
return log.Errorf("error sending message: %v", err)
|
return log.Errorf("error sending message: %v", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -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("")
|
||||||
|
}
|
25
dumpchat.go
25
dumpchat.go
|
@ -9,10 +9,31 @@ func dumpEntry(entry *chatpb.ChatEntry) {
|
||||||
log.Printf(entry.FormatTEXT())
|
log.Printf(entry.FormatTEXT())
|
||||||
}
|
}
|
||||||
|
|
||||||
func dumpchat(chat *chatpb.Chat) {
|
func dumpchat(chat *chatpb.Chat) error {
|
||||||
entries := chat.GetEntries()
|
entries := chat.GetEntries()
|
||||||
|
var lastEntry *chatpb.ChatEntry
|
||||||
if len(entries) > 0 {
|
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)
|
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
|
||||||
}
|
}
|
||||||
|
|
23
json.go
23
json.go
|
@ -6,7 +6,6 @@ import (
|
||||||
|
|
||||||
"go.wit.com/lib/protobuf/chatpb"
|
"go.wit.com/lib/protobuf/chatpb"
|
||||||
"go.wit.com/log"
|
"go.wit.com/log"
|
||||||
"google.golang.org/genai"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// GeminiRequest matches the overall structure of the gemini-cli JSON output.
|
// 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
|
|
||||||
}
|
|
||||||
|
|
33
main.go
33
main.go
|
@ -8,9 +8,6 @@ package main
|
||||||
import (
|
import (
|
||||||
"embed"
|
"embed"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/google/uuid"
|
"github.com/google/uuid"
|
||||||
"go.wit.com/dev/alexflint/arg"
|
"go.wit.com/dev/alexflint/arg"
|
||||||
|
@ -61,43 +58,19 @@ func main() {
|
||||||
me.chats.ConfigSave()
|
me.chats.ConfigSave()
|
||||||
}
|
}
|
||||||
|
|
||||||
aiClient, err := doConnect()
|
err := doConnect()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
_ = aiClient
|
|
||||||
|
|
||||||
if argv.JsonFile != "" {
|
if argv.JsonFile != "" {
|
||||||
// now try to Marshal() into a protobuf
|
doJSON()
|
||||||
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("")
|
okExit("")
|
||||||
}
|
}
|
||||||
|
|
||||||
if argv.Interact != nil {
|
if argv.Interact != nil {
|
||||||
log.Info("testing AI client with simpleHello()")
|
log.Info("testing AI client with simpleHello()")
|
||||||
err = simpleHello(aiClient)
|
err = simpleHello()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
badExit(err)
|
badExit(err)
|
||||||
}
|
}
|
||||||
|
|
11
structs.go
11
structs.go
|
@ -4,16 +4,21 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
"go.wit.com/dev/alexflint/arg"
|
"go.wit.com/dev/alexflint/arg"
|
||||||
"go.wit.com/gui"
|
"go.wit.com/gui"
|
||||||
"go.wit.com/lib/protobuf/chatpb"
|
"go.wit.com/lib/protobuf/chatpb"
|
||||||
|
"google.golang.org/genai"
|
||||||
)
|
)
|
||||||
|
|
||||||
var me *mainType
|
var me *mainType
|
||||||
|
|
||||||
// this app's variables
|
// this app's variables
|
||||||
type mainType struct {
|
type mainType struct {
|
||||||
pp *arg.Parser // for parsing the command line args. Yay to alexf lint!
|
pp *arg.Parser // for parsing the command line args. Yay to alexf lint!
|
||||||
chats *chatpb.Chats // all our prior conversations with regex
|
chats *chatpb.Chats // all our prior conversations with regex
|
||||||
myGui *gui.Node // the gui toolkit handle
|
myGui *gui.Node // the gui toolkit handle
|
||||||
|
client *genai.Client // the Google Gemini AI client variable
|
||||||
|
ctx context.Context
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue