stash
This commit is contained in:
112
main.go
Normal file
112
main.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const systemPrompt = `You are a coding assistant running inside a CLI. You have file tools scoped
|
||||
to the current project directory. All paths are relative to the project root; absolute paths
|
||||
and paths that escape the root (via "..") will be rejected. Prefer listing and reading before
|
||||
editing. Keep replies concise.`
|
||||
|
||||
func main() {
|
||||
root, err := os.Getwd()
|
||||
if err != nil {
|
||||
fmt.Fprintln(os.Stderr, "error getting working directory:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
if err := loadConfig(root); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "config error:", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
apiKey := os.Getenv("OPENAI_API_KEY")
|
||||
baseURL := getEnvDefault("OPENAI_BASE_URL", "https://api.openai.com/v1")
|
||||
model := getEnvDefault("OPENAI_MODEL", "gpt-4o-mini")
|
||||
|
||||
if apiKey == "" {
|
||||
fmt.Fprintln(os.Stderr, "OPENAI_API_KEY is not set")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
client := NewClient(baseURL, apiKey, model)
|
||||
tools := toolDefinitions()
|
||||
|
||||
messages := []Message{{Role: "system", Content: systemPrompt}}
|
||||
|
||||
fmt.Printf("NyxTex agent — model=%s root=%s\n", model, root)
|
||||
fmt.Println("Type your request. Empty line to submit. Ctrl+D or /exit to quit.")
|
||||
|
||||
reader := bufio.NewReader(os.Stdin)
|
||||
for {
|
||||
fmt.Print("\n> ")
|
||||
input, err := readUserInput(reader)
|
||||
if err != nil {
|
||||
fmt.Println()
|
||||
return
|
||||
}
|
||||
input = strings.TrimSpace(input)
|
||||
if input == "" {
|
||||
continue
|
||||
}
|
||||
if input == "/exit" || input == "/quit" {
|
||||
return
|
||||
}
|
||||
|
||||
messages = append(messages, Message{Role: "user", Content: input})
|
||||
|
||||
if err := runTurn(context.Background(), client, tools, root, &messages); err != nil {
|
||||
fmt.Fprintln(os.Stderr, "error:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func readUserInput(r *bufio.Reader) (string, error) {
|
||||
line, err := r.ReadString('\n')
|
||||
if err != nil && line == "" {
|
||||
return "", err
|
||||
}
|
||||
return line, nil
|
||||
}
|
||||
|
||||
// runTurn sends the conversation and handles any tool-call loop until the
|
||||
// assistant produces a plain text reply.
|
||||
func runTurn(ctx context.Context, client *Client, tools []Tool, root string, messages *[]Message) error {
|
||||
for {
|
||||
msg, err := client.Chat(ctx, *messages, tools)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
*messages = append(*messages, msg)
|
||||
|
||||
if len(msg.ToolCalls) == 0 {
|
||||
if strings.TrimSpace(msg.Content) != "" {
|
||||
fmt.Println(msg.Content)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, tc := range msg.ToolCalls {
|
||||
fmt.Printf(" [tool] %s %s\n", tc.Function.Name, tc.Function.Arguments)
|
||||
result := runTool(root, tc.Function.Name, tc.Function.Arguments)
|
||||
*messages = append(*messages, Message{
|
||||
Role: "tool",
|
||||
ToolCallID: tc.ID,
|
||||
Name: tc.Function.Name,
|
||||
Content: result,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func getEnvDefault(key, def string) string {
|
||||
if v := os.Getenv(key); v != "" {
|
||||
return v
|
||||
}
|
||||
return def
|
||||
}
|
||||
Reference in New Issue
Block a user