Revert Kimi partnership UI, restore daily limit survey (#663)

* docs: add uBlock Origin install info to getting started and ad-blocking pages

Chrome dropped support for the full uBlock Origin extension — highlight
that BrowserOS brings it back and make it easy to install from both the
getting started guide and the dedicated ad-blocking page.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* feat: revert Kimi partnership UI, restore daily limit survey

Remove Kimi/Moonshot AI partnership branding from the rate limit
banner, provider card, provider templates, and LLM hub. Restore
the original survey CTA on daily limit errors. Moonshot AI remains
as a regular provider template without the "Recommended" badge.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

* fix: address Greptile review comments

- Guard survey CTA with !isCreditsExhausted to avoid showing it for
  credits-exhausted users who already see "View Usage & Billing"
- Remove dead kimi-launch feature flag files (kimi-launch.ts,
  useKimiLaunch.ts)
- Remove unused KIMI_RATE_LIMIT analytics events
- Remove VITE_PUBLIC_KIMI_LAUNCH from env schema and .env.example

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>

---------

Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Felarof
2026-04-08 16:39:00 -07:00
committed by GitHub
parent 412386b489
commit df7873562d
14 changed files with 64 additions and 180 deletions

View File

@@ -3,13 +3,17 @@ title: "Ad Blocking"
description: "BrowserOS supports full ad blocking with uBlock Origin" description: "BrowserOS supports full ad blocking with uBlock Origin"
--- ---
BrowserOS supports full ad blocking through [uBlock Origin](https://ublockorigin.com/), the most effective open-source ad blocker available. BrowserOS supports full ad blocking through [uBlock Origin](https://ublockorigin.com/), the most powerful open-source ad blocker available — the full extension, not the watered-down "Lite" version.
## How It Works ## Why BrowserOS?
Chrome has been [phasing out support](https://developer.chrome.com/docs/extensions/develop/migrate/mv2-deprecation-timeline) for Manifest V2 extensions, which uBlock Origin relies on for its full blocking capabilities. We re-enabled Manifest V2 support in BrowserOS so uBlock Origin can run at full power. Chrome [killed support](https://developer.chrome.com/docs/extensions/develop/migrate/mv2-deprecation-timeline) for uBlock Origin by phasing out Manifest V2 extensions. The only option left on Chrome is "uBlock Origin Lite," a significantly weaker version that can't use advanced filtering rules.
Install it from the Chrome Web Store: [uBlock Origin](https://chromewebstore.google.com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm) **BrowserOS re-enabled full Manifest V2 support**, so you can install and run the original uBlock Origin at full power — the same extension Chrome no longer allows.
<Card title="Install uBlock Origin" icon="shield-check" href="https://chromewebstore.google.com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm">
Install the full uBlock Origin extension from the Chrome Web Store. Works on BrowserOS out of the box.
</Card>
## BrowserOS vs Chrome ## BrowserOS vs Chrome

View File

@@ -42,6 +42,10 @@ Welcome to BrowserOS! Let's get you set up.
## You're all set! ## You're all set!
<Tip>
**Block ads with uBlock Origin** — Chrome dropped support for the full uBlock Origin extension, but BrowserOS brought it back. [Install it from the Chrome Web Store](https://chromewebstore.google.com/detail/ublock-origin/cjpalhdlnbpafiamejdnhcphjbkeiagm) and browse ad-free. [Learn more →](/features/ad-blocking)
</Tip>
Explore what BrowserOS can do: Explore what BrowserOS can do:
<Columns cols={2}> <Columns cols={2}>

View File

@@ -15,9 +15,6 @@ VITE_PUBLIC_SENTRY_DSN=
# BrowserOS API URL # BrowserOS API URL
VITE_PUBLIC_BROWSEROS_API=https://api.browseros.com VITE_PUBLIC_BROWSEROS_API=https://api.browseros.com
# Launch feature flags
VITE_PUBLIC_KIMI_LAUNCH=false
# GraphQL Schema Path (optional — falls back to schema/schema.graphql) # GraphQL Schema Path (optional — falls back to schema/schema.graphql)
GRAPHQL_SCHEMA_PATH= GRAPHQL_SCHEMA_PATH=

View File

@@ -61,7 +61,6 @@ import {
KIMI_API_KEY_GUIDE_CLICKED_EVENT, KIMI_API_KEY_GUIDE_CLICKED_EVENT,
MODEL_SELECTED_EVENT, MODEL_SELECTED_EVENT,
} from '@/lib/constants/analyticsEvents' } from '@/lib/constants/analyticsEvents'
import { useKimiLaunch } from '@/lib/feature-flags/useKimiLaunch'
import { import {
getDefaultBaseUrlForProviders, getDefaultBaseUrlForProviders,
getProviderTemplate, getProviderTemplate,
@@ -226,7 +225,6 @@ export const NewProviderDialog: FC<NewProviderDialogProps> = ({
const modelListRef = useRef<HTMLDivElement>(null) const modelListRef = useRef<HTMLDivElement>(null)
const { supports } = useCapabilities() const { supports } = useCapabilities()
const { baseUrl: agentServerUrl } = useAgentServerUrl() const { baseUrl: agentServerUrl } = useAgentServerUrl()
const kimiLaunch = useKimiLaunch()
const filteredProviderTypeOptions = providerTypeOptions.filter((opt) => { const filteredProviderTypeOptions = providerTypeOptions.filter((opt) => {
if (opt.value === 'chatgpt-pro') if (opt.value === 'chatgpt-pro')
@@ -234,8 +232,6 @@ export const NewProviderDialog: FC<NewProviderDialogProps> = ({
if (opt.value === 'github-copilot') if (opt.value === 'github-copilot')
return supports(Feature.GITHUB_COPILOT_SUPPORT) return supports(Feature.GITHUB_COPILOT_SUPPORT)
if (opt.value === 'qwen-code') return supports(Feature.QWEN_CODE_SUPPORT) if (opt.value === 'qwen-code') return supports(Feature.QWEN_CODE_SUPPORT)
if (opt.value === 'moonshot')
return kimiLaunch || initialValues?.type === 'moonshot'
if (opt.value === 'openai-compatible') { if (opt.value === 'openai-compatible') {
return supports(Feature.OPENAI_COMPATIBLE_SUPPORT) return supports(Feature.OPENAI_COMPATIBLE_SUPPORT)
} }

View File

@@ -2,7 +2,6 @@ import { Check, Loader2, Trash2 } from 'lucide-react'
import type { FC } from 'react' import type { FC } from 'react'
import { Badge } from '@/components/ui/badge' import { Badge } from '@/components/ui/badge'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { useKimiLaunch } from '@/lib/feature-flags/useKimiLaunch'
import { BrowserOSIcon, ProviderIcon } from '@/lib/llm-providers/providerIcons' import { BrowserOSIcon, ProviderIcon } from '@/lib/llm-providers/providerIcons'
import type { LlmProviderConfig } from '@/lib/llm-providers/types' import type { LlmProviderConfig } from '@/lib/llm-providers/types'
import { cn } from '@/lib/utils' import { cn } from '@/lib/utils'
@@ -30,7 +29,6 @@ export const ProviderCard: FC<ProviderCardProps> = ({
isTesting = false, isTesting = false,
}) => { }) => {
const inputId = `provider-${provider.id}` const inputId = `provider-${provider.id}`
const kimiLaunch = useKimiLaunch()
return ( return (
<label <label
@@ -79,30 +77,21 @@ export const ProviderCard: FC<ProviderCardProps> = ({
</Badge> </Badge>
)} )}
</div> </div>
{isBuiltIn && provider.type === 'browseros' && kimiLaunch && (
<span className="mb-1 inline-block rounded-full border border-orange-300/60 bg-orange-100/70 px-3 py-0.5 font-semibold text-orange-700 text-xs dark:border-orange-400/40 dark:bg-orange-500/15 dark:text-orange-300">
In partnership with Moonshot AI
</span>
)}
<p className="truncate text-muted-foreground text-sm"> <p className="truncate text-muted-foreground text-sm">
{isBuiltIn ? ( {isBuiltIn ? (
kimiLaunch ? ( <>
'Extended usage limits for the next 2 weeks!' BrowserOS-hosted model with strict rate limits.{' '}
) : ( <a
<> href="https://docs.browseros.com/features/bring-your-own-llm"
BrowserOS-hosted model with strict rate limits.{' '} target="_blank"
<a rel="noopener noreferrer"
href="https://docs.browseros.com/features/bring-your-own-llm" className="underline hover:text-foreground"
target="_blank" onClick={(e) => e.stopPropagation()}
rel="noopener noreferrer" >
className="underline hover:text-foreground" Bring your own key
onClick={(e) => e.stopPropagation()} </a>{' '}
> for better performance.
Bring your own key </>
</a>{' '}
for better performance.
</>
)
) : provider.baseUrl ? ( ) : provider.baseUrl ? (
`${provider.modelId}${provider.baseUrl}` `${provider.modelId}${provider.baseUrl}`
) : ( ) : (

View File

@@ -7,7 +7,6 @@ import {
} from '@/components/ui/collapsible' } from '@/components/ui/collapsible'
import { Feature } from '@/lib/browseros/capabilities' import { Feature } from '@/lib/browseros/capabilities'
import { useCapabilities } from '@/lib/browseros/useCapabilities' import { useCapabilities } from '@/lib/browseros/useCapabilities'
import { useKimiLaunch } from '@/lib/feature-flags/useKimiLaunch'
import { import {
type ProviderTemplate, type ProviderTemplate,
providerTemplates, providerTemplates,
@@ -23,7 +22,6 @@ export const ProviderTemplatesSection: FC<ProviderTemplatesSectionProps> = ({
onUseTemplate, onUseTemplate,
}) => { }) => {
const { supports } = useCapabilities() const { supports } = useCapabilities()
const kimiLaunch = useKimiLaunch()
const filteredTemplates = providerTemplates.filter((template) => { const filteredTemplates = providerTemplates.filter((template) => {
if (template.id === 'chatgpt-pro') if (template.id === 'chatgpt-pro')
@@ -31,7 +29,6 @@ export const ProviderTemplatesSection: FC<ProviderTemplatesSectionProps> = ({
if (template.id === 'github-copilot') if (template.id === 'github-copilot')
return supports(Feature.GITHUB_COPILOT_SUPPORT) return supports(Feature.GITHUB_COPILOT_SUPPORT)
if (template.id === 'qwen-code') return supports(Feature.QWEN_CODE_SUPPORT) if (template.id === 'qwen-code') return supports(Feature.QWEN_CODE_SUPPORT)
if (template.id === 'moonshot') return kimiLaunch
if (template.id === 'openai-compatible') { if (template.id === 'openai-compatible') {
return supports(Feature.OPENAI_COMPATIBLE_SUPPORT) return supports(Feature.OPENAI_COMPATIBLE_SUPPORT)
} }
@@ -67,7 +64,6 @@ export const ProviderTemplatesSection: FC<ProviderTemplatesSectionProps> = ({
<ProviderTemplateCard <ProviderTemplateCard
key={template.id} key={template.id}
template={template} template={template}
highlighted={template.id === 'moonshot'}
isNew={isNew} isNew={isNew}
onUseTemplate={onUseTemplate} onUseTemplate={onUseTemplate}
/> />

View File

@@ -2,8 +2,6 @@ import { Globe2, Trash2 } from 'lucide-react'
import type { FC } from 'react' import type { FC } from 'react'
import { useMemo } from 'react' import { useMemo } from 'react'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
import { useKimiLaunch } from '@/lib/feature-flags/useKimiLaunch'
import { cn } from '@/lib/utils'
import { getFaviconUrl, type LlmHubProvider } from './models' import { getFaviconUrl, type LlmHubProvider } from './models'
interface HubProviderRowProps { interface HubProviderRowProps {
@@ -20,20 +18,9 @@ export const HubProviderRow: FC<HubProviderRowProps> = ({
onDelete, onDelete,
}) => { }) => {
const iconUrl = useMemo(() => getFaviconUrl(provider.url), [provider.url]) const iconUrl = useMemo(() => getFaviconUrl(provider.url), [provider.url])
const kimiLaunch = useKimiLaunch()
const normalizedName = provider.name.trim().toLowerCase()
const normalizedUrl = provider.url.trim().toLowerCase()
const isKimi = normalizedName === 'kimi' || normalizedUrl.includes('kimi.com')
const showKimiFlare = isKimi && kimiLaunch
return ( return (
<div <div className="group flex w-full items-center gap-4 rounded-xl border border-border bg-card p-4 transition-all hover:border-[var(--accent-orange)] hover:shadow-md">
className={cn(
'group flex w-full items-center gap-4 rounded-xl border border-border bg-card p-4 transition-all hover:border-[var(--accent-orange)] hover:shadow-md',
showKimiFlare &&
'border-orange-300/80 bg-orange-50/20 shadow-sm ring-1 ring-orange-300/45 dark:bg-orange-500/5',
)}
>
<div className="flex h-10 w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted"> <div className="flex h-10 w-10 shrink-0 items-center justify-center overflow-hidden rounded-lg bg-muted">
{iconUrl ? ( {iconUrl ? (
<img <img
@@ -49,16 +36,6 @@ export const HubProviderRow: FC<HubProviderRowProps> = ({
<div className="min-w-0 flex-1"> <div className="min-w-0 flex-1">
<div className="mb-0.5 flex items-center gap-2"> <div className="mb-0.5 flex items-center gap-2">
<span className="block truncate font-semibold">{provider.name}</span> <span className="block truncate font-semibold">{provider.name}</span>
{showKimiFlare && (
<div className="flex flex-wrap items-center gap-1">
<span className="rounded-full border border-orange-300/60 bg-orange-100/70 px-2 py-0.5 font-semibold text-[11px] text-orange-700 dark:border-orange-400/40 dark:bg-orange-500/15 dark:text-orange-300">
Recommended
</span>
<span className="rounded-full border border-orange-300/60 bg-orange-100/60 px-2.5 py-0.5 font-medium text-orange-700 text-xs dark:border-orange-400/40 dark:bg-orange-500/15 dark:text-orange-300">
Powered by Moonshot AI
</span>
</div>
)}
</div> </div>
<p className="truncate text-muted-foreground/70 text-xs"> <p className="truncate text-muted-foreground/70 text-xs">
{provider.url} {provider.url}

View File

@@ -1,20 +1,18 @@
import { AlertCircle, RefreshCw } from 'lucide-react' import { AlertCircle, RefreshCw } from 'lucide-react'
import type { FC } from 'react' import type { FC } from 'react'
// import { useMemo } from 'react' import { useMemo } from 'react'
import { Button } from '@/components/ui/button' import { Button } from '@/components/ui/button'
// --- Commented out for Kimi partnership launch (restore after) --- const SURVEY_DIRECTIONS = [
// const SURVEY_DIRECTIONS = [ 'competitor',
// 'competitor', 'switching',
// 'switching', 'workflow',
// 'workflow', 'activation',
// 'activation', ] as const
// ] as const
// function pickRandomDirection(): string {
// function pickRandomDirection(): string { return SURVEY_DIRECTIONS[Math.floor(Math.random() * SURVEY_DIRECTIONS.length)]
// return SURVEY_DIRECTIONS[Math.floor(Math.random() * SURVEY_DIRECTIONS.length)] }
// }
// --- End commented out survey code ---
interface ChatErrorProps { interface ChatErrorProps {
error: Error error: Error
@@ -95,13 +93,11 @@ export const ChatError: FC<ChatErrorProps> = ({
const { text, url, isRateLimit, isCreditsExhausted, isConnectionError } = const { text, url, isRateLimit, isCreditsExhausted, isConnectionError } =
parseErrorMessage(error.message, providerType) parseErrorMessage(error.message, providerType)
// --- Commented out for Kimi partnership launch (restore after) --- const surveyUrl = useMemo(
// const surveyUrl = useMemo( () =>
// () => `/app.html?page=survey&maxTurns=20&experimentId=daily_limit_${pickRandomDirection()}#/settings/survey`,
// `/app.html?page=survey&maxTurns=20&experimentId=daily_limit_${pickRandomDirection()}#/settings/survey`, [],
// [], )
// )
// --- End commented out survey code ---
const getTitle = () => { const getTitle = () => {
if (isRateLimit) return 'Daily limit reached' if (isRateLimit) return 'Daily limit reached'
@@ -126,8 +122,17 @@ export const ChatError: FC<ChatErrorProps> = ({
View troubleshooting guide View troubleshooting guide
</a> </a>
)} )}
{/* --- Commented out for Kimi partnership launch (restore after) --- {isCreditsExhausted && url && (
{isRateLimit && ( <a
href={url}
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground text-xs underline hover:text-foreground"
>
View Usage & Billing
</a>
)}
{isRateLimit && !isCreditsExhausted && (
<p className="text-muted-foreground text-xs"> <p className="text-muted-foreground text-xs">
<a <a
href={url} href={url}
@@ -148,27 +153,6 @@ export const ChatError: FC<ChatErrorProps> = ({
</a> </a>
</p> </p>
)} )}
--- End commented out survey code --- */}
{isCreditsExhausted && url && (
<a
href={url}
target="_blank"
rel="noopener noreferrer"
className="text-muted-foreground text-xs underline hover:text-foreground"
>
View Usage & Billing
</a>
)}
{isRateLimit && providerType === 'browseros' && (
<a
href="/app.html#/settings/ai"
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1.5 rounded-md border border-[var(--accent-orange)] bg-[var(--accent-orange)]/10 px-3 py-1.5 font-medium text-[var(--accent-orange)] text-xs transition-colors hover:bg-[var(--accent-orange)]/20"
>
Add your own provider for unlimited usage
</a>
)}
{onRetry && ( {onRetry && (
<Button <Button
variant="outline" variant="outline"

View File

@@ -280,14 +280,6 @@ export const KIMI_API_KEY_CONFIGURED_EVENT = 'settings.kimi.api_key_configured'
export const KIMI_API_KEY_GUIDE_CLICKED_EVENT = export const KIMI_API_KEY_GUIDE_CLICKED_EVENT =
'settings.kimi.api_key_guide_clicked' 'settings.kimi.api_key_guide_clicked'
/** @public */
export const KIMI_RATE_LIMIT_DOCS_CLICKED_EVENT =
'ui.rate_limit.kimi_docs_clicked'
/** @public */
export const KIMI_RATE_LIMIT_PLATFORM_CLICKED_EVENT =
'ui.rate_limit.moonshot_platform_clicked'
/** @public */ /** @public */
export const SIDEPANEL_VOICE_RECORDING_STARTED_EVENT = export const SIDEPANEL_VOICE_RECORDING_STARTED_EVENT =
'sidepanel.voice.recording_started' 'sidepanel.voice.recording_started'

View File

@@ -6,7 +6,6 @@ const EnvSchema = z.object({
VITE_PUBLIC_POSTHOG_HOST: z.string().optional(), VITE_PUBLIC_POSTHOG_HOST: z.string().optional(),
VITE_PUBLIC_SENTRY_DSN: z.string().optional(), VITE_PUBLIC_SENTRY_DSN: z.string().optional(),
VITE_PUBLIC_BROWSEROS_API: z.string().optional(), VITE_PUBLIC_BROWSEROS_API: z.string().optional(),
VITE_PUBLIC_KIMI_LAUNCH: z.string().optional(),
PROD: z.boolean(), PROD: z.boolean(),
}) })

View File

@@ -1,14 +0,0 @@
import { env } from '@/lib/env'
const ENABLED_VALUES = new Set(['1', 'true', 'yes', 'on'])
function parseKimiLaunchFlag(value: string | undefined): boolean {
if (!value) return false
return ENABLED_VALUES.has(value.trim().toLowerCase())
}
const kimiLaunchEnabled = parseKimiLaunchFlag(env.VITE_PUBLIC_KIMI_LAUNCH)
export function isKimiLaunchEnabled(): boolean {
return kimiLaunchEnabled
}

View File

@@ -1,5 +0,0 @@
import { isKimiLaunchEnabled } from './kimi-launch'
export function useKimiLaunch(): boolean {
return isKimiLaunchEnabled()
}

View File

@@ -1,6 +1,5 @@
import { getBrowserOSAdapter } from '@/lib/browseros/adapter' import { getBrowserOSAdapter } from '@/lib/browseros/adapter'
import { BROWSEROS_PREFS } from '@/lib/browseros/prefs' import { BROWSEROS_PREFS } from '@/lib/browseros/prefs'
import { isKimiLaunchEnabled } from '@/lib/feature-flags/kimi-launch'
/** @public */ /** @public */
export interface LlmHubProvider { export interface LlmHubProvider {
@@ -8,43 +7,15 @@ export interface LlmHubProvider {
url: string url: string
} }
const KIMI_PROVIDER: LlmHubProvider = {
name: 'Kimi',
url: 'https://www.kimi.com',
}
function ensureKimiFirst(providers: LlmHubProvider[]): LlmHubProvider[] {
if (!isKimiLaunchEnabled()) return providers
const hasKimi = providers.some(
(p) => p.name === 'Kimi' || p.url.includes('kimi.com'),
)
return hasKimi ? providers : [KIMI_PROVIDER, ...providers]
}
export async function loadProviders(): Promise<LlmHubProvider[]> { export async function loadProviders(): Promise<LlmHubProvider[]> {
try { try {
const adapter = getBrowserOSAdapter() const adapter = getBrowserOSAdapter()
const providersPref = await adapter.getPref( const providersPref = await adapter.getPref(
BROWSEROS_PREFS.THIRD_PARTY_LLM_PROVIDERS, BROWSEROS_PREFS.THIRD_PARTY_LLM_PROVIDERS,
) )
const providers = (providersPref?.value as LlmHubProvider[]) || [] return (providersPref?.value as LlmHubProvider[]) || []
if (providers.length === 0) {
if (isKimiLaunchEnabled()) {
const defaults = [KIMI_PROVIDER]
await saveProviders(defaults)
return defaults
}
return []
}
const normalized = ensureKimiFirst(providers)
if (normalized !== providers) {
await saveProviders(normalized)
}
return normalized
} catch { } catch {
return isKimiLaunchEnabled() ? [KIMI_PROVIDER] : [] return []
} }
} }

View File

@@ -2,14 +2,12 @@ import { storage } from '@wxt-dev/storage'
import { sessionStorage } from '@/lib/auth/sessionStorage' import { sessionStorage } from '@/lib/auth/sessionStorage'
import { getBrowserOSAdapter } from '@/lib/browseros/adapter' import { getBrowserOSAdapter } from '@/lib/browseros/adapter'
import { BROWSEROS_PREFS } from '@/lib/browseros/prefs' import { BROWSEROS_PREFS } from '@/lib/browseros/prefs'
import { isKimiLaunchEnabled } from '@/lib/feature-flags/kimi-launch'
import type { LlmProviderConfig, LlmProvidersBackup } from './types' import type { LlmProviderConfig, LlmProvidersBackup } from './types'
import { uploadLlmProvidersToGraphql } from './uploadLlmProvidersToGraphql' import { uploadLlmProvidersToGraphql } from './uploadLlmProvidersToGraphql'
/** Default provider ID constant */ /** Default provider ID constant */
export const DEFAULT_PROVIDER_ID = 'browseros' export const DEFAULT_PROVIDER_ID = 'browseros'
const DEFAULT_PROVIDER_NAME = 'BrowserOS' const DEFAULT_PROVIDER_NAME = 'BrowserOS'
const KIMI_LAUNCH_PROVIDER_NAME = 'Kimi K2.5'
/** Storage key for LLM providers array */ /** Storage key for LLM providers array */
export const providersStorage = storage.defineItem<LlmProviderConfig[]>( export const providersStorage = storage.defineItem<LlmProviderConfig[]>(
@@ -91,7 +89,7 @@ export function setupLlmProvidersSyncToBackend(): () => void {
/** Load providers from storage */ /** Load providers from storage */
export async function loadProviders(): Promise<LlmProviderConfig[]> { export async function loadProviders(): Promise<LlmProviderConfig[]> {
const providers = (await providersStorage.getValue()) || [] const providers = (await providersStorage.getValue()) || []
const normalizedProviders = normalizeProvidersForLaunch(providers) const normalizedProviders = normalizeProviderNames(providers)
// Keep storage consistent so every consumer sees the same provider name. // Keep storage consistent so every consumer sees the same provider name.
if ( if (
@@ -109,7 +107,7 @@ export function createDefaultBrowserOSProvider(): LlmProviderConfig {
return { return {
id: DEFAULT_PROVIDER_ID, id: DEFAULT_PROVIDER_ID,
type: 'browseros', type: 'browseros',
name: getBuiltInProviderName(), name: DEFAULT_PROVIDER_NAME,
baseUrl: 'https://api.browseros.com/v1', baseUrl: 'https://api.browseros.com/v1',
modelId: 'browseros-auto', modelId: 'browseros-auto',
supportsImages: true, supportsImages: true,
@@ -125,26 +123,22 @@ export function createDefaultProvidersConfig(): LlmProviderConfig[] {
return [createDefaultBrowserOSProvider()] return [createDefaultBrowserOSProvider()]
} }
function getBuiltInProviderName(): string { /**
return isKimiLaunchEnabled() * Normalize built-in provider names back to "BrowserOS" (e.g. from "Kimi K2.5"
? KIMI_LAUNCH_PROVIDER_NAME * which was set during a previous partnership launch).
: DEFAULT_PROVIDER_NAME */
} function normalizeProviderNames(
function normalizeProvidersForLaunch(
providers: LlmProviderConfig[], providers: LlmProviderConfig[],
): LlmProviderConfig[] { ): LlmProviderConfig[] {
const builtInProviderName = getBuiltInProviderName()
return providers.map((provider) => { return providers.map((provider) => {
if ( if (
provider.id === DEFAULT_PROVIDER_ID && provider.id === DEFAULT_PROVIDER_ID &&
provider.type === 'browseros' && provider.type === 'browseros' &&
provider.name !== builtInProviderName provider.name !== DEFAULT_PROVIDER_NAME
) { ) {
return { return {
...provider, ...provider,
name: builtInProviderName, name: DEFAULT_PROVIDER_NAME,
} }
} }
return provider return provider