From f57d63831d604d726685fe31494788e81f17900a Mon Sep 17 00:00:00 2001 From: Paul Buetow Date: Sun, 7 Sep 2025 18:00:10 +0300 Subject: editor: remove prefilled text in temp files for custom prompts (TUI and CLI) --- docs/coverage.html | 642 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 405 insertions(+), 237 deletions(-) (limited to 'docs/coverage.html') diff --git a/docs/coverage.html b/docs/coverage.html index fb5d655..8560a58 100644 --- a/docs/coverage.html +++ b/docs/coverage.html @@ -61,67 +61,69 @@ - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + - + + + @@ -306,19 +308,21 @@ type App struct { // Code actions PromptCodeActionRewriteSystem string `json:"-" toml:"-"` PromptCodeActionDiagnosticsSystem string `json:"-" toml:"-"` - PromptCodeActionDocumentSystem string `json:"-" toml:"-"` - PromptCodeActionRewriteUser string `json:"-" toml:"-"` - PromptCodeActionDiagnosticsUser string `json:"-" toml:"-"` - PromptCodeActionDocumentUser string `json:"-" toml:"-"` - PromptCodeActionGoTestSystem string `json:"-" toml:"-"` - PromptCodeActionGoTestUser string `json:"-" toml:"-"` + PromptCodeActionDocumentSystem string `json:"-" toml:"-"` + PromptCodeActionRewriteUser string `json:"-" toml:"-"` + PromptCodeActionDiagnosticsUser string `json:"-" toml:"-"` + PromptCodeActionDocumentUser string `json:"-" toml:"-"` + PromptCodeActionGoTestSystem string `json:"-" toml:"-"` + PromptCodeActionGoTestUser string `json:"-" toml:"-"` + PromptCodeActionSimplifySystem string `json:"-" toml:"-"` + PromptCodeActionSimplifyUser string `json:"-" toml:"-"` // CLI PromptCLIDefaultSystem string `json:"-" toml:"-"` PromptCLIExplainSystem string `json:"-" toml:"-"` } // Constructor: defaults for App (kept first among functions) -func newDefaultConfig() App { +func newDefaultConfig() App { // Coding-friendly default temperature across providers // Users can override per provider in config.toml (including 0.0). t := 0.2 @@ -359,8 +363,10 @@ func newDefaultConfig() App { PromptCodeActionRewriteUser: "Instruction: {{instruction}}\n\nSelected code to transform:\n{{selection}}", PromptCodeActionDiagnosticsUser: "Diagnostics to resolve (selection only):\n{{diagnostics}}\n\nSelected code:\n{{selection}}", PromptCodeActionDocumentUser: "Add documentation comments to this code:\n{{selection}}", - PromptCodeActionGoTestSystem: "You are a precise Go unit test generator. Given a Go function, write one or more Test* functions using the testing package. Do NOT include package or imports, only the test function(s). Prefer table-driven tests. Keep it minimal and idiomatic.", - PromptCodeActionGoTestUser: "Function under test:\n{{function}}", + PromptCodeActionGoTestSystem: "You are a precise Go unit test generator. Given a Go function, write one or more Test* functions using the testing package. Do NOT include package or imports, only the test function(s). Prefer table-driven tests. Keep it minimal and idiomatic.", + PromptCodeActionGoTestUser: "Function under test:\n{{function}}", + PromptCodeActionSimplifySystem: "You are a precise code improvement engine. Simplify and improve the given code while preserving behavior. Return only the improved code with no prose or backticks.", + PromptCodeActionSimplifyUser: "Improve this code:\n{{selection}}", PromptCLIDefaultSystem: "You are Hexai CLI. Default to very short, concise answers. If the user asks for commands, output only the commands (one per line) with no commentary or explanation. Only when the word 'explain' appears in the prompt, produce a verbose explanation.", PromptCLIExplainSystem: "You are Hexai CLI. The user requested an explanation. Provide a clear, verbose explanation with reasoning and details. If commands are needed, include them with brief context.", @@ -369,17 +375,17 @@ func newDefaultConfig() App { // Load reads configuration from a file and merges with defaults. // It respects the XDG Base Directory Specification. -func Load(logger *log.Logger) App { +func Load(logger *log.Logger) App { cfg := newDefaultConfig() if logger == nil { return cfg // Return defaults if no logger is provided (e.g. in tests) } - configPath, err := getConfigPath() + configPath, err := getConfigPath() if err != nil { logger.Printf("%v", err) // Even if config path cannot be resolved, still allow env overrides below. - } else { + } else { if fileCfg, err := loadFromFile(configPath, logger); err == nil && fileCfg != nil { cfg.mergeWith(fileCfg) } @@ -388,10 +394,10 @@ func Load(logger *log.Logger) App { } // Environment overrides (take precedence over file) - if envCfg := loadFromEnv(logger); envCfg != nil { + if envCfg := loadFromEnv(logger); envCfg != nil { cfg.mergeWith(envCfg) } - return cfg + return cfg } // Private helpers @@ -488,14 +494,16 @@ type sectionPromptsChat struct { } type sectionPromptsCodeAction struct { - RewriteSystem string `toml:"rewrite_system"` - DiagnosticsSystem string `toml:"diagnostics_system"` - DocumentSystem string `toml:"document_system"` - RewriteUser string `toml:"rewrite_user"` - DiagnosticsUser string `toml:"diagnostics_user"` - DocumentUser string `toml:"document_user"` - GoTestSystem string `toml:"go_test_system"` - GoTestUser string `toml:"go_test_user"` + RewriteSystem string `toml:"rewrite_system"` + DiagnosticsSystem string `toml:"diagnostics_system"` + DocumentSystem string `toml:"document_system"` + RewriteUser string `toml:"rewrite_user"` + DiagnosticsUser string `toml:"diagnostics_user"` + DocumentUser string `toml:"document_user"` + GoTestSystem string `toml:"go_test_system"` + GoTestUser string `toml:"go_test_user"` + SimplifySystem string `toml:"simplify_system"` + SimplifyUser string `toml:"simplify_user"` } type sectionPromptsCLI struct { @@ -619,7 +627,7 @@ func (fc *fileConfig) toApp() App { out.PromptChatSystem = fc.Prompts.Chat.System } // code action - if (fc.Prompts.CodeAction != sectionPromptsCodeAction{}) { + if (fc.Prompts.CodeAction != sectionPromptsCodeAction{}) { if strings.TrimSpace(fc.Prompts.CodeAction.RewriteSystem) != "" { out.PromptCodeActionRewriteSystem = fc.Prompts.CodeAction.RewriteSystem } @@ -641,10 +649,16 @@ func (fc *fileConfig) toApp() App { if strings.TrimSpace(fc.Prompts.CodeAction.GoTestSystem) != "" { out.PromptCodeActionGoTestSystem = fc.Prompts.CodeAction.GoTestSystem } - if strings.TrimSpace(fc.Prompts.CodeAction.GoTestUser) != "" { - out.PromptCodeActionGoTestUser = fc.Prompts.CodeAction.GoTestUser - } - } + if strings.TrimSpace(fc.Prompts.CodeAction.GoTestUser) != "" { + out.PromptCodeActionGoTestUser = fc.Prompts.CodeAction.GoTestUser + } + if strings.TrimSpace(fc.Prompts.CodeAction.SimplifySystem) != "" { + out.PromptCodeActionSimplifySystem = fc.Prompts.CodeAction.SimplifySystem + } + if strings.TrimSpace(fc.Prompts.CodeAction.SimplifyUser) != "" { + out.PromptCodeActionSimplifyUser = fc.Prompts.CodeAction.SimplifyUser + } + } // cli if (fc.Prompts.CLI != sectionPromptsCLI{}) { if strings.TrimSpace(fc.Prompts.CLI.DefaultSystem) != "" { @@ -662,13 +676,13 @@ func (fc *fileConfig) toApp() App { return out } -func loadFromFile(path string, logger *log.Logger) (*App, error) { +func loadFromFile(path string, logger *log.Logger) (*App, error) { b, err := os.ReadFile(path) - if err != nil { + if err != nil { if !os.IsNotExist(err) && logger != nil { logger.Printf("cannot open TOML config file %s: %v", path, err) } - return nil, err + return nil, err } var tables fileConfig @@ -843,9 +857,15 @@ func (a *App) mergePrompts(other *App) { if strings.TrimSpace(other.PromptCodeActionGoTestSystem) != "" { a.PromptCodeActionGoTestSystem = other.PromptCodeActionGoTestSystem } - if strings.TrimSpace(other.PromptCodeActionGoTestUser) != "" { - a.PromptCodeActionGoTestUser = other.PromptCodeActionGoTestUser - } + if strings.TrimSpace(other.PromptCodeActionGoTestUser) != "" { + a.PromptCodeActionGoTestUser = other.PromptCodeActionGoTestUser + } + if strings.TrimSpace(other.PromptCodeActionSimplifySystem) != "" { + a.PromptCodeActionSimplifySystem = other.PromptCodeActionSimplifySystem + } + if strings.TrimSpace(other.PromptCodeActionSimplifyUser) != "" { + a.PromptCodeActionSimplifyUser = other.PromptCodeActionSimplifyUser + } // CLI if strings.TrimSpace(other.PromptCLIDefaultSystem) != "" { a.PromptCLIDefaultSystem = other.PromptCLIDefaultSystem @@ -886,33 +906,33 @@ func (a *App) mergeProviderFields(other *App) { } } -func getConfigPath() (string, error) { +func getConfigPath() (string, error) { var configPath string if xdgConfigHome := os.Getenv("XDG_CONFIG_HOME"); xdgConfigHome != "" { configPath = filepath.Join(xdgConfigHome, "hexai", "config.toml") - } else { + } else { home, err := os.UserHomeDir() if err != nil { return "", fmt.Errorf("cannot find user home directory: %v", err) } - configPath = filepath.Join(home, ".config", "hexai", "config.toml") + configPath = filepath.Join(home, ".config", "hexai", "config.toml") } - return configPath, nil + return configPath, nil } // --- Environment overrides --- // loadFromEnv constructs an App containing only fields set via HEXAI_* env vars. // These values should take precedence over file config when merged. -func loadFromEnv(logger *log.Logger) *App { +func loadFromEnv(logger *log.Logger) *App { var out App var any bool // helpers - getenv := func(k string) string { return strings.TrimSpace(os.Getenv(k)) } - parseInt := func(k string) (int, bool) { + getenv := func(k string) string { return strings.TrimSpace(os.Getenv(k)) } + parseInt := func(k string) (int, bool) { v := getenv(k) - if v == "" { + if v == "" { return 0, false } n, err := strconv.Atoi(v) @@ -924,9 +944,9 @@ func loadFromEnv(logger *log.Logger) *App { } return n, true } - parseFloatPtr := func(k string) (*float64, bool) { + parseFloatPtr := func(k string) (*float64, bool) { v := getenv(k) - if v == "" { + if v == "" { return nil, false } f, err := strconv.ParseFloat(v, 64) @@ -939,43 +959,43 @@ func loadFromEnv(logger *log.Logger) *App { return &f, true } - if n, ok := parseInt("HEXAI_MAX_TOKENS"); ok { + if n, ok := parseInt("HEXAI_MAX_TOKENS"); ok { out.MaxTokens = n any = true } - if s := getenv("HEXAI_CONTEXT_MODE"); s != "" { + if s := getenv("HEXAI_CONTEXT_MODE"); s != "" { out.ContextMode = s any = true } - if n, ok := parseInt("HEXAI_CONTEXT_WINDOW_LINES"); ok { + if n, ok := parseInt("HEXAI_CONTEXT_WINDOW_LINES"); ok { out.ContextWindowLines = n any = true } - if n, ok := parseInt("HEXAI_MAX_CONTEXT_TOKENS"); ok { + if n, ok := parseInt("HEXAI_MAX_CONTEXT_TOKENS"); ok { out.MaxContextTokens = n any = true } - if n, ok := parseInt("HEXAI_LOG_PREVIEW_LIMIT"); ok { + if n, ok := parseInt("HEXAI_LOG_PREVIEW_LIMIT"); ok { out.LogPreviewLimit = n any = true } - if n, ok := parseInt("HEXAI_MANUAL_INVOKE_MIN_PREFIX"); ok { + if n, ok := parseInt("HEXAI_MANUAL_INVOKE_MIN_PREFIX"); ok { out.ManualInvokeMinPrefix = n any = true } - if n, ok := parseInt("HEXAI_COMPLETION_DEBOUNCE_MS"); ok { + if n, ok := parseInt("HEXAI_COMPLETION_DEBOUNCE_MS"); ok { out.CompletionDebounceMs = n any = true } - if n, ok := parseInt("HEXAI_COMPLETION_THROTTLE_MS"); ok { + if n, ok := parseInt("HEXAI_COMPLETION_THROTTLE_MS"); ok { out.CompletionThrottleMs = n any = true } - if f, ok := parseFloatPtr("HEXAI_CODING_TEMPERATURE"); ok { + if f, ok := parseFloatPtr("HEXAI_CODING_TEMPERATURE"); ok { out.CodingTemperature = f any = true } - if s := getenv("HEXAI_TRIGGER_CHARACTERS"); s != "" { + if s := getenv("HEXAI_TRIGGER_CHARACTERS"); s != "" { parts := strings.Split(s, ",") out.TriggerCharacters = nil for _, p := range parts { @@ -985,19 +1005,19 @@ func loadFromEnv(logger *log.Logger) *App { } any = true } - if s := getenv("HEXAI_INLINE_OPEN"); s != "" { + if s := getenv("HEXAI_INLINE_OPEN"); s != "" { out.InlineOpen = s any = true } - if s := getenv("HEXAI_INLINE_CLOSE"); s != "" { + if s := getenv("HEXAI_INLINE_CLOSE"); s != "" { out.InlineClose = s any = true } - if s := getenv("HEXAI_CHAT_SUFFIX"); s != "" { + if s := getenv("HEXAI_CHAT_SUFFIX"); s != "" { out.ChatSuffix = s any = true } - if s := getenv("HEXAI_CHAT_PREFIXES"); s != "" { + if s := getenv("HEXAI_CHAT_PREFIXES"); s != "" { parts := strings.Split(s, ",") out.ChatPrefixes = nil for _, p := range parts { @@ -1007,59 +1027,131 @@ func loadFromEnv(logger *log.Logger) *App { } any = true } - if s := getenv("HEXAI_PROVIDER"); s != "" { + if s := getenv("HEXAI_PROVIDER"); s != "" { out.Provider = s any = true } // Provider-specific - if s := getenv("HEXAI_OPENAI_BASE_URL"); s != "" { + if s := getenv("HEXAI_OPENAI_BASE_URL"); s != "" { out.OpenAIBaseURL = s any = true } - if s := getenv("HEXAI_OPENAI_MODEL"); s != "" { + if s := getenv("HEXAI_OPENAI_MODEL"); s != "" { out.OpenAIModel = s any = true } - if f, ok := parseFloatPtr("HEXAI_OPENAI_TEMPERATURE"); ok { + if f, ok := parseFloatPtr("HEXAI_OPENAI_TEMPERATURE"); ok { out.OpenAITemperature = f any = true } - if s := getenv("HEXAI_OLLAMA_BASE_URL"); s != "" { + if s := getenv("HEXAI_OLLAMA_BASE_URL"); s != "" { out.OllamaBaseURL = s any = true } - if s := getenv("HEXAI_OLLAMA_MODEL"); s != "" { + if s := getenv("HEXAI_OLLAMA_MODEL"); s != "" { out.OllamaModel = s any = true } - if f, ok := parseFloatPtr("HEXAI_OLLAMA_TEMPERATURE"); ok { + if f, ok := parseFloatPtr("HEXAI_OLLAMA_TEMPERATURE"); ok { out.OllamaTemperature = f any = true } - if s := getenv("HEXAI_COPILOT_BASE_URL"); s != "" { + if s := getenv("HEXAI_COPILOT_BASE_URL"); s != "" { out.CopilotBaseURL = s any = true } - if s := getenv("HEXAI_COPILOT_MODEL"); s != "" { + if s := getenv("HEXAI_COPILOT_MODEL"); s != "" { out.CopilotModel = s any = true } - if f, ok := parseFloatPtr("HEXAI_COPILOT_TEMPERATURE"); ok { + if f, ok := parseFloatPtr("HEXAI_COPILOT_TEMPERATURE"); ok { out.CopilotTemperature = f any = true } - if !any { + if !any { return nil } return &out } -