diff --git a/CHANGELOG.md b/CHANGELOG.md index 944637f0d4..a1c24fd0c0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,7 @@ ### ✨ New Features +- **feat(dashboard):** "Add session cookie" modal now shows a prominent **"Open ‹host› →"** link to the provider's own site ([#6268](https://github.com/diegosouzapw/OmniRoute/issues/6268)) — every `-web` cookie-session provider (chatgpt-web, claude-web, gemini-web, kimi-web, lmarena, qwen-web, m365-copilot-web, …) renders a one-click external link (opening the provider's login/home page in a new tab) so operators no longer tab away to retype the URL mid-setup. The host resolves from a pure, unit-tested `resolveWebProviderHost()` (prefers `WEB_COOKIE_PROVIDERS[id].website`, falls back to the registry `baseUrl` origin); non-web providers render exactly as before. Kilo's dup flag vs #6265 (modal-too-small-on-1080p) was a false positive — distinct concern. Regression guard: `tests/unit/resolve-web-provider-host.test.ts` (5). (thanks @chirag127) - **feat(providers):** add **DigitalOcean** AI (serverless inference) as an OpenAI-compatible API-key provider — base `https://inference.do-ai.run/v1`, wired through the shared OpenAI-compatible registry with full model passthrough (`open-sse/config/providers/registry/digitalocean/`, `src/shared/constants/providers/apikey/inference-hosts.ts`). Regression guard: `tests/unit/digitalocean-provider.test.ts`. (thanks @newnol) - **feat(providers):** add **Huancheng Public API** (`hcnsec`) as an OpenAI-compatible regional provider — Xinjiang Huancheng Cybersecurity's public LLM platform (base `https://api.hcnsec.cn/v1`, free credits via daily check-ins), wired through the shared OpenAI-compatible registry with full model passthrough (`open-sse/config/providers/registry/hcnsec/`, `src/shared/constants/providers/apikey/regional.ts`). Regression guard: `tests/unit/hcnsec-provider.test.ts`. (thanks @UnrealAryan) - **feat(dashboard):** the web-session credential guide now shows an **"Open {host}" link** to the provider's sign-in site (derived from the provider `website` via `getProviderWebsiteHost`), so you can jump straight to the page where the cookie/session must be captured. Regression guard: `tests/unit/web-session-provider-link-6316.test.ts`. (thanks @jordansilly77-stack) diff --git a/src/app/(dashboard)/dashboard/providers/[id]/components/modals/AddApiKeyModal.tsx b/src/app/(dashboard)/dashboard/providers/[id]/components/modals/AddApiKeyModal.tsx index 3163deee46..ca4a7cfb9c 100644 --- a/src/app/(dashboard)/dashboard/providers/[id]/components/modals/AddApiKeyModal.tsx +++ b/src/app/(dashboard)/dashboard/providers/[id]/components/modals/AddApiKeyModal.tsx @@ -2,7 +2,11 @@ import { useState, useEffect, useRef } from "react"; import { useTranslations } from "next-intl"; import { Button, Badge, Input, Modal, Toggle } from "@/shared/components"; -import { providerAllowsOptionalApiKey, supportsBulkApiKey } from "@/shared/constants/providers"; +import { + providerAllowsOptionalApiKey, + supportsBulkApiKey, + resolveWebProviderHost, +} from "@/shared/constants/providers"; import { parseBulkApiKeys } from "@/shared/utils/bulkApiKeyParser"; import { providerHasFreeModels } from "@/shared/utils/freeModels"; import { @@ -87,6 +91,12 @@ export default function AddApiKeyModal({ const webSessionCredential = getWebSessionCredentialRequirement(provider); const isNoAuthWebSessionCredential = webSessionCredential?.kind === "none"; const isWebSessionCredential = !!webSessionCredential && webSessionCredential.kind !== "none"; + // #6268 — for web-session providers, resolve the provider's public site so the + // modal can offer a prominent "Open ‹host› →" link. Gated on webSessionCredential + // so non-web providers never render a link. + const webProviderHostLink = webSessionCredential + ? resolveWebProviderHost(provider, defaultBaseUrl) + : null; const providerDisplayName = providerName || provider || ""; const apiKeyOptional = providerAllowsOptionalApiKey(provider) || Boolean(isNoAuthWebSessionCredential); @@ -427,6 +437,21 @@ export default function AddApiKeyModal({ onClose={onClose} >
+ {webProviderHostLink && ( + + + {providerText(t, "openWebProviderSite", "Open {host}", { + host: webProviderHostLink.host, + })} + + )} {bulkSupported && (