Remove topic restrictions from Duncan cloud system prompt
Details
Duncan was scoped as "dedicated exclusively to the PrivStack ecosystem"
which refused general-knowledge questions. Cloud models use the user's
own API key, so there's no reason to restrict what they can talk about.
Updated cloud system prompt to:
- Explicitly allow any topic (general knowledge, weather, creative, etc.)
- Ask for location context (zip code) when needed for location-dependent
questions like weather, if not already in memory
- Use memory-stored location when available
Fix API key delete failing when vault blob is already gone
Details
When a vault blob no longer exists (data wipe, profile change), the
VaultBlobDelete call throws NotFound, which aborted the entire delete
handler — leaving the stale key hint in settings and the entry in the
Saved Keys list with no way to remove it.
Now catches the VaultBlobDelete failure independently and still proceeds
to clean up the settings hint and cached provider key.
Fix Duncan not initializing — use settings key hints for IsAvailable
Details
The previous fix (deferred recheck) was insufficient. The root issue is
that AiService.IsAvailable called provider.IsConfigured which does a
synchronous vault blob read via FFI. This can fail silently during
startup, and since IsEnabled is a plain getter with no re-notification,
Duncan stays hidden for the session.
New approach: IsAvailable for cloud providers now checks
AppSettings.AiSavedKeyHints instead of reading the vault. The key hints
are persisted in the settings JSON when a user saves an API key, so
they're available immediately at startup — no vault read needed. The
actual vault read still happens at request time via the async path in
CompleteAsync/StreamCompleteAsync, which properly handles vault unlock.
This is a UI-gating-only change. The vault-based IsConfigured check
is still used by GetProviders() (settings page) and at request time.
Fix Duncan not initializing on app load due to vault timing
Details
The AI provider's IsConfigured check uses a synchronous vault read with
a 2-second timeout (GetApiKeySync). During DI resolution this runs before
EnsureStandardVaults has unlocked the ai-vault, so it times out and
returns false. Since IsEnabled is a plain computed property with no
re-notification, Duncan stays dead for the entire session.
Fix:
- AiService.RecheckAvailability() — called from the deferred background
services block after the vault is guaranteed unlocked. Re-evaluates the
provider's IsConfigured state.
- AiService.AvailabilityChanged event — fires when availability transitions.
- AiSuggestionTrayViewModel subscribes to AvailabilityChanged and re-raises
PropertyChanged for IsEnabled, which flips the UI visibility binding.
Load .env file at startup for local development
Details
Adds a LoadDotEnv() helper that walks up from the executable directory
to find the nearest .env file and sets any missing environment variables.
This ensures PRIVSTACK_GITHUB_CLIENT_ID and other secrets are available
during local dev without requiring manual export or launchSettings.json.
Existing env vars are never overwritten.
Get notified about new releases