Skip to content

feat(mobile): fetch available model list from the LLM gateway#2564

Draft
oliverb123 wants to merge 3 commits into
mainfrom
posthog-code/mobile-fetch-models-from-gateway
Draft

feat(mobile): fetch available model list from the LLM gateway#2564
oliverb123 wants to merge 3 commits into
mainfrom
posthog-code/mobile-fetch-models-from-gateway

Conversation

@oliverb123

Copy link
Copy Markdown
Contributor

Problem

On mobile, the available model list was hardcoded in composer/options.ts, so newer models (e.g. 4.8 / 5) never showed up without shipping a new app build. The desktop app already downloads the list from the LLM gateway, so the two clients drifted.

Changes

  • Moved the LLM gateway URL construction and the model fetch/format logic into @posthog/shared (zero-dependency, already a mobile dependency) as the single source of truth; packages/agent now re-exports from it so the desktop path is literally the same code.
  • Mobile fetches the model list from the gateway's /v1/models endpoint via a new useModels hook backed by a persisted cache, mapping models exactly like the desktop app (Anthropic models, gateway-formatted names). A small built-in list remains only as a cold-start / offline fallback so the picker is never empty.

How did you test this?

  • pnpm --filter @posthog/shared test (incl. new gateway URL + model tests) — pass
  • Agent gateway tests (gateway-models, utils/gateway) — pass
  • pnpm --filter agent typecheck and agent build — pass
  • Mobile tsc on touched files (clean), biome on changed files (clean), and vitest run src/features/tasks (84 tests) — pass

Automatic notifications

  • Publish to changelog?
  • Alert Sales and Marketing teams?

Created with PostHog Code from a Slack thread

The mobile app hardcoded its model list in `composer/options.ts`, so new models (e.g. 4.8 / 5) never appeared without shipping a new build. The desktop app instead downloads the catalogue from the LLM gateway's `/v1/models` endpoint.

Move the gateway URL construction and model-fetch/format logic into `@posthog/shared` (zero-dependency, already a mobile dependency) as the single source of truth, and have `packages/agent` re-export from it so the desktop path is literally the same code. Mobile now fetches the list the same way via a `useModels` hook backed by a persisted cache, falling back to a small built-in list only on a cold start or when the gateway is unreachable.

Generated-By: PostHog Code
Task-Id: 89aa4bb4-eaa8-4894-8c4c-3f6b096fc78a
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit cc47f46.

@greptile-apps

greptile-apps Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Comments Outside Diff (2)

  1. apps/mobile/src/features/tasks/hooks/useModels.ts, line 323-328 (link)

    P1 Query key missing cloudRegion — stale models served across region switches

    The query key ["models", "list"] is constant across regions. If a user switches from us to eu (or logs out and back in on a different region), TanStack Query sees the same key and treats the cached US models as fresh for the full 10-minute staleTime. During that window getAvailableModels is not called, so getLlmGatewayUrl(getBaseUrl()) points at the new region's gateway but the old region's model list is displayed. Including cloudRegion in the key fixes this: any region change immediately invalidates the cache and triggers a re-fetch.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: apps/mobile/src/features/tasks/hooks/useModels.ts
    Line: 323-328
    
    Comment:
    **Query key missing `cloudRegion` — stale models served across region switches**
    
    The query key `["models", "list"]` is constant across regions. If a user switches from `us` to `eu` (or logs out and back in on a different region), TanStack Query sees the same key and treats the cached US models as fresh for the full 10-minute `staleTime`. During that window `getAvailableModels` is not called, so `getLlmGatewayUrl(getBaseUrl())` points at the new region's gateway but the old region's model list is displayed. Including `cloudRegion` in the key fixes this: any region change immediately invalidates the cache and triggers a re-fetch.
    
    How can I resolve this? If you propose a fix, please make it concise.
  2. packages/shared/src/gateway-models.test.ts, line 736-746 (link)

    P2 Non-parameterised tests for supportsReasoningEffort and isBlockedModelId

    The getLlmGatewayUrl test in gateway.test.ts already uses it.each (the preferred parameterised style for this repo). The supportsReasoningEffort and isBlockedModelId blocks below group multiple unrelated assertions inside a single it, making failures harder to attribute. Converting them to it.each tables would align with the team's convention and make each case independently named and reportable.

    Prompt To Fix With AI
    This is a comment left during a code review.
    Path: packages/shared/src/gateway-models.test.ts
    Line: 736-746
    
    Comment:
    **Non-parameterised tests for `supportsReasoningEffort` and `isBlockedModelId`**
    
    The `getLlmGatewayUrl` test in `gateway.test.ts` already uses `it.each` (the preferred parameterised style for this repo). The `supportsReasoningEffort` and `isBlockedModelId` blocks below group multiple unrelated assertions inside a single `it`, making failures harder to attribute. Converting them to `it.each` tables would align with the team's convention and make each case independently named and reportable.
    
    How can I resolve this? If you propose a fix, please make it concise.

    Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

Prompt To Fix All With AI
Fix the following 3 code review issues. Work through them one at a time, proposing concise fixes.

---

### Issue 1 of 3
apps/mobile/src/features/tasks/hooks/useModels.ts:323-328
**Query key missing `cloudRegion` — stale models served across region switches**

The query key `["models", "list"]` is constant across regions. If a user switches from `us` to `eu` (or logs out and back in on a different region), TanStack Query sees the same key and treats the cached US models as fresh for the full 10-minute `staleTime`. During that window `getAvailableModels` is not called, so `getLlmGatewayUrl(getBaseUrl())` points at the new region's gateway but the old region's model list is displayed. Including `cloudRegion` in the key fixes this: any region change immediately invalidates the cache and triggers a re-fetch.

### Issue 2 of 3
packages/shared/src/gateway-models.ts:220-222
**Duplicated `MODELS_WITH_EFFORT` set — two sources of truth that must be kept in sync manually**

`supportsReasoningEffort` here and `supportsEffort` in `packages/agent/src/adapters/claude/session/models.ts` both maintain private copies of the same four-model set. The comment even says "keep in sync". Now that this logic lives in `@posthog/shared`, the agent's copy can be deleted and replaced with an import of `supportsReasoningEffort` — removing the manual sync requirement entirely.

```suggestion
// Models that expose a reasoning-effort control.
const MODELS_WITH_EFFORT = new Set([
```

### Issue 3 of 3
packages/shared/src/gateway-models.test.ts:736-746
**Non-parameterised tests for `supportsReasoningEffort` and `isBlockedModelId`**

The `getLlmGatewayUrl` test in `gateway.test.ts` already uses `it.each` (the preferred parameterised style for this repo). The `supportsReasoningEffort` and `isBlockedModelId` blocks below group multiple unrelated assertions inside a single `it`, making failures harder to attribute. Converting them to `it.each` tables would align with the team's convention and make each case independently named and reportable.

Reviews (1): Last reviewed commit: "feat(mobile): fetch available model list..." | Re-trigger Greptile

Comment thread packages/shared/src/gateway-models.ts Outdated
Comment on lines +220 to +222
// Models that expose a reasoning-effort control. Mirrors `MODELS_WITH_EFFORT`
// in packages/agent/src/adapters/claude/session/models.ts — keep in sync.
const MODELS_WITH_EFFORT = new Set([

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Duplicated MODELS_WITH_EFFORT set — two sources of truth that must be kept in sync manually

supportsReasoningEffort here and supportsEffort in packages/agent/src/adapters/claude/session/models.ts both maintain private copies of the same four-model set. The comment even says "keep in sync". Now that this logic lives in @posthog/shared, the agent's copy can be deleted and replaced with an import of supportsReasoningEffort — removing the manual sync requirement entirely.

Suggested change
// Models that expose a reasoning-effort control. Mirrors `MODELS_WITH_EFFORT`
// in packages/agent/src/adapters/claude/session/models.ts — keep in sync.
const MODELS_WITH_EFFORT = new Set([
// Models that expose a reasoning-effort control.
const MODELS_WITH_EFFORT = new Set([
Prompt To Fix With AI
This is a comment left during a code review.
Path: packages/shared/src/gateway-models.ts
Line: 220-222

Comment:
**Duplicated `MODELS_WITH_EFFORT` set — two sources of truth that must be kept in sync manually**

`supportsReasoningEffort` here and `supportsEffort` in `packages/agent/src/adapters/claude/session/models.ts` both maintain private copies of the same four-model set. The comment even says "keep in sync". Now that this logic lives in `@posthog/shared`, the agent's copy can be deleted and replaced with an import of `supportsReasoningEffort` — removing the manual sync requirement entirely.

```suggestion
// Models that expose a reasoning-effort control.
const MODELS_WITH_EFFORT = new Set([
```

How can I resolve this? If you propose a fix, please make it concise.

Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!

- Fix the `quality` (biome ci) failure: organize imports/exports in utils/gateway.ts.
- Address Greptile review: delete the agent's duplicate MODELS_WITH_EFFORT set and have `supportsEffort` delegate to `supportsReasoningEffort` in @posthog/shared, so there's a single source of truth instead of two sets kept in sync manually.

Generated-By: PostHog Code
Task-Id: 89aa4bb4-eaa8-4894-8c4c-3f6b096fc78a
Address Greptile review:
- Include cloudRegion in the useModels query key. The gateway URL is region-derived, so a constant key served the previous region's cached models for the full staleTime window after a region switch.
- Convert the isBlockedModelId and supportsReasoningEffort tests to it.each tables to match the repo's parameterized-test convention.

Generated-By: PostHog Code
Task-Id: 89aa4bb4-eaa8-4894-8c4c-3f6b096fc78a
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