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!") }