Skip to content

Search is only available in production builds. Try building and previewing the site to test it out locally.

Models & API keys

The Models page (/space/models) is the control center for the model catalog and your BYOK keys. Three tabs: Model Catalog, API Keys & Providers, and Global Settings.

New to the AI side? Read AI concepts from scratch first — Tokens, The context window, Sampling parameters and Reasoning, which this page’s knobs control.

This page is where you steer the underlying AI mechanics:

  • Context window (shown in the model detail panel) is how many tokens a model can read in a single request. Pricing is per token (input/output/cache). A larger window lets you feed more history + memory + retrieved docs, but costs more — so the catalog shows both, and the contextLimit setting controls how much actually gets sent.
  • Sampling knobs (temperature, top-p, top-k, penalties in Global Settings) decide the randomness/creativity of output — the difference between a dry answer and a creative one.
  • Reasoning capability (derived per model, deriveReasoningCapability) tells you whether a model thinks before answering, and getThinkingControl maps your thinking level to the provider’s reasoning-effort parameter. Reasoning models spend extra tokens thinking — faster at hard problems, pricier in latency and token cost.

The full mental model is in AI concepts from scratch.

The catalog is synced with models.dev (src/lib/models-registry.ts) — a live index of models and providers with pricing, context windows and release dates, served through /api/models/catalog with pagination (limit / offset), provider filter, full-text search (q), reasoning/vision filters and sorting (featured, name, context, price, release).

  • Provider sidebar — filter by provider with per-provider model counts and reasoning counts.
  • Model list — search across thousands of models, toggle availability (usable in chat = you have a key for that provider) and reasoning/vision badges.
  • Detail panel — full specs: context window, pricing per million tokens (input/output/cache), release date, reasoning capability (deriveReasoningCapability), and thinking control (getThinkingControl).
  • Infinite scroll — “Load N more” pagination with de-duplication.

BYOK works with any provider in src/lib/models.ts (PROVIDERS). The full list: OpenAI, Anthropic, Google Gemini, Groq, xAI (Grok), DeepSeek, Mistral, OpenRouter, Perplexity, Cerebras, Cohere, Azure, Mimo, Kimi (Moonshot), Z.AI, Qwen, plus local engines Ollama and LM Studio and any OpenAI-compatible endpoint. Every provider requires its own API key except platform-managed integrations.

Pricing principle: SynthHires does not resell model access or bundle tokens. The billing relationship is between you and the provider; the platform is the orchestration surface. That is the BYOK contract.

detectProviderFromKey (in settings-panel.tsx) guesses the provider from the key prefix, and keyInputsFor renders the correct input for each provider (API key vs Azure resource config). External key URLs are provided per provider (OpenAI platform, Anthropic console, Google AI Studio, Groq console, etc.).

All keys are stored in the encrypted local vault:

  • Storage: synthhires-credentials (vault) + synthhires-credentials:mirror (crash-safe mirror) in localStorage, plus synthhires-tokens for service tokens.
  • Encryption: AES-256-GCM. The key derives from a device salt (getOrCreateVaultSalt) and optionally a server-side secret (VAULT_KDF_SECRET) for hardened v2 blobs; legacy v1 blobs are still readable.
  • Envelopes: v2 blobs are prefixed v2:; decrypt attempts fall back across versions and known dev secrets, and self-heal by re-encrypting on the next save if a stale secret was used.
  • Cloud sync (optional): per-provider opt-in (synthhires:vault:cloud-sync-opt-in) pushes the key to /api/vault (server-side vault_entries). Only opted-in providers migrate; keys never leave the device without explicit consent.

For each chat request, the client builds a single-use handoff envelope (buildVaultHandoff): the plaintext key is wrapped with the server’s public E2EE JWK (/api/handoff-pubkey), stamped with an expiry, and sent to /api/chat. The server unwraps it for the duration of that request only — your key is never stored or logged server-side in plaintext.

Global inference parameters are persisted client-side and apply across conversations:

Setting Key Default
System instruction synthhires:systemInstruction You are a helpful AI assistant. Today is {local_date}, local time is {local_time}.
Streaming synthhires:streamResponse true
Context limit synthhires:contextLimit all
Temperature synthhires:globalParams 0.7
Max tokens synthhires:globalParams empty (provider default)
Top-P synthhires:globalParams 1
Top-K synthhires:globalParams 0
Presence / frequency penalty synthhires:globalParams 0
Enabled models synthhires:enabledModels GPT-4o, Claude Sonnet 4, Gemini 2.5 Pro, Gemini 2.0 Flash, DeepSeek V4 Pro

“Reset all” restores the defaults with a double-confirm. Per-conversation overrides (model, provider, thinking level) still take precedence over globals.

src/lib/thinking.ts derives a model’s reasoning capability (never / optional / always) and computes the correct thinking-control parameter per provider — so a high thinking level maps to the right reasoning-effort knob whether you’re on OpenAI, Anthropic, Gemini or DeepSeek.

Conceptually this is reasoning-effort abstraction: each provider names this knob differently (OpenAI’s reasoning_effort, Gemini’s thinking, DeepSeek’s deep-think), so the platform normalizes your off/low/medium/high choice into the value each provider expects — without you caring which model or company is on the other end.