mirror of
https://github.com/diegosouzapw/OmniRoute.git
synced 2026-08-04 14:22:09 +03:00
feat(providers): link web session guide to provider site (#6316)
Add an Open-provider-site link to the web-session credential guide (+host-extraction test). Integrated into release/v3.8.46.
This commit is contained in:
committed by
GitHub
parent
fb3da7ce98
commit
b796f2b457
@@ -8,6 +8,7 @@
|
||||
|
||||
### ✨ New Features
|
||||
|
||||
- **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)
|
||||
- **feat(cerebras):** add the **Gemma 4 31B** model (`gemma-4-31b`) to the Cerebras registry + pricing table. Regression guard extends `tests/unit/t28-model-catalog-updates.test.ts`. (thanks @backryun)
|
||||
- **feat(providers):** add **Yuanbao (web)** as a cookie-session provider ([#6196](https://github.com/diegosouzapw/OmniRoute/issues/6196)) — `yuanbao-web` (Tencent Yuanbao, `yuanbao.tencent.com`) with cookie-only auth (`hy_user`/`hy_token` + public agent id), SSE→OpenAI translation incl. `reasoning_content`, exposing DeepSeek V3/R1 + Hunyuan / Hunyuan-T1. Regression guard: `tests/unit/providers-yuanbao-web.test.ts`. `together-web` was **deferred** (no verifiable web-session endpoint — needs a captured request) and `huggingchat-web` **dropped** (the existing `huggingchat` already is a web-cookie provider). (thanks @chirag127)
|
||||
- **feat(providers):** route the built-in **agentrouter** through the dynamic Claude-Code wire image ([#6056](https://github.com/diegosouzapw/OmniRoute/issues/6056)) — a small static allow-set (`CC_WIRE_IMAGE_BUILTINS` in `open-sse/services/ccWireImageBuiltins.ts`), consulted by `isClaudeCodeCompatible` / `isClaudeCodeCompatibleProvider` / `applyFingerprint`, makes agentrouter adopt the CC wire-image headers + fingerprint **while guarding the CC baseUrl/auth branches** so it keeps its own registry `baseUrl` and `x-api-key` auth. Regression guard: `tests/unit/agentrouter-cc-wire-image.test.ts` (asserts the wire image is applied AND agentrouter's baseUrl/auth are preserved). Live WAF-acceptance against agentrouter.org is a VPS validation follow-up (Hard Rule #18).
|
||||
|
||||
@@ -31,6 +31,7 @@ import type { ProviderMessageTranslator } from "../providerPageHelpers";
|
||||
interface ProviderInfo {
|
||||
name: string;
|
||||
riskNoticeVariant?: string;
|
||||
website?: string;
|
||||
[key: string]: unknown;
|
||||
}
|
||||
|
||||
@@ -277,6 +278,7 @@ export default function ProviderModalsPanel({
|
||||
isOpen={showAddApiKeyModal}
|
||||
provider={providerId}
|
||||
providerName={providerInfo.name}
|
||||
providerWebsite={providerInfo.website}
|
||||
initialBaseUrl={siliconFlowInitialBaseUrl}
|
||||
isCompatible={isCompatible}
|
||||
isAnthropic={isAnthropicProtocolCompatible}
|
||||
@@ -312,6 +314,7 @@ export default function ProviderModalsPanel({
|
||||
isOpen={showEditModal}
|
||||
connection={selectedConnection}
|
||||
providerId={providerId}
|
||||
providerWebsite={providerInfo.website}
|
||||
onSave={handleUpdateConnection}
|
||||
onResyncModels={(id) => handleCompatibleImportWithProgress(id, "sync")}
|
||||
onClose={() => setShowEditModal(false)}
|
||||
|
||||
@@ -10,14 +10,30 @@ import { providerText, type ProviderMessageTranslator } from "../providerPageHel
|
||||
export interface WebSessionCredentialGuideProps {
|
||||
requirement: WebSessionCredentialRequirement;
|
||||
providerName: string;
|
||||
providerWebsite?: string;
|
||||
t: ProviderMessageTranslator;
|
||||
}
|
||||
|
||||
export function getProviderWebsiteHost(providerWebsite?: string): string | null {
|
||||
if (!providerWebsite) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return new URL(providerWebsite).host;
|
||||
} catch {
|
||||
return providerWebsite;
|
||||
}
|
||||
}
|
||||
|
||||
export default function WebSessionCredentialGuide({
|
||||
requirement,
|
||||
providerName,
|
||||
providerWebsite,
|
||||
t,
|
||||
}: WebSessionCredentialGuideProps) {
|
||||
const providerWebsiteHost = getProviderWebsiteHost(providerWebsite);
|
||||
|
||||
if (requirement.kind === "none") {
|
||||
return (
|
||||
<div className="rounded-lg border border-emerald-500/25 bg-emerald-500/10 px-3 py-3 text-sm text-text-muted">
|
||||
@@ -76,6 +92,21 @@ export default function WebSessionCredentialGuide({
|
||||
{providerText(t, "webSessionGuideStep1", "Sign in to {provider} in your browser.", {
|
||||
provider: providerName,
|
||||
})}
|
||||
{providerWebsite && providerWebsiteHost && (
|
||||
<a
|
||||
href={providerWebsite}
|
||||
target="_blank"
|
||||
rel="noopener noreferrer"
|
||||
className="ml-2 inline-flex items-center gap-1 text-primary hover:underline"
|
||||
>
|
||||
{providerText(t, "webSessionGuideOpenProvider", "Open {host}", {
|
||||
host: providerWebsiteHost,
|
||||
})}
|
||||
<span className="material-symbols-outlined text-[14px]" aria-hidden="true">
|
||||
open_in_new
|
||||
</span>
|
||||
</a>
|
||||
)}
|
||||
</li>
|
||||
<li>
|
||||
{providerText(
|
||||
|
||||
@@ -34,6 +34,7 @@ export interface AddApiKeyModalProps {
|
||||
isOpen: boolean;
|
||||
provider?: string;
|
||||
providerName?: string;
|
||||
providerWebsite?: string;
|
||||
initialBaseUrl?: string;
|
||||
isCompatible?: boolean;
|
||||
isAnthropic?: boolean;
|
||||
@@ -56,6 +57,7 @@ export default function AddApiKeyModal({
|
||||
isOpen,
|
||||
provider,
|
||||
providerName,
|
||||
providerWebsite,
|
||||
initialBaseUrl,
|
||||
isCompatible,
|
||||
isAnthropic,
|
||||
@@ -657,6 +659,7 @@ export default function AddApiKeyModal({
|
||||
<WebSessionCredentialGuide
|
||||
requirement={webSessionCredential}
|
||||
providerName={providerDisplayName}
|
||||
providerWebsite={providerWebsite}
|
||||
t={t}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -72,6 +72,7 @@ export interface EditConnectionModalProps {
|
||||
isOpen: boolean;
|
||||
connection: EditConnectionModalConnection | null;
|
||||
providerId: string;
|
||||
providerWebsite?: string;
|
||||
onSave: (data: unknown) => Promise<void | unknown>;
|
||||
/** Triggered after a successful save when the "import only free models" flag changed. */
|
||||
onResyncModels?: (connectionId: string) => void | Promise<void>;
|
||||
@@ -84,6 +85,7 @@ export default function EditConnectionModal({
|
||||
isOpen,
|
||||
connection,
|
||||
providerId,
|
||||
providerWebsite,
|
||||
onSave,
|
||||
onResyncModels,
|
||||
onClose,
|
||||
@@ -795,6 +797,7 @@ export default function EditConnectionModal({
|
||||
<WebSessionCredentialGuide
|
||||
requirement={webSessionCredential}
|
||||
providerName={providerDisplayName}
|
||||
providerWebsite={providerWebsite}
|
||||
t={t}
|
||||
/>
|
||||
)}
|
||||
|
||||
25
tests/unit/web-session-provider-link-6316.test.ts
Normal file
25
tests/unit/web-session-provider-link-6316.test.ts
Normal file
@@ -0,0 +1,25 @@
|
||||
import { test } from "node:test";
|
||||
import assert from "node:assert/strict";
|
||||
|
||||
// #6316: the web-session credential guide shows an "Open {host}" link to the
|
||||
// provider site. The host is derived from the provider's website URL via
|
||||
// getProviderWebsiteHost — a full URL collapses to its host, a bare/invalid
|
||||
// string falls back to itself, and an empty value yields null (no link).
|
||||
const { getProviderWebsiteHost } = await import(
|
||||
"../../src/app/(dashboard)/dashboard/providers/[id]/components/WebSessionCredentialGuide.tsx"
|
||||
);
|
||||
|
||||
test("#6316: full URL collapses to host", () => {
|
||||
assert.equal(getProviderWebsiteHost("https://chat.qwen.ai/path?x=1"), "chat.qwen.ai");
|
||||
assert.equal(getProviderWebsiteHost("https://www.kimi.com"), "www.kimi.com");
|
||||
});
|
||||
|
||||
test("#6316: bare/invalid string falls back to itself", () => {
|
||||
assert.equal(getProviderWebsiteHost("kimi.com"), "kimi.com");
|
||||
assert.equal(getProviderWebsiteHost("not a url"), "not a url");
|
||||
});
|
||||
|
||||
test("#6316: empty/undefined yields null (no link rendered)", () => {
|
||||
assert.equal(getProviderWebsiteHost(undefined), null);
|
||||
assert.equal(getProviderWebsiteHost(""), null);
|
||||
});
|
||||
Reference in New Issue
Block a user