Skip to content

feat: dynamic model list via browser-captured ListModels RPC #249

Description

@CharoenwitKunna

Problem

The model list is hardcoded in configs/models.json (currently 30 models). When Google adds new models (e.g. gemini-3.7-flash, robotics-er-2-preview), users must manually edit this file and restart the server.

Additionally, the generativelanguage.googleapis.com/v1beta/models endpoint returns 403 API_KEY_SERVICE_BLOCKED when called from the browser context, making direct model discovery unreliable.

Proposed Solution

Auto-fetch the model list at runtime from the same ListModels RPC endpoint that the AI Studio app calls on page load, via page.on('response') capture in BrowserManager.

Key changes:

  • BrowserManager: hook page.on('response') before page.goto to capture the app's own ListModels response + request headers (URL, API key)
  • BrowserManager.fetchLiveModels(): return captured models (with configurable TTL), falling back to a manual RPC call using the captured URL/headers
  • BrowserManager._parseListModelsResponse(): parse the [[ [...], ... ]] protobuf+JSON array into models.json-compatible objects
  • ConfigLoader: add DYNAMIC_MODELS (default true) and DYNAMIC_MODELS_TTL (default 3600000 ms) env vars
  • ProxyServerSystem: make GET /v1/models and GET /v1beta/models async, call fetchLiveModels() with static config as fallback
  • ProxyServerSystem: add POST /api/models/refresh?persist=true endpoint for manual refresh

Benefits

  • No hardcoded domain/key — auto-discovered from the browser's own captured request
  • Works even if Google rotates the CoJqbf backend domain or API key
  • Zero-config — enabled by default, models update automatically on next request after TTL expires
  • Backward compatible — DYNAMIC_MODELS=false reverts to static configs/models.json

Testing

With DYNAMIC_MODELS=true and empty configs/models.json ({"models":[]}):

  • Server fetches 36 live models via captured ListModels RPC
  • GET /v1beta/models returns all 36 models
  • Without capture fallback, auto-detects base URL from page config (CoJqbf) and API key from page scripts

Environment

  • Node.js on Windows
  • Playwright with Camoufox (Firefox)
  • AI Studio Build App with Google account auth

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions