Skip to content

Conversation

@rm-hull
Copy link
Owner

@rm-hull rm-hull commented Nov 16, 2025

This commit introduces an interactive TUI setup wizard using
the github.com/charmbracelet/huh library.

The application now validates the loaded configuration upon
startup. If validation fails (e.g., missing API keys), the
wizard guides the user through setting the required LLM
provider, API keys, and models for either Gemini or OpenAI.

Additional changes:

  • Added configuration validation via
    github.com/go-playground/validator/v10.
  • Implemented Validate() and Save() methods on the
    Config struct.

Fixes #19

This commit introduces an interactive TUI setup wizard using
the **github.com/charmbracelet/huh** library.

The application now validates the loaded configuration upon
startup. If validation fails (e.g., missing API keys), the
wizard guides the user through setting the required LLM
provider, API keys, and models for either Gemini or OpenAI.

Additional changes:
*   Added configuration validation via
    **github.com/go-playground/validator/v10**.
*   Implemented `Validate()` and `Save()` methods on the
    `Config` struct.
…t/setup-wizard

* 'main' of github.com:rm-hull/git-commit-summary:
  chore: Update indirect Go dependencies
@github-actions
Copy link

github-actions bot commented Nov 16, 2025

TestsPassed ✅SkippedFailed
JUnit Test Report42 ran42 passed0 skipped0 failed
TestResult
JUnit Test Report
com/rm-hull/git-commit-summary/internal/config.TestLoad/Defaults✅ passed
com/rm-hull/git-commit-summary/internal/config.TestLoad/WithEnvironmentVariables✅ passed
com/rm-hull/git-commit-summary/internal/config.TestLoad✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/empty_file,_add_new_properties✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/existing_file,_update_properties✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/doesnt_overwrite_values_if_new_value_is_the_same✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/existing_file,_add_new_and_update_existing✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/preserve_comments_and_other_lines✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/handle_mixed_quoting_styles✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/empty_props,_no_changes✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties/properties_with_special_characters✅ passed
com/rm-hull/git-commit-summary/internal/config.Test_updateProperties✅ passed
com/rm-hull/git-commit-summary/internal/llm_provider.TestNewProvider/GoogleProvider✅ passed
com/rm-hull/git-commit-summary/internal/llm_provider.TestNewProvider/OpenAIProvider✅ passed
com/rm-hull/git-commit-summary/internal/llm_provider.TestNewProvider/UnknownProvider✅ passed
com/rm-hull/git-commit-summary/internal/llm_provider.TestNewProvider✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/NewHistory✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Add_and_Value✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Undo✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Redo✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Undo_at_beginning✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Redo_at_end✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Add_truncates_future_history✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory/Multiple_Undos_and_Redos✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestHistory✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/tea.KeyMsg_-_CtrlC_in_showSpinner_state✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/tea.KeyMsg_-_CtrlC_in_other_states✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/gitCheckMsg_-_empty_(no_staged_changes)✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/gitCheckMsg_-_non-empty_(staged_changes)✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/gitDiffMsg✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/llmResultMsg_-_with_user_message✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/llmResultMsg_-_without_user_message✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/commitMsg✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/regenerateMsg✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/userResponseMsg✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/cancelRegenPromptMsg✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/errMsg✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/abortMsg✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/spinner.Update_for_showSpinner_state✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/commitView.Update_for_showCommitView_state✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update/promptView.Update_for_showRegeneratePrompt_state✅ passed
com/rm-hull/git-commit-summary/internal/ui.TestModel_Update✅ passed

gemini-code-assist[bot]

This comment was marked as outdated.

rm-hull and others added 4 commits November 16, 2025 21:23
Unifies configuration settings by removing provider-specific
nested structs (`GeminiConfig`, `OpenAIConfig`) in favor of
generic fields (`APIKey`, `Model`, `BaseURL`) on the main
`Config` struct.

This change facilitates the introduction of the `llama.cpp`
provider, which reuses the existing OpenAI client infrastructure
but uses dedicated environment variables for configuration.

Refactors include:
*   Introduction of `updateProperties` helper for saving config
    while preserving comments and unrelated entries in the
    `.env` file.
*   Updated setup wizard to include Llama.cpp options.
*   LLM providers now read configuration directly from the
    top-level `Config` struct.
This commit implements security hardening and improves reliability:

*   Hardens security by ensuring configuration files containing
    API keys are only readable and writable by the owner (0o600).
    They previously used 0o644.
*   Explicitly passes the `APIKey` to the Google client, removing
    reliance on automatic environment variable loading by the
    underlying `genai` library. This increases reliability.
Co-authored-by: gemini-code-assist[bot] <176961590+gemini-code-assist[bot]@users.noreply.github.com>
When the setup wizard is aborted (e.g., via Ctrl+C), the error is now
translated from the library-specific `huh.ErrUserAborted` to the
internal `interfaces.ErrAborted`.

This removes dependency on the `huh` package error types in calling
functions, such as `main.go`, simplifying error handling logic there.
Repository owner deleted a comment from gemini-code-assist bot Nov 16, 2025
@rm-hull
Copy link
Owner Author

rm-hull commented Nov 16, 2025

/gemini summary

@rm-hull
Copy link
Owner Author

rm-hull commented Nov 16, 2025

/gemini review

@gemini-code-assist
Copy link
Contributor

Summary of Changes

This pull request significantly improves the user experience for initial application setup by introducing an interactive, terminal-based configuration wizard. This wizard automatically activates if the existing configuration is invalid or incomplete, guiding the user through selecting an LLM provider and entering necessary API keys and model details. The changes also include a more robust and unified internal configuration management system with validation and persistence capabilities.

Highlights

  • Interactive Configuration Wizard: Implemented a new TUI-based setup wizard using the 'charmbracelet/huh' library to guide users through initial configuration.
  • Automatic Configuration Validation: The application now validates its loaded configuration on startup, automatically prompting the setup wizard if essential settings (like API keys) are missing or invalid.
  • Unified Configuration Structure: The 'Config' struct has been refactored to use a single set of 'APIKey', 'Model', and 'BaseURL' fields, dynamically populated based on the selected 'LLMProvider'.
  • Configuration Persistence: New 'Validate()' and 'Save()' methods have been added to the 'Config' struct, allowing for programmatic validation and persistent storage of configuration changes to a 'config.env' file.
  • Enhanced .env File Management: A new 'updateProperties' helper function intelligently updates the 'config.env' file, preserving comments and existing entries while adding or modifying specific key-value pairs.
Changelog
  • go.mod
    • Added 'github.com/charmbracelet/huh' for the TUI wizard.
    • Added 'github.com/go-playground/validator/v10' for configuration validation.
    • Updated 'github.com/charmbracelet/bubbles' version.
    • Introduced several new indirect dependencies to support the added libraries.
  • go.sum
    • Updated checksums to reflect new and modified module dependencies.
  • internal/config/config.go
    • Refactored the 'Config' struct to consolidate LLM provider-specific fields (Gemini, OpenAI) into generic 'APIKey', 'Model', and 'BaseURL' fields, with validation tags.
    • Introduced a 'Validate()' method for configuration integrity checks using 'go-playground/validator'.
    • Added a 'Save()' method to write updated configuration to the 'config.env' file.
    • Implemented an 'updateProperties' helper function to handle intelligent updates of '.env' files, preserving non-modified lines and comments.
    • Adjusted the 'Load()' function logic to populate the unified 'Config' fields based on the 'LLMProvider'.
  • internal/config/config_test.go
    • Updated existing tests to align with the refactored 'Config' struct.
    • Added comprehensive unit tests for the 'updateProperties' function, covering various file content and update scenarios.
  • internal/llm_provider/google.go
    • Modified 'NewGoogleProvider' to retrieve the API key and model directly from the unified 'Config' fields.
  • internal/llm_provider/openai.go
    • Modified 'NewOpenAiProvider' to retrieve the API key, model, and base URL directly from the unified 'Config' fields.
  • internal/llm_provider/provider.go
    • Extended 'NewProvider' to support 'llama.cpp' as an LLM provider, routing its configuration through the OpenAI provider logic.
  • internal/llm_provider/provider_test.go
    • Updated tests to reflect the changes in how configuration is accessed.
  • internal/setup/wizard.go
    • New file containing the 'Run' function which orchestrates the interactive TUI setup wizard.
    • Defines 'huh.Group' forms for Google (Gemini), OpenAI, and Llama.cpp configurations, dynamically shown based on user selection.
    • Includes logic for setting default model values if not explicitly chosen by the user.
  • main.go
    • Integrated configuration validation at application startup.
    • If configuration validation fails, the 'setup.Run' wizard is invoked to guide the user.
    • The updated configuration is saved using 'newCfg.Save()' after the wizard completes.
    • Improved error handling for wizard abortion scenarios.
Activity
  • A 'github-actions[bot]' reported 2 failed JUnit tests related to 'Test_updateProperties' in 'internal/config/config_test.go'.
  • The 'gemini-code-assist[bot]' provided a high-priority review comment suggesting to restrict 'config.env' file permissions to '0600' and simplify the 'Save' method.
  • The 'gemini-code-assist[bot]' provided a medium-priority review comment suggesting to reuse a single 'validator.New()' instance instead of creating a new one on each call.
  • The 'gemini-code-assist[bot]' provided a medium-priority review comment recommending replacing hardcoded model names with exported constants for better maintainability.
  • The 'gemini-code-assist[bot]' provided a medium-priority review comment advising to handle 'huh.ErrUserAborted' gracefully in 'main.go' for a better user experience.
  • The author 'rm-hull' posted a '/gemini summary' command.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request introduces a helpful interactive setup wizard for configuration, which is a great improvement for user experience. The refactoring of the Config struct simplifies the structure nicely. My review focuses on a critical bug in saving the llama.cpp configuration, inconsistencies in how default values are loaded, a subtle bug in how the configuration file is updated, and opportunities to reduce duplicated code by centralizing default values. Addressing these points will improve the robustness and maintainability of the new configuration management.

Comment on lines 129 to 144
// 3: quote type = `"` or empty if unquoted
re := regexp.MustCompile(`^\s*([A-Za-z_][A-Za-z0-9_]*)=(?:"(.*)"|(.*))\s*$`)

for _, line := range original {
m := re.FindStringSubmatch(line)
if m == nil {
// Keep raw/unknown lines
out = append(out, line)
continue
}

key := m[1]

// m[2] is the quoted value (if present)
// m[3] is the unquoted value (if present)
quotedOriginal := m[2] != ""
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

There are a couple of issues in this section:

  1. The comment for the regex's capture group 3 is misleading. It captures the unquoted value, not the quote type.
  2. The logic on line 144 to detect if a value was originally quoted is buggy for empty quoted strings (e.g., KEY=""). It will be incorrectly identified as unquoted and rewritten without quotes.

A more robust approach would be to inspect the line string directly to check for surrounding quotes, as the regex capture groups are ambiguous for empty values.

Ensures consistency when appending new configuration
properties to the config file by sorting them
alphabetically.
The default LLM model assignment logic is now centralized
within `config.Load()`, removing duplication found in
`setup/wizard.go`.

This change also includes:
*   Fixing the `LLM_PROVIDER` value when saving `llama.cpp`
    configuration properties.
*   Removing verbose output when configuration validation
    fails and the setup wizard runs automatically.
This formalizes the configuration for the dummy test LLM provider.

*   API key and Model validation are now bypassed when
    `LLMProvider` is set to "test".
*   The test provider can now be selected and saved using the
    setup wizard, which is now triggered automatically if test
    mode is detected.
*   Simplifies the internal `NewTestDummy` provider constructor.
Updates the indirect dependency `github.com/clipperhouse/displaywidth`
from `v0.5.0` to `v0.6.0` in `go.mod` for general maintenance.
Adds placeholders for planned future work in the setup
wizard flow in `internal/setup/wizard.go`:

*   Adding invisible fields for form-level validation.
*   Implementing a final confirmation step (summary/Yes/No).
A confirmation step is now included at the end of the setup
wizard flow.

This allows users to review the selected LLM provider, API Key,
and model before confirming that the configuration should be
saved and potentially overwrite existing settings.

If the user declines the confirmation prompt, the setup process
is aborted.
When updating existing configuration properties in files, this change
implements two key improvements:

* The original line is archived by preceding it with a comment marker
  (`#`).
* The new configuration value is always written using double quotes
  (`key="value"`), ensuring consistent formatting regardless of how
  the original property was structured.
Extracts the confirmation step into a dedicated submitGroup.

Adds validationGroup using **go-playground/validator** to display
required fields if configuration validation fails.

*   Restructures provider groups (OpenAI, Google, Llama.cpp)
    to show Model selection before API Key input.
*   Converts Llama.cpp model input to a select list.
Updates to configuration properties now only comment out
the existing line and write the new line if the value
has actually changed (`oldVal != newVal`).

This refinement reduces file churn and prevents unnecessary
commenting of lines when configuration values are reapplied
but are identical to the existing values.
@coveralls
Copy link

coveralls commented Nov 17, 2025

Pull Request Test Coverage Report for Build 19863877439

Details

  • 74 of 263 (28.14%) changed or added relevant lines in 7 files are covered.
  • 1 unchanged line in 1 file lost coverage.
  • Overall coverage decreased (-4.7%) to 34.127%

Changes Missing Coverage Covered Lines Changed/Added Lines %
internal/llm_provider/google.go 2 3 66.67%
internal/llm_provider/provider.go 2 3 66.67%
internal/llm_provider/test_dummy.go 0 1 0.0%
main.go 0 9 0.0%
internal/config/config.go 67 113 59.29%
internal/setup/wizard.go 0 131 0.0%
Files with Coverage Reduction New Missed Lines %
internal/config/config.go 1 63.16%
Totals Coverage Status
Change from base Build 19863363397: -4.7%
Covered Lines: 301
Relevant Lines: 882

💛 - Coveralls

Adds new LLM options to the setup configuration wizard.

* Includes `Gemini 3 Pro (Preview)` to the Google models list.
* Updates the Llama.CPP model selection with several modern,
  high-performing models (e.g., Llama 3.1, Qwen 2.5, Phi 4, and
  updated Gemma 3 variants), replacing outdated options.
…t/setup-wizard

* 'main' of github.com:rm-hull/git-commit-summary:
  chore: Update Go dependencies in go.mod
  chore(deps): Bump actions/checkout from 5 to 6 (#24)
  chore(deps): Bump google.golang.org/genai from 1.35.0 to 1.36.0 (#23)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add setup wizard

3 participants