feat(assistant): wire the Nep casino guide on top of the Gemini SDK#26
Merged
Conversation
Replaces the Assistant placeholder with the cu-14 mockup port driven
end-to-end by Google's Gemini SDK.
* domain/assistant: ChatTurn + Role enum + AssistantRepository
interface so the feature layer never imports the SDK directly.
* data/assistant: NepSystemPrompt anchors the Neptunia-inspired
persona and the casino-only scope guardrail; GeminiAssistantRepository
builds a fresh chat per turn, logs failures with full stack traces
under the AssistantRepo tag, and fails fast with a clear message
when GEMINI_API_KEY is empty so the UI can render a useful bubble
instead of a generic exception.
* di/AssistantModule: provides the singleton GenerativeModel pinned
to gemini-2.5-flash (the model with the broadest free-tier coverage
across regions) and binds the repository.
* feature/assistant: sealed AssistantUiState (Welcome / Conversation)
backed by an MVVM Hilt ViewModel. The welcome body renders the
hero card and four canned suggestions; the conversation body uses
a LazyColumn with stable per-message UUIDs so repeat questions
inside the same minute don't crash on key collisions, plus a
typing indicator and an error bubble accent on failed turns. The
input bar enforces the 300-char budget, dispatches on the IME
Send action, and rides the soft keyboard via imePadding.
Extracts the pulsing Polygon-mainnet dot out of LoginScreenEffects
into ui/components/PulsingDot so the Nep header and the login meta
row share one implementation.
Wires the Gradle script to read GEMINI_API_KEY from local.properties
(gitignored) into BuildConfig, and declares the INTERNET permission
the Gemini HTTP client needs (Firebase merges it on release builds
but a clean debug install needs it explicit, otherwise the repository
silently fails every turn).
Eight unit tests cover the ViewModel state machine: initial Welcome,
user-bubble-then-typing-then-reply, draft trimming, empty/over-budget
rejection, error bubble surface on repository failure, error filtering
from the next-turn history, multi-turn history wiring, and clear()
back to Welcome.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
domain/assistantexposesAssistantRepository+ChatTurn+Roleso the feature layer never imports the SDK.data/assistantships the Nep system prompt and the Gemini-backed implementation;di/AssistantModuleprovides the singletonGenerativeModel(pinned togemini-2.5-flash) and binds the repository.feature/assistantis a sealedAssistantUiState(Welcome / Conversation) backed by a Hilt MVVM ViewModel that exposes aStateFlow. The Welcome body renders the hero + four canned suggestions; the Conversation body uses aLazyColumnwith per-message UUIDs, a typing indicator, and a danger-accented bubble on failed turns. The input bar enforces the 300-char budget, sends on IME Send, and rides the soft keyboard viaimePadding.PulsingDotout ofLoginScreenEffectsintoui/componentsso the Nep header and the login meta row share one implementation.GEMINI_API_KEYto the Gradle script (read from gitignoredlocal.propertiesintoBuildConfig) and declares theINTERNETpermission the SDK needs.Persona + scope
NepSystemPromptanchors the Neptunia-inspired voice (cheerful, casual, "~" suffix, refers to itself as Nep) and locks the scope to Stack Casino game rules / Provably Fair / wallet on Polygon. Off-topic asks get a polite refusal via the prompt itself instead of an extra UI state.Notes
GeminiAssistantRepositorylogs failures under theAssistantRepotag with full stack traces and short-circuits with a clear message when the key is empty so the UI can render a useful bubble instead of a generic exception.Test plan
Local setup
Add to
stack/local.properties(gitignored):Then
./gradlew installDebug.