Skip to content

fix(android): AI Coach fixes for #1074 (crash, Disconnect UI, truncation, real errors, model scan) - #1083

Merged
ryanbr merged 3 commits into
mainfrom
android-coach-error-crash-robustness
Aug 5, 2026
Merged

ryanbr merged 3 commits into
mainfrom
android-coach-error-crash-robustness

Conversation

@ryanbr

@ryanbr ryanbr commented Aug 5, 2026 •

Copy link
Copy Markdown
Owner

Fixes #1074 (AI Coach + custom DeepSeek provider, Android)

After reviewing the reporter's screenshots, this addresses all the reported symptoms:

1. Crash (NullPointerException in the Coach error line)

error!! read inside a semantics {} closure that the accessibility pass runs later; a recomposition can clear error first, so the deferred !! throws. Snapshot a stable local first.

2. Disconnect button broken / invisible (screenshots 2 & 3)

A long model id in the provider pill (Custom (OpenAI-compatible) · deepseek-v4-pro) consumed the row and squeezed "Disconnect" into a one-letter-per-line vertical stack (or pushed it off-screen). StatePill now ellipsizes (a pill is single-line); the Disconnect keeps its intrinsic single-line width.

3. Reply truncated / "context window" (screenshot 1)

max_tokens = 900 cut detailed replies mid-sentence on cloud providers → 4096 (a cap, not a target; the Gemini leg already used 4096). And the cut-off note gave Ollama-specific num_ctx advice that's wrong for a cloud provider — rewritten accurate + provider-agnostic.

4. Empty response → surface the real error

On a 200 with empty content (a hand-set model the provider doesn't offer — the reporter's model names were Gemini's), the app threw a blanket "empty reply". Now it surfaces the provider's actual error, or points at the hand-set model. All three provider paths.

5. Model scan not working

A pasted full chat URL made the scan derive …/chat/completions/models. normalizeCustomBaseUrl strips the chat suffix so /models and /chat/completions resolve either way.

Testing

Follow-up

Swift AICoach twin (Custom.swift) has the same empty-reply + base-URL gaps — a mirrored change + app-build to follow. Android-only; no analytics/decoder/stored-data/BLE change.

@ryanbr
ryanbr force-pushed the android-coach-error-crash-robustness branch from eec53bc to 8c165b1 Compare August 5, 2026 08:33
@ryanbr ryanbr changed the title fix(android): Coach error-display crash + surface the provider's real error (#1074) fix(android): Coach crash + surface real provider errors + model-scan URL (#1074) Aug 5, 2026
…truncation, Disconnect UI)

Five fixes for the AI Coach + custom OpenAI-compatible (DeepSeek) provider report,
all confirmed against the reporter's screenshots:

1. Crash — `error!!` read inside a `semantics {}` contentDescription closure NPE'd
   when the accessibility pass ran after a recomposition cleared `error`. Snapshot
   into a stable local first.
2. Surface the provider's real error — on a 200 with empty assistant content (a
   hand-set model the provider doesn't offer), some servers put the error IN the 200
   body. Surface it instead of a blanket "empty reply"; all three provider paths.
3. Custom base-URL normalization — a pasted full chat URL made the model scan hit
   .../chat/completions/models and return nothing; strip the chat suffix so /models
   and /chat/completions resolve either way.
4. Truncation — max_tokens 900 cut detailed cloud replies mid-sentence (the screenshot
   showed it on DeepSeek). Raise to 4096 (a cap, not a target; the Gemini leg already
   used 4096). The cut-off note gave Ollama-specific `num_ctx` advice that is wrong for
   cloud providers — rewritten accurate and provider-agnostic.
5. Disconnect UI — a long model id in the provider pill squeezed the Disconnect into a
   one-char vertical stack (or off-screen). StatePill now ellipsizes (a pill is one
   line); the Disconnect keeps its intrinsic single-line width.

Pure helpers unit-tested (AiCoachEmptyReplyTest, AiCoachCustomUrlTest);
compileFullDebugKotlin + i18n audit green. Layout changes not device-verified
(Compose won't render on this box). Android-only; the Swift AICoach twin has the
empty-reply + base-URL gaps as a follow-up.
@ryanbr
ryanbr force-pushed the android-coach-error-crash-robustness branch from 8c165b1 to c5a1427 Compare August 5, 2026 08:50
@ryanbr ryanbr changed the title fix(android): Coach crash + surface real provider errors + model-scan URL (#1074) fix(android): AI Coach fixes for #1074 (crash, Disconnect UI, truncation, real errors, model scan) Aug 5, 2026
ryanbr added a commit that referenced this pull request Aug 5, 2026
Mirrors the Swift side of the Android AI Coach fixes (#1083 for #1074):

- Raise the reply cap 900 -> 4096 tokens on OpenAI, Anthropic and the
  Custom (OpenAI-compatible) provider. 900 truncated detailed coaching
  replies mid-sentence; Gemini was already 4096. It is a cap, not a
  target - the system prompt keeps replies short.
- Provider-agnostic truncation note (was Ollama-specific num_ctx advice
  that is wrong for cloud providers hitting the response-length cap).
- Surface the provider's real error when a 200 body carries no assistant
  content: some OpenAI-compatible servers return the error INSIDE the 200
  body. New emptyReplyError() + AICoachError.emptyReply case render the
  same user-facing text as Android emptyReplyMessage, byte-for-byte.
  Wired into the Custom / OpenAI / Anthropic / Gemini parses.
- Trim assistant content before the empty-check and return, matching
  Android's ?.trim(): a whitespace-only 200 reply is treated as empty
  (so emptyReplyError fires) rather than returned as blank text.
- Normalise the Custom base URL (normalizeCustomBaseURL): strip a trailing
  /chat/completions or /completions so a pasted full chat URL no longer
  makes the model scan hit .../chat/completions/models and return nothing.
  Byte-identical to Android normalizeCustomBaseUrl.

Adds AICoachEmptyReplyAndUrlTests mirroring the Android parity tests.

App-target Swift (no default CI); compiled via app-build (Strand macOS +
NOOPiOS).
The modern-params leg (max_completion_tokens) fronts reasoning models,
which count hidden thinking tokens against that budget - so the old 900
starved them into truncated/empty replies even more readily than the
standard path. Match the standard leg's 4096 cap. A cap, not a target;
short answers are unaffected. Keeps this at parity with the iOS/macOS
side, which uses 4096 on both legs.
The emptyReplyMessage KDoc was stranded above normalizeCustomBaseUrl's
own doc block, so it documented nothing (Dokka/IDE hover would miss it)
and tripped the detached-doc-comment regression gate. Move it down onto
emptyReplyMessage. No code change.
ryanbr added a commit that referenced this pull request Aug 5, 2026
iOS/macOS parity for the Android AI Coach fixes (#1083, tracking #1074): 4096 reply cap on all provider legs, provider-agnostic truncation note, real provider-error surfacing on empty 200s, trim-before-empty-check, and Custom base-URL normalisation. Byte-identical user-facing text to Android. App-build (Strand macOS + NOOPiOS) green.
@ryanbr
ryanbr merged commit e9ba0f7 into main Aug 5, 2026
3 checks passed
@ryanbr
ryanbr deleted the android-coach-error-crash-robustness branch August 5, 2026 09:23
simoncad7 pushed a commit to simoncad7/noop that referenced this pull request Aug 17, 2026
iOS/macOS parity for the Android AI Coach fixes (ryanbr#1083, tracking ryanbr#1074): 4096 reply cap on all provider legs, provider-agnostic truncation note, real provider-error surfacing on empty 200s, trim-before-empty-check, and Custom base-URL normalisation. Byte-identical user-facing text to Android. App-build (Strand macOS + NOOPiOS) green.
simoncad7 pushed a commit to simoncad7/noop that referenced this pull request Aug 17, 2026
…runcation, real errors, model scan) (ryanbr#1083)

Android AI Coach robustness for ryanbr#1074: crash fix, Disconnect row layout, 4096 reply cap on both legs, provider-agnostic truncation note, real provider-error surfacing on empty 200s, and Custom base-URL normalisation so the model scan resolves. iOS/macOS parity landed in ryanbr#1087.
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.

[WHOOP] Broken UI in Coach settings, context limiting and errors on DeepSeek API

1 participant