Skip to content

feat: add obk settings interactive TUI#103

Merged
priyanshujain merged 31 commits intomasterfrom
settings-command
Mar 19, 2026
Merged

feat: add obk settings interactive TUI#103
priyanshujain merged 31 commits intomasterfrom
settings-command

Conversation

@priyanshujain
Copy link
Copy Markdown
Collaborator

@priyanshujain priyanshujain commented Mar 19, 2026

Summary

  • Adds obk settings command — an interactive TUI tree browser for browsing and editing all settings after initial setup
  • Pure service layer (settings/) with Get/Set closures on *config.Config — no reflection, no UI deps — ready for web UI or HTTP API later
  • Bubbletea TUI (internal/settings/tui/) with expand/collapse categories, inline values, huh form editing, and viewport scrolling
  • Providers-first UX: Providers category appears above model fields — users set up API keys before choosing models
  • Live API key verification: After entering an API key, a tiny test call (5 tokens, 10s timeout) verifies it immediately
  • Dynamic model selection: Model tier fields are selects that only show models from providers with configured API keys (recommended models marked with *)
  • Filtered profiles: Profile select only shows profiles whose required providers are all configured
  • 31 tests covering all field types, nil-pointer safety, dynamic options, verification flow, save errors, and edge cases

Test plan

  • go build ./... compiles
  • go test ./settings/... — 31 tests pass
  • obk settings appears in obk --help
  • obk settings — TUI launches, tree renders with current config values
  • Expand Providers, enter API key → see "Saved! API key verified" flash
  • Enter wrong API key → see "Saved! Warning: verification failed: ..."
  • Select Default Model → only models from configured providers shown
  • Select Profile → only profiles with configured providers shown
  • Edit a string field (timezone) → verify saved to ~/.obk/config.yaml
  • Esc/q exits cleanly

Pure service layer for browsing and editing all obk settings via
Get/Set closures on config fields. Includes full tree of categories
(General, Models, Channels, Data Sources, Integrations, Advanced)
with nil-pointer safety and credential store abstraction.
Tree browser with expand/collapse categories, inline value display,
and huh form editing. Supports string, select, bool, number, and
password field types with viewport scrolling.
Wires settings service and TUI into the CLI with credential
store/load from keychain.
These are now directly imported by the settings TUI package.
…cases

Covers save error propagation, nil credential handlers, select field
round-trips (profile, auth method), context window/compaction threshold,
nil-pointer safety for integrations/websearch/daemon, telegram owner_id,
password empty-set noop, loadCred failure fallback, and GWS fields.
- Move Providers category above model fields in the tree
- Model tier fields are now TypeSelect with OptionsFunc that shows
  only models from providers with configured API keys
- Profile select filters to profiles whose required providers are
  all configured
- API key fields get AfterSet hook for live verification
- Add OptionsFunc, AfterSet, verifyProvider to service types
- editor.go passes svc to resolve OptionsFunc at form build time
- model.go calls AfterSet on successful save, appends status to flash
Registers provider factories and adds live API key verification
using a tiny test call (5 tokens, 10s timeout) with the cheapest
model for each provider.
Tests for: providers before models in tree, model tiers are selects,
options filtered by configured providers, empty-providers placeholder,
profile filtering, AfterSet verify success/failure, ResolvedOptions
fallback, nil verifyProvider handler.
Support custom edit handlers (wizards) and conditional read-only fields
for the profile-first settings flow.
Helpers for profile selection with dynamic preview, API key prompts,
provider selection, and model selection forms.
Rewrite registry to use profile wizard as primary entry point. Fixed
profiles lock model tiers. Custom profiles allow per-tier model selection.
Provider auth verified before saving. Providers moved to bottom of tree.
Support EditFunc wizards by quitting bubbletea, running the wizard
synchronously, then restarting TUI. Add ReadOnly flash message for
locked fields.
Replace provider-first tests with profile display, EditFunc, ReadOnly,
masked key, and dynamic model options tests.
…-flash

gemini-2.0-flash-lite is deprecated/404. Replace all references across
profiles, model catalog, context windows, test models, and docs.
Models → LLM Models, Profile → LLM Cost Profile,
"(1 API key)" → "(single provider)" on all single-provider profiles.
Cost profiles (starter/standard/premium) first, single-provider next.
Profile list labels simplified to just p.Label; description shown via
ProfilePreview in DescriptionFunc.
ListModels calls each provider's free list-models API to enumerate
available models. VerifyModelAccess sends a minimal chat to confirm
the API key has access to a specific model. Includes httptest tests
for all 5 providers including Anthropic pagination.
JSON-based cache at ~/.obk/models/<provider>.json with TTL staleness
check and per-model verification tracking keyed by API key hash.
Replace chat-based verification (sends "Reply with OK") with the free
ListModels API. Results are cached to ~/.obk/models/ for later use.
modelOptionsForTier and buildTierOptions now read from the model cache
populated by ListModels instead of the static ModelCatalog. ModelCatalog,
ModelsForProviders, and ModelsForTier removed. ModelInfo type kept.
EditFunc is no longer needed — profile wizard now runs inline
in the bubbletea TUI. Save() exposes saveFn for the TUI model.
Remove profileWizard, setupFixedProfile, setupCustomProfile,
configureProviderAuth, buildProfileSelectOptions — all replaced
by inline TUI state machine in model.go.
Huh form wrappers (runProfileSelect, promptAPIKey, selectProvider,
selectModel) are no longer needed — forms are built inline in TUI.
EditFunc field was removed from Field struct.
Single tea.NewProgram run — profile wizard now runs inline
as TUI state transitions instead of quitting and restarting.
Add wizard states (profileSelect, providerAuth, verifying,
modelSelect) to TUI model. Background model cache loading on
init. Async provider verification via tea.Cmd. No more screen
flicker from quitting and restarting bubbletea.
Bubbletea uses value receivers — pointers to model struct fields
become dangling after Update copies. Allocate wizardProfile and
wizardAPIKey on the heap so huh forms write to a stable address.
This fixes profile selection picking the wrong profile.
@priyanshujain priyanshujain merged commit 6069a34 into master Mar 19, 2026
8 checks passed
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.

1 participant