Peter.Morton fc9b17bcec Adding terminal messenger
This is a golang based application that connects to the basic messenger
2025-11-01 22:46:34 -05:00

197 lines
4.2 KiB
Go

package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"strings"
"time"
"github.com/chzyer/readline"
)
const (
apiURL = "https://router.ivastudio.verint.live/ProxyScript/run/67bca862210071627d32ef12/current/basic_messenger"
colorReset = "\033[0m"
colorBlue = "\033[34m"
colorGreen = "\033[32m"
)
type Metadata struct {
Channel string `json:"channel"`
}
type Message struct {
Input string `json:"input"`
Model string `json:"model"`
PreviousResponseID string `json:"previous_response_id,omitempty"`
Metadata Metadata `json:"metadata"`
}
type ContentItem struct {
Type string `json:"type"`
Text string `json:"text"`
Annotations []string `json:"annotations"`
}
type OutputMessage struct {
Type string `json:"type"`
ID string `json:"id"`
Role string `json:"role"`
Content []ContentItem `json:"content"`
}
type Response struct {
ID string `json:"id"`
Object string `json:"object"`
CreatedAt int64 `json:"created_at"`
Status string `json:"status"`
Model string `json:"model"`
Output []OutputMessage `json:"output"`
}
type Messenger struct {
client *http.Client
model string
previousResponseID string
}
func NewMessenger(model string) *Messenger {
return &Messenger{
client: &http.Client{
Timeout: 10 * time.Second,
},
model: model,
}
}
func (m *Messenger) sendRequest(input string) (*Response, error) {
msg := Message{
Input: input,
Model: m.model,
PreviousResponseID: m.previousResponseID,
Metadata: Metadata{
Channel: "text",
},
}
jsonData, err := json.Marshal(msg)
if err != nil {
return nil, fmt.Errorf("failed to marshal JSON: %w", err)
}
req, err := http.NewRequest("POST", apiURL, bytes.NewBuffer(jsonData))
if err != nil {
return nil, fmt.Errorf("failed to create request: %w", err)
}
req.Header.Set("Content-Type", "application/json")
resp, err := m.client.Do(req)
if err != nil {
return nil, fmt.Errorf("failed to send request: %w", err)
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)
if err != nil {
return nil, fmt.Errorf("failed to read response: %w", err)
}
var response Response
if err := json.Unmarshal(body, &response); err != nil {
return nil, fmt.Errorf("failed to unmarshal response: %w", err)
}
// Update previous response ID for conversation continuity
if response.ID != "" {
m.previousResponseID = response.ID
}
return &response, nil
}
func (m *Messenger) SendMessage(text string) (string, error) {
resp, err := m.sendRequest(text)
if err != nil {
return "", err
}
if resp.Status != "completed" {
return "", fmt.Errorf("response status: %s", resp.Status)
}
// Extract text from the response output
if len(resp.Output) > 0 && len(resp.Output[0].Content) > 0 {
return resp.Output[0].Content[0].Text, nil
}
return "", fmt.Errorf("no output received")
}
func printHeader() {
fmt.Println("=== Terminal Messenger ===")
fmt.Println("Type your message (or 'quit' to exit)")
fmt.Println("Use ↑/↓ arrows to navigate history")
fmt.Println("==========================")
fmt.Println()
}
func main() {
// Get model
fmt.Print("Enter model name (default: 'default'): ")
var model string
fmt.Scanln(&model)
if model == "" {
model = "default"
}
messenger := NewMessenger(model)
printHeader()
// Setup readline for input history and line editing
rl, err := readline.NewEx(&readline.Config{
Prompt: colorBlue + "You: " + colorReset,
HistoryFile: "/tmp/messenger_history.tmp",
InterruptPrompt: "^C",
EOFPrompt: "exit",
})
if err != nil {
fmt.Printf("Error setting up readline: %v\n", err)
return
}
defer rl.Close()
// Main message loop
for {
input, err := rl.Readline()
if err != nil { // io.EOF or readline.ErrInterrupt
break
}
input = strings.TrimSpace(input)
if input == "quit" || input == "exit" {
break
}
if input == "" {
continue
}
response, err := messenger.SendMessage(input)
if err != nil {
fmt.Printf("Error: %v\n", err)
continue
}
fmt.Printf(colorGreen+"Assistant: %s"+colorReset+"\n\n", response)
}
fmt.Println("\nGoodbye!")
}