Skip to content

Route food-label analysis through Cloud Run proxy#21

Open
eman-cickusic wants to merge 1 commit into
benevolentbandwidth:mainfrom
eman-cickusic:route-analysis-via-proxy
Open

Route food-label analysis through Cloud Run proxy#21
eman-cickusic wants to merge 1 commit into
benevolentbandwidth:mainfrom
eman-cickusic:route-analysis-via-proxy

Conversation

@eman-cickusic

Copy link
Copy Markdown
Contributor

What

Routes the app's food-label analysis through the Cloud Run /analyze proxy so scanning works with no user-supplied LLM key. When no key is saved, requests go to the keyless proxy (Gemini via Vertex/ADC). A saved key still routes to the existing bring-your-own-key (Gemini/OpenAI/Grok/Groq) providers, so power users keep direct control. Result chat is unchanged (still uses a personal key).

Why

The proxy (merged in #20, deployed to b2-ultra-processed/us-east1) runs Gemini under the runtime service account, so users no longer need to paste an API key to analyze a label.

How

  • ProxyFoodLabelLlmWorkflow — implements the existing FoodLabelLlmWorkflow interface. The proxy returns nova + ingredients + allergens + usage in one response, so the single POST /analyze is run once as a de-duplicated in-flight Deferred (keyed by the scan's ingredient text) and all three pipeline stages join it. Because the request runs in a workflow-owned scope, the pipeline's per-stage withTimeout + retry joins the same call instead of firing a second one — important for Cloud Run cold starts. Net: one scan = one /analyze call, token usage counted once. Allergen cache-miss fails loudly (rescan) rather than returning a false "no allergens".
  • SelectingFoodLabelLlmWorkflow — picks proxy (no key) vs BYOK (key present); re-read every call so toggling a key in Settings takes effect on the next scan.
  • PROXY_BASE_URL BuildConfig field, default = the Cloud Run URL, overridable via ZEST_PROXY_BASE_URL in local.properties.
  • Dropped the "missing key" scanner banner/badge and the dead hasApiKey plumbing — scanning is keyless.

Testing

  • ./gradlew :app:testDebugUnitTest31 unit tests pass (6 new: response parsing, single-call across 3 stages, concurrent-stage dedup, upstream-error mapping, and key-based routing). androidTest compiles.

Follow-up (not in this PR)

backend/main.py CORS is allow_origins=["*"] — fine for the app, but worth locking down before broad web exposure.

🤖 Generated with Claude Code

Analysis now works without a user-supplied LLM key: when no key is
saved, requests go to the keyless Cloud Run /analyze proxy (Gemini via
Vertex/ADC). A saved key still routes to the existing BYOK providers.

- ProxyFoodLabelLlmWorkflow: one /analyze POST per scan, sliced across
  the 3 pipeline stages via a de-duplicated in-flight Deferred so the
  pipeline's per-stage timeout+retry joins the same call instead of
  issuing a second one (one scan = one call, correct token accounting).
- SelectingFoodLabelLlmWorkflow: proxy when no key, BYOK when present.
- PROXY_BASE_URL BuildConfig field (ZEST_PROXY_BASE_URL override).
- Drop the "missing key" scanner banner/badge; scanning is keyless.
- Result chat unchanged (still uses a personal key).

Tests: parse, single-call/dedup, error mapping, and key-based routing.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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.

1 participant