From 95fc84527831a52449b4205403b67ab931905ae9 Mon Sep 17 00:00:00 2001 From: Bruno Perez Date: Wed, 8 Jul 2026 20:07:15 +0200 Subject: [PATCH] feat: pre-fill the Manifest Cloud gateway URL by default --- README.md | 2 +- src/App.tsx | 20 +++++++++++--------- src/providers.ts | 10 ++++++++++ 3 files changed, 22 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index 4bee271..9b6ce9a 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Your API key is held in `sessionStorage` (cleared when you close the tab). Every Open , then: -- **Provider preset** — pick a provider (OpenAI, Anthropic, Mistral, Groq, …) to auto-fill its base URL and wire format, or stay on **Custom / Manifest** to point at your own gateway. Editing the Base URL by hand switches back to Custom. +- **Provider preset** — pick a provider (OpenAI, Anthropic, Mistral, Groq, …) to auto-fill its base URL and wire format. The default, **Custom / Manifest**, pre-fills the Manifest Cloud gateway (`https://app.manifest.build`) — edit the Base URL by hand to point at your own gateway (which switches the pill back to Custom). - **Format** — the wire protocol: OpenAI Chat Completions (`/v1/chat/completions`), OpenAI Responses (`/v1/responses`), or Anthropic Messages (`/v1/messages`). This sets the endpoint path, auth scheme, body shape, and how the response is parsed. - **Base URL** — e.g. `https://your-manifest.example.com`, `https://api.openai.com`, `https://api.anthropic.com`, or `http://localhost:3001` (more on cross-origin below). Wingman appends the format's path. - **API key** — `Authorization: Bearer` for OpenAI-style formats, `x-api-key` for Anthropic (attached automatically per format). diff --git a/src/App.tsx b/src/App.tsx index c1980c4..1c1f904 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -23,6 +23,7 @@ import { PROVIDER_BY_ID, DEFAULT_PROVIDER_ID, CUSTOM_PROVIDER, + MANIFEST_BASE_URL, type Provider, } from './providers'; import { partitionHeaders, sendRequest, sendRequestStreaming, type SendResult } from './send'; @@ -97,17 +98,17 @@ function recordFromEntries(entries: HeaderEntry[]): Record { } function defaultBaseUrl(): string { - // Hosted Wingman has no implicit backend — leave the field empty so the - // user must paste a URL or follow the ?baseUrl= query param. Pre-filling a - // localhost guess on wingman.manifest.build would only produce confusing - // CORS errors. - if (typeof window === 'undefined') return ''; + // Wingman is a Manifest gateway tester first, so default the Base URL to the + // canonical Manifest Cloud gateway — the user shouldn't have to type it. On + // localhost we instead guess the local gateway port so `npm run dev` targets + // a locally-running Manifest. The health badge surfaces reachability / CORS. + if (typeof window === 'undefined') return MANIFEST_BASE_URL; const { protocol, hostname, port } = window.location; if (hostname === 'localhost' || hostname === '127.0.0.1') { if (port === '3002' || port === '3000') return `${protocol}//${hostname}:3001`; return `${protocol}//${hostname}:${port || '3001'}`; } - return ''; + return MANIFEST_BASE_URL; } // An external embed (?baseUrl=…, e.g. the Manifest dashboard drawer) is always @@ -316,8 +317,9 @@ const App: Component = () => { }; // Pick a provider preset: switch to its wire format and, for a concrete - // provider, fill the base URL + a usable default model. Selecting "Custom" - // resets to Manifest/BYO defaults so the user can type their own endpoint. + // provider, fill the base URL + a usable default model. Selecting "Custom / + // Manifest" resets to the Manifest gateway defaults (base URL pre-filled, the + // `auto` router model) — the field stays free-text for a BYO endpoint. const selectProvider = (id: string) => { const preset = PROVIDER_BY_ID[id]; if (!preset || id === providerId()) return; @@ -325,7 +327,7 @@ const App: Component = () => { writeStorage(STORAGE.provider, id); setFormatSafely(preset.formatId); if (preset.id === DEFAULT_PROVIDER_ID) { - persistAndSetBase(''); + persistAndSetBase(defaultBaseUrl()); persistAndSetModel('auto'); } else { persistAndSetBase(preset.baseUrl); diff --git a/src/providers.ts b/src/providers.ts index ef8e33a..15bac23 100644 --- a/src/providers.ts +++ b/src/providers.ts @@ -49,6 +49,16 @@ export interface Provider { /** The default preset: today's behaviour (free-text base URL → Manifest). */ export const DEFAULT_PROVIDER_ID = 'custom'; +/** + * Canonical Manifest Cloud gateway. Pre-filled as the default Base URL on the + * hosted app so the primary use case — testing a Manifest gateway — works + * without typing (or mistyping) the host. Note it's `app.manifest.build`, not + * `api.manifest.build`: the latter has no TLS cert. This host speaks the + * OpenAI/Anthropic-compatible wire format (`{host}/v1/chat/completions`, + * `{host}/v1/messages`). Source: manifest.build llms.txt. + */ +export const MANIFEST_BASE_URL = 'https://app.manifest.build'; + export const PROVIDERS: readonly Provider[] = [ { id: 'custom',