Skip to content

Commit c731c76

Browse files
feat: Enhance interactive commands and disable color output
This commit introduces several improvements to the interactive mode of the chat application and removes terminal color output. The following changes have been made: - **Disable Color Output:** The `tput` function has been modified to return an empty string, effectively removing all ANSI color and style sequences from the terminal output. - **New `/list` Command:** An interactive command `/list` has been added to display the list of supported models. - **Improved `/modelinfo` Command:** The `/modelinfo` command now defaults to showing information for the currently active model if no model name is specified. - **New `/askfor_model_setting` Command:** A new command, `/askfor_model_setting`, has been implemented to allow users to interactively configure the settings for the current model one by one. - **Refined `/help` Command:** The `/help` command in interactive mode now displays a concise list of only the interactive commands, making it more user-friendly. The full help message is still available via the `--help` flag.
1 parent bce1ddf commit c731c76

File tree

1 file changed

+91
-15
lines changed

1 file changed

+91
-15
lines changed

main.go

Lines changed: 91 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import (
1111
"math/rand"
1212
"net/http"
1313
"os"
14-
"os/exec"
1514
"path/filepath"
1615
"regexp"
1716
"sort"
@@ -81,11 +80,7 @@ type ConversationFile struct {
8180
}
8281

8382
func tput(name string) string {
84-
out, err := exec.Command("tput", name).Output()
85-
if err != nil {
86-
return ""
87-
}
88-
return string(out)
83+
return ""
8984
}
9085

9186
var (
@@ -96,6 +91,29 @@ var (
9691
red = tput("setaf 1")
9792
)
9893

94+
func printInteractiveHelp() {
95+
var builder strings.Builder
96+
builder.WriteString(fmt.Sprintf("%sInteractive Commands:%s\n", bold, normal))
97+
builder.WriteString(" /help Show this help message.\n")
98+
builder.WriteString(" /exit, /quit Exit the program.\n")
99+
builder.WriteString(" /history Print full conversation JSON.\n")
100+
builder.WriteString(" /clear Clear conversation messages.\n")
101+
builder.WriteString(" /save <file> Save conversation to a new file.\n")
102+
builder.WriteString(" /list List supported models.\n")
103+
builder.WriteString(" /model <model_name> Switch model for the session.\n")
104+
builder.WriteString(" /modelinfo [name] List settings for a model (defaults to current).\n")
105+
builder.WriteString(" /askfor_model_setting Interactively set model parameters.\n")
106+
builder.WriteString(" /persist-settings Save the current session's settings to the conversation file.\n")
107+
builder.WriteString(" /persist-system <file>\n Persist a system prompt from a file.\n")
108+
builder.WriteString(" /exportlast [-t] <file>\n Export last AI response to a markdown file (-t filters thinking).\n")
109+
builder.WriteString(" /exportlastn [-t] <n> <file>\n Export last n AI responses.\n")
110+
builder.WriteString(" /exportn [-t] <n> <file>\n Export the Nth-to-last AI response.\n")
111+
builder.WriteString(" /randomodel Switch to a random supported model.\n\n")
112+
builder.WriteString("For any model setting, you can use `/setting_name <value>` or `/setting_name unset`.\n")
113+
builder.WriteString("For example: `/temperature 0.8`, `/stop unset`\n\n")
114+
fmt.Print(builder.String())
115+
}
116+
99117
func printHelp(cfg map[string]string) {
100118
var builder strings.Builder
101119

@@ -1269,7 +1287,7 @@ func main() {
12691287
}
12701288

12711289
// Interactive banner
1272-
fmt.Fprintln(os.Stderr)
1290+
fmt.Fprint(os.Stderr, "\n")
12731291
fmt.Fprintln(os.Stderr, `AI models generate responses and outputs based on complex algorithms and
12741292
machine learning techniques, and those responses or outputs may be
12751293
inaccurate, harmful, biased or indecent. By testing this model, you assume
@@ -1665,7 +1683,7 @@ func handleInteractiveInput(userInput, convFile string, cfg map[string]string) b
16651683
// --- Static commands ---
16661684
switch commandName {
16671685
case "exit", "quit":
1668-
fmt.Fprintln(os.Stderr, "Bye.")
1686+
fmt.Fprint(os.Stderr, "Bye.\n")
16691687
os.Exit(0)
16701688
return true
16711689
case "history":
@@ -1760,8 +1778,14 @@ func handleInteractiveInput(userInput, convFile string, cfg map[string]string) b
17601778
cfg["MODEL"] = newModel
17611779
fmt.Fprintf(os.Stderr, "%sSwitched model to %s%s\n", green, newModel, normal)
17621780
return true
1781+
case "list":
1782+
fmt.Fprintf(os.Stderr, "%sSupported models:%s\n", bold, normal)
1783+
for _, m := range modelsList {
1784+
fmt.Fprintf(os.Stderr, " %s\n", m)
1785+
}
1786+
return true
17631787
case "help":
1764-
printHelp(cfg)
1788+
printInteractiveHelp()
17651789
return true
17661790
case "model":
17671791
if len(parts) < 2 {
@@ -1787,19 +1811,71 @@ func handleInteractiveInput(userInput, convFile string, cfg map[string]string) b
17871811
fmt.Fprintf(os.Stderr, "%sModel set to %s%s\n", green, modelName, normal)
17881812
return true
17891813
case "modelinfo":
1814+
var modelName string
17901815
if len(parts) < 2 {
1791-
fmt.Fprintln(os.Stderr, "Usage: /modelinfo <model_name>")
1792-
return true
1816+
modelName = cfg["MODEL"]
1817+
} else {
1818+
modelName = parts[1]
17931819
}
1794-
modelName := parts[1]
1795-
modelDef, exists := ModelDefinitions[modelName]
1796-
if !exists {
1797-
fmt.Fprintf(os.Stderr, "%sError: Model '%s' not found.%s\n", red, modelName, normal)
1820+
1821+
// Validate that the model is known before proceeding
1822+
found := false
1823+
for _, m := range modelsList {
1824+
if m == modelName {
1825+
found = true
1826+
break
1827+
}
1828+
}
1829+
if !found {
1830+
fmt.Fprintf(os.Stderr, "%sError: Model '%s' not found in the list of supported models.%s\n", red, modelName, normal)
17981831
return true
17991832
}
1833+
1834+
modelDef := GetModelDefinition(modelName) // This will fall back to 'others' if no specific def
18001835
info := getModelInfoString(modelName, modelDef)
18011836
fmt.Fprint(os.Stderr, info)
18021837
return true
1838+
1839+
case "askfor_model_setting":
1840+
modelDef := GetModelDefinition(cfg["MODEL"])
1841+
paramNames := make([]string, 0, len(modelDef.Parameters))
1842+
for name := range modelDef.Parameters {
1843+
paramNames = append(paramNames, name)
1844+
}
1845+
sort.Strings(paramNames)
1846+
1847+
allConfigurableParams := append(paramNames, "stream", "history_limit")
1848+
1849+
fmt.Fprintln(os.Stderr, "Interactively configure settings. Press Enter to keep the current value.")
1850+
1851+
for _, paramName := range allConfigurableParams {
1852+
configKey := strings.ToUpper(paramName)
1853+
currentValue, _ := cfg[configKey]
1854+
1855+
fmt.Fprintf(os.Stderr, "\nParameter: %s [current: %s]\nEnter new value: ", paramName, currentValue)
1856+
1857+
newValue, err := readSingleLine(nil, []string{"\n"}, true)
1858+
if err != nil && err != io.EOF {
1859+
fmt.Fprintf(os.Stderr, "%sError reading input: %v%s\n", red, err, normal)
1860+
break
1861+
}
1862+
1863+
newValue = strings.TrimSpace(newValue)
1864+
if newValue == "" {
1865+
fmt.Fprintln(os.Stderr, " (value unchanged)")
1866+
continue
1867+
}
1868+
1869+
if err := validateParameter(paramName, newValue, modelDef); err != nil {
1870+
fmt.Fprintf(os.Stderr, "%s Error: %v%s\n", red, err, normal)
1871+
continue
1872+
}
1873+
1874+
cfg[configKey] = newValue
1875+
fmt.Fprintf(os.Stderr, " %sSet to %s%s\n", green, newValue, normal)
1876+
}
1877+
fmt.Fprintf(os.Stderr, "\n%sFinished updating settings.%s\n", green, normal)
1878+
return true
18031879
}
18041880

18051881
// --- Dynamic parameter setting commands ---

0 commit comments

Comments
 (0)