209 lines
5.4 KiB
Go

package main
import (
"bytes"
"encoding/json"
"fmt"
"io"
"net/http"
"os"
"path/filepath"
"sort"
"strings"
"time"
"github.com/chzyer/readline"
)
const (
apiURL = "https://router.ivastudio.verint.live/ProxyScript/run/67bca862210071627d32ef12/current/basic_messenger"
blue = "\033[34m"
green = "\033[32m"
reset = "\033[0m"
)
type Request struct {
Input string `json:"input"`
Model string `json:"model"`
PreviousResponseID string `json:"previous_response_id,omitempty"`
Metadata map[string]string `json:"metadata"`
}
type Response struct {
ID string `json:"id"`
Status string `json:"status"`
Output []struct {
Content []struct {
Text string `json:"text"`
} `json:"content"`
} `json:"output"`
}
type Messenger struct {
client *http.Client
model string
prevID string
}
func (m *Messenger) Send(input string) (string, error) {
data, _ := json.Marshal(Request{input, m.model, m.prevID, map[string]string{"channel": "text"}})
resp, err := m.client.Post(apiURL, "application/json", bytes.NewBuffer(data))
if err != nil {
return "", err
}
defer resp.Body.Close()
body, _ := io.ReadAll(resp.Body)
var r Response
json.Unmarshal(body, &r)
m.prevID = r.ID
if r.Status == "completed" && len(r.Output) > 0 && len(r.Output[0].Content) > 0 {
return r.Output[0].Content[0].Text, nil
}
return "", fmt.Errorf("invalid response")
}
func getConversations() []string {
files, _ := filepath.Glob("/tmp/messenger_*_log.txt")
type f struct {
id string
t time.Time
}
var list []f
for _, file := range files {
info, _ := os.Stat(file)
id := strings.TrimSuffix(strings.TrimPrefix(filepath.Base(file), "messenger_"), "_log.txt")
list = append(list, f{id, info.ModTime()})
}
sort.Slice(list, func(i, j int) bool { return list[i].t.After(list[j].t) })
var ids []string
for i, item := range list {
if i >= 5 {
break
}
ids = append(ids, item.id)
}
return ids
}
func readFile(path string) string {
data, _ := os.ReadFile(path)
return strings.TrimSpace(string(data))
}
func writeFile(path, content string) {
os.WriteFile(path, []byte(content), 0644)
}
func appendFile(path, content string) {
f, _ := os.OpenFile(path, os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
defer f.Close()
f.WriteString(content)
}
func showHistory(id string) {
lines := strings.Split(readFile(fmt.Sprintf("/tmp/messenger_%s_log.txt", id)), "\n")
start := len(lines) - 20
if start < 0 {
start = 0
}
fmt.Println("\n--- Previous Messages ---")
for _, line := range lines[start:] {
if strings.Contains(line, "You: ") {
fmt.Printf(blue+"You: %s"+reset+"\n", strings.SplitN(line, "You: ", 2)[1])
} else if strings.Contains(line, "Assistant: ") {
fmt.Printf(green+"Assistant: %s"+reset+"\n", strings.SplitN(line, "Assistant: ", 2)[1])
}
}
fmt.Println("-------------------------\n")
}
func main() {
var id, model string
fmt.Println("\n░▀█▀░█░█░█▀█░░░█▄█░█▀▀░█▀▀░█▀▀░█▀▀░█▀█░█▀▀░█▀▀░█▀▄\n░░█░░▀▄▀░█▀█░░░█░█░█▀▀░▀▀█░▀▀█░█▀▀░█░█░█░█░█▀▀░█▀▄\n░▀▀▀░░▀░░▀░▀░░░▀░▀░▀▀▀░▀▀▀░▀▀▀░▀▀▀░▀░▀░▀▀▀░▀▀▀░▀░▀")
// Check for recent conversations
convs := getConversations()
if len(convs) > 0 {
fmt.Println("Recent conversations:")
for i, cid := range convs {
m := readFile(fmt.Sprintf("/tmp/messenger_%s_meta.txt", cid))
fmt.Printf("%d. %s (model: %s)\n", i+1, cid, m)
}
fmt.Print("\nContinue? (enter number or 'n' for new): ")
var choice string
fmt.Scanln(&choice)
var num int
if _, err := fmt.Sscanf(choice, "%d", &num); err == nil && num >= 1 && num <= len(convs) {
id = convs[num-1]
model = readFile(fmt.Sprintf("/tmp/messenger_%s_meta.txt", id))
fmt.Printf("Continuing: %s (model: %s)\n", id, model)
showHistory(id)
}
}
if model == "" {
fmt.Print("Enter model name (default: 'default'): ")
fmt.Scanln(&model)
if model == "" {
model = "default"
}
}
m := &Messenger{&http.Client{Timeout: 10 * time.Second}, model, id}
fmt.Println("Use ↑/↓ for history, 'quit' to exit\n")
histFile := "/tmp/messenger_temp.tmp"
if id != "" {
histFile = fmt.Sprintf("/tmp/messenger_%s.tmp", id)
}
rl, _ := readline.NewEx(&readline.Config{Prompt: blue + "You: " + reset, HistoryFile: histFile})
defer rl.Close()
first := id == ""
for {
input, err := rl.Readline()
if err != nil || input == "quit" || input == "exit" {
break
}
if input = strings.TrimSpace(input); input == "" {
continue
}
response, err := m.Send(input)
if err != nil {
fmt.Println("Error:", err)
continue
}
if first && m.prevID != "" {
first = false
rl.Close()
rl, _ = readline.NewEx(&readline.Config{
Prompt: blue + "You: " + reset,
HistoryFile: fmt.Sprintf("/tmp/messenger_%s.tmp", m.prevID),
})
writeFile(fmt.Sprintf("/tmp/messenger_%s_meta.txt", m.prevID), m.model)
fmt.Printf("(ID: %s)\n\n", m.prevID)
}
if m.prevID != "" {
ts := time.Now().Format("2006-01-02 15:04:05")
logFile := fmt.Sprintf("/tmp/messenger_%s_log.txt", m.prevID)
appendFile(logFile, fmt.Sprintf("[%s] You: %s\n[%s] Assistant: %s\n", ts, input, ts, response))
}
fmt.Printf(green+"Assistant: %s"+reset+"\n\n", response)
}
fmt.Println("Goodbye!")
}