summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--convertToPB.go21
-rw-r--r--doConnect.go73
-rw-r--r--dumpchat.go2
-rw-r--r--handleFunctionCall.go51
4 files changed, 140 insertions, 7 deletions
diff --git a/convertToPB.go b/convertToPB.go
index e9399b6..13faad5 100644
--- a/convertToPB.go
+++ b/convertToPB.go
@@ -21,15 +21,24 @@ func convertToPB(resp *genai.GenerateContentResponse) *chatpb.ChatEntry {
PartType: &chatpb.Part_Text{Text: part.Text},
})
}
- if part.FunctionCall != nil {
- fmt.Printf("Gemini API requested to execute command: %s\n", part.FunctionCall.Name)
- // This is a simplified conversion of args.
- // A more robust implementation would handle different value types.
+ if fc := part.FunctionCall; fc != nil {
+ fmt.Printf("Gemini API requested to execute command: %s\n", fc.Name)
entry.Parts = append(entry.Parts, &chatpb.Part{
PartType: &chatpb.Part_FunctionCall{
FunctionCall: &chatpb.FunctionCall{
- Name: part.FunctionCall.Name,
- Args: &chatpb.ArgsInfo{}, // TODO: Properly map args if needed
+ Name: fc.Name,
+ Args: &chatpb.ArgsInfo{}, // TODO: Properly map args from fc.Args map[string]any
+ },
+ },
+ })
+ }
+ if fr := part.FunctionResponse; fr != nil {
+ // Convert the FunctionResponse to the protobuf equivalent
+ entry.Parts = append(entry.Parts, &chatpb.Part{
+ PartType: &chatpb.Part_FunctionResponse{
+ FunctionResponse: &chatpb.FunctionResponse{
+ Name: fr.Name,
+ // TODO: Properly map the response content
},
},
})
diff --git a/doConnect.go b/doConnect.go
index 1c29f04..4082aa6 100644
--- a/doConnect.go
+++ b/doConnect.go
@@ -5,6 +5,7 @@ import (
"fmt"
"os"
+ "go.wit.com/lib/protobuf/chatpb"
"go.wit.com/log"
"google.golang.org/genai"
)
@@ -23,6 +24,78 @@ func doConnect() error {
return log.Errorf("failed to create new genai client: %w", err)
}
+ if me.lastChat == nil {
+ log.Info("WTF. lastChat is nil")
+ return nil
+ }
+
+ // if me.lastChat.Entries == nil {
+ // me.lastChat.Entries = new(chatpb.ChatEntry)
+ // }
+
+ // In a real application, you would get user input here.
+ // For now, we'll use a hardcoded prompt.
+ if len(me.lastChat.GetEntries()) == 0 {
+ me.lastChat.Entries = append(me.lastChat.Entries, &chatpb.ChatEntry{
+ Parts: []*chatpb.Part{
+ {PartType: &chatpb.Part_Text{Text: "hello, how are you"}},
+ },
+ })
+ }
+
+ lastEntry := me.lastChat.GetEntries()[len(me.lastChat.GetEntries())-1]
+ genaiContents, err := convertToGenai(lastEntry.GetGeminiRequest())
+ if err != nil {
+ return err
+ }
+
+ resp, err := me.client.Models.GenerateContent(me.ctx, "gemini-2.5-flash", genaiContents, nil)
+ if err != nil {
+ return log.Errorf("error sending message: %v", err)
+ }
+
+ if resp == nil || len(resp.Candidates) == 0 || resp.Candidates[0].Content == nil {
+ log.Info("Received an empty response from the API. Stopping.")
+ return nil
+ }
+
+ // Append the model's response to the history
+ me.lastChat.Entries = append(me.lastChat.Entries, convertToPB(resp))
+
+ // Check for a function call
+ hasFunctionCall := false
+ for _, part := range resp.Candidates[0].Content.Parts {
+ if fc := part.FunctionCall; fc != nil {
+ hasFunctionCall = true
+ functionResponse := handleFunctionCall(fc)
+ // Append the function response to the history for the next turn
+ me.lastChat.Entries = append(me.lastChat.Entries, &chatpb.ChatEntry{
+ Parts: []*chatpb.Part{
+ {PartType: &chatpb.Part_FunctionResponse{
+ FunctionResponse: &chatpb.FunctionResponse{
+ Name: functionResponse.Name,
+ // TODO: map response
+ },
+ }},
+ },
+ })
+ }
+ }
+
+ // If there was no function call, print the text and stop.
+ if !hasFunctionCall {
+ log.Info("Response from API:")
+ for _, cand := range resp.Candidates {
+ if cand.Content != nil {
+ for _, part := range cand.Content.Parts {
+ if part.Text != "" {
+ fmt.Println(part.Text)
+ }
+ }
+ }
+ }
+ }
+
return nil
}
diff --git a/dumpchat.go b/dumpchat.go
index 2f479ae..3f57323 100644
--- a/dumpchat.go
+++ b/dumpchat.go
@@ -24,7 +24,7 @@ func dumpchat(chat *chatpb.Chat) error {
if lastEntry.GeminiRequest == nil {
return log.Errorf("lastEntry.GeminiRequest == nil")
}
- aichat, err := convertToGenai(lastEntry.GeminiRequest)
+ aichat, err := convertToGenai(lastEntry.GetGeminiRequest())
if err != nil {
log.Info("convertToGenai() returned with error", err)
return err
diff --git a/handleFunctionCall.go b/handleFunctionCall.go
new file mode 100644
index 0000000..a218238
--- /dev/null
+++ b/handleFunctionCall.go
@@ -0,0 +1,51 @@
+package main
+
+import (
+ "fmt"
+
+ "go.wit.com/log"
+ "google.golang.org/genai"
+)
+
+// handleFunctionCall executes a command requested by the Gemini API and returns the result.
+func handleFunctionCall(fc *genai.FunctionCall) *genai.FunctionResponse {
+ if fc == nil {
+ return nil
+ }
+
+ if fc.Name != "run_shell_command" {
+ log.Infof("Unsupported function call: %s", fc.Name)
+ return &genai.FunctionResponse{
+ Name: fc.Name,
+ Response: map[string]any{
+ "error": fmt.Sprintf("Unsupported function call: %s", fc.Name),
+ },
+ }
+ }
+
+ // Extract arguments
+ cmd, _ := fc.Args["command"].(string)
+ dir, _ := fc.Args["directory"].(string)
+
+ if cmd == "" {
+ return &genai.FunctionResponse{
+ Name: fc.Name,
+ Response: map[string]any{
+ "error": "missing command argument",
+ },
+ }
+ }
+
+ // Execute the command (this is a placeholder for the actual execution)
+ // In a real implementation, you would use the run_shell_command tool here.
+ log.Infof("Executing command: '%s' in directory: '%s'", cmd, dir)
+ // For now, we'll return a dummy response.
+ // TODO: Replace this with actual command execution.
+
+ return &genai.FunctionResponse{
+ Name: fc.Name,
+ Response: map[string]any{
+ "output": "command executed successfully (dummy response)",
+ },
+ }
+}