Skip to content

Android/Expo chat screen #150

Description

@rghvgrv

Parent

#145 — Ask Splitzy: personal spending chatbot (self-hosted LLM)

What to build

The Android/Expo chat screen: a streaming API client for POST /api/chat/stream, a Zustand store for chat state, and a chat screen route using existing UI primitives. Consumes the same contract as #149 (history + streaming), independently buildable in parallel.

Implementation Steps

  1. Endpoint + types — Add CHAT_STREAM: "/api/Chat/stream" to Android/src/constants/endpoints.ts. Add ChatTurn, ChatRequest/ChatMessage types to Android/src/types/api.types.ts, mirroring the backend DTOs from Chat foundation: streaming balance intent + router skeleton #146/Multi-turn conversation context (stateless history) #148.
  2. Streaming API client — Create Android/src/services/api/chat.api.ts. The existing Android/src/services/api/client.ts uses axios, which does not support incremental response streaming in React Native; implement this call with fetch() directly (attaching Authorization: Bearer <token> via expo-secure-store's tokenStorage.getAccessToken(), matching client.ts's token source) and consume the response body via ReadableStream/async iteration. [HITL]: verify the installed Expo SDK 55 / RN 0.83 runtime supports fetch response streaming (via the whatwg streams polyfill) in a real device/emulator build before relying on it — fall back to a documented workaround if not supported.
  3. Chat store — Create Android/src/stores/chat.store.ts (Zustand, following the pattern in Android/src/stores/dashboard.store.ts): holds the turn history (trimmed per Multi-turn conversation context (stateless history) #148's contract), in-progress streaming message, loading/error state.
  4. Chat screen — Create Android/src/app/chat.tsx (or a tab entry under Android/src/app/(tabs)/ if preferred for discoverability) using existing primitives from Android/src/components/ui/ (Input, Button, LoadingSpinner, GlassCard) and Android/src/components/layout/ScreenWrapper.tsx, styled with NativeWind per this app's design system (Android/CLAUDE.md).
  5. Manual verification — Run npm run android (or iOS) and npx tsc --noEmit; ask a balance question, a category-spend question, a follow-up, and an out-of-scope question; confirm streaming renders and all four states display correctly per this project's existing manual-QA practice.

Agent Routing

agent_routing:
  complexity_hint: medium
  required_capability: balanced
  parallel_safe: true
  cost_preference: balanced
  speed_preference: balanced
  ownership_scope:
    - Android/src/services/api/chat.api.ts
    - Android/src/stores/chat.store.ts
    - Android/src/app/chat.tsx
    - Android/src/constants/endpoints.ts
    - Android/src/types/api.types.ts
  verification:
    - npx tsc --noEmit (from Android/)
    - Manual device/emulator walkthrough: balance / category / follow-up / refusal questions

Technical Context Snapshot

Current stack in scope

  • Expo SDK 55, React Native 0.83, React 19, Expo Router (file-based), Zustand for state, NativeWind v4 for styling, Axios + expo-secure-store for the existing authenticated HTTP client (Android/src/services/api/client.ts).
  • Design system: primary #256af4, background #0a0f18, glass panels — see Android/CLAUDE.md.

Dependencies in scope

  • Reuse: existing expo-secure-store token helpers, existing components/ui/* primitives, existing stores/* Zustand pattern.
  • New dependency additions allowed for this slice: no, unless the [HITL] streaming-support check in step 2 finds fetch streaming unavailable on this RN version — if so, flag back rather than silently adding a polyfill package.

Architecture alignment

  • Do not modify files outside Android/ in this slice (per Android/CLAUDE.md).
  • Follow existing services/api/*.api.ts + stores/*.store.ts conventions (see dashboard.api.ts / dashboard.store.ts).
  • create-git-issue provides routing hints only; it must not assign concrete agent/model names.
  • run-with-it remains the final runtime routing authority.

Integration touchpoints

Acceptance criteria

  • User can open the chat screen, ask a question, and see the answer stream in incrementally (or, if streaming proves unsupported on-device, render the complete answer with a clear loading state — documented as a deviation).
  • A follow-up question is sent with prior turn history and answered in context.
  • Out-of-scope questions render visibly differently from real data answers.

Blocked by

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    enhancementNew feature or requestready-for-agentImplementation-ready slice for an AFK/agent to pick up

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions