feat(gemini): add profile management and advanced settings UI#74
feat(gemini): add profile management and advanced settings UI#74Itstommy10 wants to merge 1 commit into
Conversation
- implement saved profiles list and deletion in provider settings modal - add profiles directory, quota display, and pace mode configuration - wire profiles directory override from database to runtime manager - align Gemini provider features with Codex for consistency
prakersh
left a comment
There was a problem hiding this comment.
Hey, thanks for putting this together! Multi-account Gemini support is something we've wanted (issue #73), and the overall architecture here - profile-based management with a manager pattern mirroring how Codex multi-account works - is the right direction. There are some issues to sort out before this can merge though. I've grouped them by severity to make it easier to work through.
Build Failures (CI broken)
The PR references types and functions that don't exist in the current codebase. It looks like there are API-layer changes that were meant to be part of this PR but weren't included in the diff:
api.GeminiCredentials.UserID- this field doesn't exist on the struct (seeinternal/api/gemini_credentials.go:13-19)api.ParseGeminiIDTokenUserID()- function doesn't exist anywhere in the repoapi.GeminiCredentials.CompositeExternalID()- method doesn't existagent.NewGeminiAgentWithAccount()- onlyNewGeminiAgentexists currentlyagent.GeminiAgent.SetTokenSave()- not defined on the agent
There are also two call-site signature changes that don't match the existing functions:
store.QueryGeminiRange(0, start, end)- current signature is(start, end time.Time, limit ...int), no account ID parametertracker.UsageSummary(0, modelID)- current signature is(familyID string), no account ID parameter
Both CI jobs (Test and Menubar macOS) fail with 9+ compilation errors from these missing pieces. If you have these changes locally, they just need to be included in the PR.
Security Issues
A few things here that should be addressed before merge:
Path traversal in profile names (High):
Profile names are used directly in file path construction without any sanitization:
profilePath := filepath.Join(profilesDir, name+".json")A name like ../../.ssh/authorized_keys would resolve outside the profiles directory. This affects save, delete, refresh, SaveProfile, and DeleteProfile. A straightforward fix would be validating names against something like [a-zA-Z0-9_-], or using filepath.Base() and checking the result.
Credential file written world-readable (High):
In gemini_agent_manager.go, SaveProfile writes files with 0644:
return os.WriteFile(profilePath, data, 0644)Since these files contain OAuth tokens, they'd be readable by any user on the system. The rest of the codebase consistently uses 0o600 for credential files - this should match.
Plaintext credential storage (Medium):
Profiles store access tokens, refresh tokens, and ID tokens as plaintext JSON. The project uses macOS Keychain for Anthropic tokens (see internal/api/anthropic_token_unix.go). Worth considering whether Gemini tokens should follow the same pattern rather than introducing a separate, less secure storage path. Happy to discuss the tradeoffs here if helpful.
Missing Functionality
No API route handlers registered:
The frontend JS calls ${API_BASE}/api/gemini/profiles (both GET and DELETE), but no route handler for that path is registered anywhere in handlers.go. The PR adds SetGeminiAgentManager but the actual endpoint wiring is missing - so all profile operations from the UI will return 404.
Hardcoded placeholder in production code (gemini_profiles.go:315):
// TODO: Sostituire con ricerca corretta per nome
dbAccount, err := st.GetProviderAccountByID(1) // Segnaposto temporaneo per sbloccare la buildThis will return wrong account data for every profile except the one that happens to have DB ID 1.
Code Structure
Root-level files:
gemini_profiles.go (373 lines) and gemini_profiles_test.go are in the repo root as package main. The project's convention is to put this kind of logic under internal/ - for reference, the Codex equivalent lives at internal/agent/codex_agent_manager.go. Moving these would keep the codebase consistent.
Duplicate function definitions:
geminiCompositeExternalID and geminiProfileCompositeExternalID are defined identically in both gemini_profiles.go and gemini_agent_manager.go. These should live in one place.
Dead code in main.go:
geminiClient = api.NewGeminiClient(token, logger)
_ = geminiClient // Marcatore per evitare declared and not usedSince the PR replaces the single-agent approach with the manager, geminiClient is no longer needed and can be removed.
Test Issues
The tests have a few problems that would prevent them from passing even if the build issues were fixed:
gemini_profiles_test.go: Creates profiles at~/.gemini/profiles/butgeminiProfilesDir()returns~/.onwatch/data/gemini-profiles/- the test will never find its own test datagemini_agent_manager_test.go: Callsf.manager.Run()with no arguments, butRun(ctx context.Context)requires a context- Several tests construct
api.GeminiCredentials{UserID: ...}which won't compile sinceUserIDisn't a field on that struct
Minor
- Comments in Italian ("Segnaposto temporaneo", "Sostituire con ricerca corretta", "Marcatore per evitare") - should be in English for consistency
- The template parsing refactor (
template.New("").ParseFStotemplate.ParseFS+ manualLookup) is an unrelated change that alters template naming semantics - would be cleaner as a separate PR if intentional subtle.ConstantTimeCompareis used for comparing locally-stored tokens where there's no timing attack vector - a plain!=would be clearer and more appropriate here- Verbose template debug logging (iterating and logging all template names) added to production code paths
I know that's a lot of items, but the core design is solid. Once the missing API-layer changes are included and these issues are addressed, this should come together well. Happy to help with any of these if you have questions.
This PR enhances the Gemini provider by adding profile management and advanced configuration options to the UI, matching the functionality available for the Codex provider.
Key Changes:
Why:
Previously, Gemini settings only allowed toggling telemetry. This update provides parity with Codex, allowing users with multiple Google Cloud projects or specific quota needs to manage them more effectively through the web interface.