Skip to content

fix(agent): refresh model catalog on auth change without full reauth#3655

Draft
posthog[bot] wants to merge 1 commit into
mainfrom
posthog-code/refresh-model-catalog-on-auth-change
Draft

fix(agent): refresh model catalog on auth change without full reauth#3655
posthog[bot] wants to merge 1 commit into
mainfrom
posthog-code/refresh-model-catalog-on-auth-change

Conversation

@posthog

@posthog posthog Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

Problem

Two users reported that Codex disappeared from the model list mid-session, and it only came back after signing out and back in. Another user still had it available at the same time, pointing to a user-session-specific stale-state problem rather than a platform-wide removal.

The model catalog is fetched from the AI gateway /v1/models by fetchGatewayModels / fetchModelsList in @posthog/agent. Both hold module-level in-memory caches keyed by (gatewayUrl, authToken) with a 10-minute TTL and no explicit invalidation. The cache is therefore only busted by TTL expiry or a change of the token half of the key — and a full sign-out/sign-in is precisely what rotates the token. So once a stale (or entitlement-restricted) catalog was cached for a user's token, nothing short of the TTL lapsing or a full reauthentication would refresh it. That matches the reported symptom and the sign-out/in workaround exactly.

Changes

  • Add resetGatewayModelCaches() to @posthog/agent/gateway-models, which drops both in-process model caches.
  • Wire it to auth-state changes: AgentService subscribes via a new onAuthStateChanged method on the AgentAuth port (backed by AuthService's existing StateChanged event), so any auth transition (login, logout, org switch, token refresh) drops the cache. The next picker/config read re-reads the gateway, so a model that becomes available surfaces without a full reauthentication. This mirrors the existing StateChanged-driven cache resets in LlmGatewayService and UsageMonitor.
  • The refetch stays cheap and TTL-cached; AgentService is a process-lifetime singleton, so the subscription never needs tearing down.

How did you test this?

  • Added a regression test in gateway-models.test.ts proving that, for the same token (no reauth), a model marked restricted is served from cache, then reappears as allowed after resetGatewayModelCaches() forces a re-read. Runs for both fetchGatewayModels and fetchModelsList.
  • pnpm --filter @posthog/agent exec vitest run src/gateway-models.test.ts — 34 passed.
  • pnpm --filter @posthog/workspace-server exec vitest run for agent.test.ts + auth-adapter.test.ts — 46 passed.
  • pnpm --filter @posthog/agent --filter @posthog/workspace-server --filter @posthog/core typecheck and pnpm --filter code typecheck — clean.
  • Biome lint clean on all changed files.

Automatic notifications

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

Created with PostHog Code from this inbox report.

The gateway model caches (fetchGatewayModels / fetchModelsList) are
module-level singletons keyed by (gatewayUrl, authToken) with a 10-minute
TTL and no explicit invalidation. They were only busted by TTL expiry or a
change of the token half of the key — which is exactly what a full
sign-out/sign-in does. So when a model's availability changed for a user
mid-session (e.g. Codex), the stale catalog could keep hiding it until the
user fully signed out and back in.

Add resetGatewayModelCaches() and wire it to auth-state changes via the
AgentAuth port, so any auth transition drops the cache and the next
picker/config read re-reads the gateway — a model that becomes available
surfaces without a full reauthentication. Mirrors the existing
StateChanged-driven cache reset in LlmGatewayService / UsageMonitor.

Adds a regression test proving the catalog refreshes for the same token
after a reset (i.e. without a token change).

Generated-By: PostHog Code
Task-Id: f2a3c85e-350e-4ec6-b482-3b663cab9d2c
@trunk-io

trunk-io Bot commented Jul 21, 2026

Copy link
Copy Markdown

Merging to main in this repository is managed by Trunk.

  • To merge this pull request, check the box to the left or comment /trunk merge below.

After your PR is submitted to the merge queue, this comment will be automatically updated with its status. If the PR fails, failure details will also be posted here

@github-actions

Copy link
Copy Markdown

React Doctor found no issues in the changed files. 🎉

Reviewed by React Doctor for commit 160dafb.

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.

0 participants