CHANGELOG.md (view raw)
1# Changelog
2
3All notable changes to this project will be documented in this file.
4
5The format is based on [Keep a
6Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to
7[Semantic Versioning](https://semver.org/spec/v2.0.0.html).
8
9## [0.7.1] - 2026-04-22
10
11### Fixed
12
13- Environment variables were correctly overriding config file values, but CLI
14 arguments without explicit flags were also overriding config file values
15 unintentionally.
16 - Root cause: `go-arg` was populating struct fields with default values
17 from `default:` tags even when those CLI flags weren't provided
18 - Fix: Removed `default:` tags from Args struct fields for LLM options
19 (`model`, `base-url`, `api-key`, `max-tokens`, `temperature`);
20 Viper's own default handling is sufficient
21 - Fix: Changed Args struct fields from value types to pointer types
22 (`*string`, `*int`, `*float64`) so that "not provided on CLI" can be
23 distinguished from "provided but zero/empty"
24 - Fix: Updated `BindCLIArgs()` and `isZero()` to properly handle pointer
25 types and distinguish nil pointers from zero values
26- `isZero()` with compound type switch cases: Compound type cases like `case
27 *int, *int8, *int16, *int32, *int64` don't properly handle nil comparison when
28 stored in an interface variable. Fixed by splitting into individual type cases.
29- `isZero()` missing nil interface handling: When a nil pointer is stored
30 in an `any` interface, `value != nil` returns `true` (the interface itself
31 is not nil). Added early `if v == nil { return true }` check.
32
33## [0.7.0] - 2026-04-22
34
35### Added
36
37- **`--dry-run` option**: Validate configuration and preview what would happen
38 without making any LLM API calls. Useful for validating feeds file and
39 configuration, checking article counts and filtering results and anything
40 else that can be done "offline".
41- **Styled terminal output using `lipgloss`**: All CLI output now uses ANSI
42 colour codes for better readability:
43- **`$NO_COLOR` environment variable support**: Respects the ["no
44color"](https://no-color.org/) standard. When `NO_COLOR` is set, all styling is
45disabled and plain text is output instead.
46
47### Changed
48
49- API key validation now only occurs when not using `--dry-run` mode
50
51## [0.6.0] - 2026-04-22
52
53### Added
54
55- **Comprehensive unit test suite**, including CLI argument tests
56 (`--feeds-file`, `--prompt`, `--api-key`, `--model`, `--base-url`),
57 configuration tests, aggregator tests, output formatter tests, processor
58 tests and defaults tests.
59- **`--base-url` CLI option**: configure custom API endpoints for different LLM
60 providers. Should support any OpenAI-compatible provider.
61 - Environment variable: `LLM_AGGREGATOR_BASE_URL`
62- `internal/defaults` package
63- `docs/TESTING.md` which contains a comprehensive testing guide with test
64 descriptions
65
66### Changed
67
68- **Configuration defaults**: All packages now use `defaults.Default*` constants
69 - `internal/config`: Uses `defaults.Default*` for default values
70 - `internal/runtime`: Uses `defaults.Default*` for runtime defaults
71 - `internal/llm`: Uses `defaults.Default*` for LLM client defaults
72
73### Fixed
74
75- `nil` pointer safety in aggregator
76 - Added nil checks for `progressCtx` across all log statements
77 - `FeedAggregator` now works correctly when progress context is nil
78 - Tests use `NewFeedAggregatorWithProgress` with explicit progress context
79
80## [0.5.0] - 2026-04-22
81
82### Added
83
84- **Accurate token counting with tiktoken**
85 - New `internal/tokeniser` package using OpenAI's tiktoken-go library
86 - BPE tokenisation for accurate token counting vs rough character estimation
87 - Encoding caching to avoid repeated initialisation overhead
88 - Model-aware encoding selection (cl100k_base, o200k_base, etc.)
89 - `CountTokens()` and `CountMessagesTokens()` functions
90 - Fallback to rough estimation when tiktoken initialisation fails
91- **Concurrent feed fetching**: Feeds are now fetched concurrently using
92 `golang.org/x/sync/errgroup`
93 - Semaphore limits concurrent requests to 10 to avoid server overload
94 - Mutex-protected shared state for thread-safe article collection
95 - Partial failures don't stop other feeds from being processed
96- **Scrollable summary in TUI**
97 - Bubble Tea viewport component for browsing long summaries
98 - Keyboard navigation: j/k or arrows (scroll), Space/B (page), g/G
99 (start/end)
100 - Mouse wheel scrolling support
101 - Scroll progress indicator showing position and total lines
102
103### Changed
104
105- **Streamlined configuration management**: Viper now uses global instance with
106automatic precedence handling. Simplified configuration flow: Parse → GetViper
107→ BindCLIArgs → ViperToRuntime
108- **TUI colour scheme**: All hex colour codes replaced with ANSI 256-colour
109 palette
110
111### Fixed
112
113- Viewport now properly handles scroll events via `Update()`. Summary content
114 pre-wrapped to viewport width before display
115- Fixed string literal colour names to use actual variables
116
117## [0.4.0] - 2026-04-21
118
119### Changed
120
121- **TUI is now fully functional and production-ready**: Replaced the
122work-in-progress TUI implementation with a robust Bubble Tea command pattern:
123 - Runtime execution now uses native `tea.Cmd` instead of manual goroutine
124 orchestration.
125 - Added real-time progress updates via `progress.Progress` interface with
126 stage, substage, and article count messages.
127 - TUI displays a spinner, elapsed time, and final summary inline.
128 - Removed signal handling and channel synchronisation in favour of Bubble
129 Tea's built-in lifecycle.
130 - `TUIProgress` now only sends messages to an existing program, simplifying
131 integration.
132 - Both verbose mode (`SimpleLogger`) and TUI mode share the same
133 `progress.Progress` interface.
134
135## [0.3.0] - 2026-04-21
136
137### Added
138
139- **Configuration file support via TOML** (XDG-compliant and cross-platform)
140 - Load settings from `~/.config/llm_aggregator/config.toml`
141 - Supports all aggregation, API, and output options
142 - Example configuration file at `configs/config.example.toml`
143- **Environment variable support with `LLM_AGGREGATOR_` prefix**
144 - All configuration options can be set via environment variables
145 - Precedence order: CLI arguments > environment variables > config file >
146 built‑in defaults
147- New `internal/config` package with Viper integration
148 - `Load()` and `Save()` methods for configuration management
149 - `GetConfigPath()` for XDG‑compliant config file location
150 - `ConfigExists()` to check for existing configuration
151- Comprehensive unit tests for configuration loading, saving, and environment
152 variable precedence (`internal/config/config_test.go`)
153
154### Changed
155
156- **Environment variable renamed:** `DEEPSEEK_API_KEY` →
157 `LLM_AGGREGATOR_API_KEY`
158- **CLI help text** now reflects the new API key environment variable and
159 general configuration options
160- **Command‑line argument precedence** implemented in `cmd/llm_aggregator.go`
161via `applyConfiguration()`
162- Updated all help text, documentation, and code references
163- `README.md` completely revised with a new "Configuration" section
164
165### Removed
166
167- Global `QuietMode` and `VerboseMode` variables from
168`internal/config/config.go`. Replaced by runtime‑specific configuration in
169`runtime.Runtime` and CLI arguments
170- Hardcoded system prompt in `runtime.NewRuntime()`. Now left empty, allowing
171configuration or client default to be used
172- CLI flags now correctly override config file and environment variables
173
174## [0.2.0] - 2026-04-21
175
176### Changed
177
178- Moved all progress and status messages behind `-v/--verbose` flag
179- Default CLI mode is now silent except for final output and errors
180- Components (aggregator, processor, LLM client) use logger interface
181controlled by verbose flag
182
183## [0.1.0] - 2026-04-21
184
185### Added
186
187- Complete translation from Python prototype to Go implementation
188- RSS/Atom feed parsing using `gofeed` library
189- DeepSeek API integration via `openai-go` client, configured for `/chat/completions` endpoint
190- Content filtering and processing with keyword‑based include/exclude, date filtering, and sorting
191- Command‑line interface using `go‑arg` with automatic help and version flags
192- Multiple output formats: plain text, GitHub‑flavoured markdown, and JSON
193- Terminal user interface (TUI) built with `bubbletea` featuring:
194 - Animated progress bar with gradient colours (`#FF7CCB` to `#FDFF8C`)
195 - Live article counters (aggregated/processed)
196 - Elapsed time display
197 - Coloured status indicators using `lipgloss` styling
198 - Keyboard controls (q/Ctrl+C to quit)
199- Web content extraction fallback using `goquery` when feed descriptions are minimal
200- Configurable limits: articles per feed, maximum age, total articles
201- Token estimation and API usage logging
202- Environment variable support (`LLM_AGGREGATOR_API_KEY`) for authentication
203- Example feeds file with technology, programming, and free software sources
204
205### Changed
206
207- Program structure organised into standard Go layout: `cmd/`, `internal/`, `pkg/`
208- English spelling conventions maintained throughout (colour, initialise, summarise)
209- Error handling improved with specific messages for common API failures (invalid key, rate limits, etc.)
210- Progress reporting unified through a `ProgressContext` interface for both TUI and CLI modes
211
212### Fixed
213
214- Initial API endpoint mismatch (using `/responses` instead of `/chat/completions`)
215- Nil pointer dereferences when handling optional feed metadata (author, dates)
216- String repetition syntax errors in Go (replaced `"="*80` with `strings.Repeat`)
217- CLI help/version flag handling to show information without requiring other arguments
218- Type compatibility issues with `openai-go` v3 API (message parameters, token usage fields)