feat(logo): show "Not logged in" state and provider display name in logo
Add isNotLoggedIn() utility to detect unauthenticated state and display "Not logged in" message in both LogoV2 and CondensedLogo components. Replace billing type with provider display name (e.g. "OpenAI", "AWS Bedrock") when logged in. Subscribe to authVersion to re-render on login/logout. Add third-party provider model options for OpenAI, Gemini, Grok, Bedrock, Vertex, and Foundry. Disable biome formatter.
This commit is contained in:
parent
afee7d3ed2
commit
6fb91d2c28
|
|
@ -7,7 +7,7 @@ import { useAppState } from '../../state/AppState.js';
|
|||
import { getEffortSuffix } from '../../utils/effort.js';
|
||||
import { truncate } from '../../utils/format.js';
|
||||
import { isFullscreenEnvEnabled } from '../../utils/fullscreen.js';
|
||||
import { formatModelAndBilling, getLogoDisplayData, truncatePath } from '../../utils/logoV2Utils.js';
|
||||
import { formatModelAndBilling, getLogoDisplayData, isNotLoggedIn, truncatePath } from '../../utils/logoV2Utils.js';
|
||||
import { renderModelSetting } from '../../utils/model/model.js';
|
||||
import { OffscreenFreeze } from '../OffscreenFreeze.js';
|
||||
import { AnimatedClawd } from './AnimatedClawd.js';
|
||||
|
|
@ -23,7 +23,10 @@ export function CondensedLogo(): ReactNode {
|
|||
const { columns } = useTerminalSize();
|
||||
const agent = useAppState(s => s.agent);
|
||||
const effortValue = useAppState(s => s.effortValue);
|
||||
// Subscribe to authVersion to re-render after login/logout
|
||||
useAppState(s => s.authVersion);
|
||||
const model = useMainLoopModel();
|
||||
const notLoggedIn = isNotLoggedIn();
|
||||
const modelDisplayName = renderModelSetting(model);
|
||||
const { version, cwd, billingType, agentName: agentNameFromSettings } = getLogoDisplayData();
|
||||
|
||||
|
|
@ -92,7 +95,9 @@ export function CondensedLogo(): ReactNode {
|
|||
</Text>{' '}
|
||||
<Text dimColor>v{truncatedVersion}</Text>
|
||||
</Text>
|
||||
{shouldSplit ? (
|
||||
{notLoggedIn ? (
|
||||
<Text dimColor>Not logged in</Text>
|
||||
) : shouldSplit ? (
|
||||
<>
|
||||
<Text dimColor>{truncatedModel}</Text>
|
||||
<Text dimColor>{truncatedBilling}</Text>
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import {
|
|||
getRecentActivitySync,
|
||||
getRecentReleaseNotesSync,
|
||||
getLogoDisplayData,
|
||||
isNotLoggedIn,
|
||||
} from '../../utils/logoV2Utils.js';
|
||||
import { truncate } from '../../utils/format.js';
|
||||
import { getDisplayPath } from '../../utils/file.js';
|
||||
|
|
@ -82,6 +83,8 @@ export function LogoV2(): React.ReactNode {
|
|||
const showOverageCreditUpsell = useShowOverageCreditUpsell();
|
||||
const agent = useAppState(s => s.agent);
|
||||
const effortValue = useAppState(s => s.effortValue);
|
||||
// Subscribe to authVersion to re-render after login/logout
|
||||
useAppState(s => s.authVersion);
|
||||
|
||||
const config = getGlobalConfig();
|
||||
|
||||
|
|
@ -136,6 +139,7 @@ export function LogoV2(): React.ReactNode {
|
|||
}, [showOverageCreditUpsell, showOnboarding, showGuestPassesUpsell, isCondensedMode]);
|
||||
|
||||
const model = useMainLoopModel();
|
||||
const notLoggedIn = isNotLoggedIn();
|
||||
const fullModelDisplayName = renderModelSetting(model);
|
||||
const { version, cwd, billingType, agentName: agentNameFromSettings } = getLogoDisplayData();
|
||||
// Prefer AppState.agent (set from --agent CLI flag) over settings
|
||||
|
|
@ -247,8 +251,8 @@ export function LogoV2(): React.ReactNode {
|
|||
<Box marginY={1}>
|
||||
<Clawd />
|
||||
</Box>
|
||||
<Text dimColor>{modelDisplayName}</Text>
|
||||
<Text dimColor>{billingType}</Text>
|
||||
<Text dimColor>{notLoggedIn ? 'Not logged in' : modelDisplayName}</Text>
|
||||
{!notLoggedIn && <Text dimColor>{billingType}</Text>}
|
||||
<Text dimColor>{agentName ? `@${agentName} · ${truncatedCwd}` : truncatedCwd}</Text>
|
||||
</Box>
|
||||
</OffscreenFreeze>
|
||||
|
|
@ -269,8 +273,9 @@ export function LogoV2(): React.ReactNode {
|
|||
}
|
||||
|
||||
const welcomeMessage = formatWelcomeMessage(username);
|
||||
const modelLine =
|
||||
!process.env.IS_DEMO && config.oauthAccount?.organizationName
|
||||
const modelLine = notLoggedIn
|
||||
? 'Not logged in'
|
||||
: !process.env.IS_DEMO && config.oauthAccount?.organizationName
|
||||
? `${modelDisplayName} · ${billingType} · ${config.oauthAccount.organizationName}`
|
||||
: `${modelDisplayName} · ${billingType}`;
|
||||
// Calculate cwd width accounting for agent name if present
|
||||
|
|
|
|||
|
|
@ -1,7 +1,8 @@
|
|||
import { getDirectConnectServerUrl, getSessionId } from '../bootstrap/state.js'
|
||||
import { stringWidth } from '@anthropic/ink'
|
||||
import type { LogOption } from '../types/logs.js'
|
||||
import { getSubscriptionName, isClaudeAISubscriber } from './auth.js'
|
||||
import { getAnthropicApiKey } from './auth.js'
|
||||
import { hasCoStrictCredentialsSync } from '../costrict/provider/credentials.js'
|
||||
import { getCwd } from './cwd.js'
|
||||
import { getDisplayPath } from './file.js'
|
||||
import {
|
||||
|
|
@ -9,6 +10,7 @@ import {
|
|||
truncateToWidth,
|
||||
truncateToWidthNoEllipsis,
|
||||
} from './format.js'
|
||||
import { getAPIProvider, getProviderDisplayName } from './model/providers.js'
|
||||
import { getStoredChangelogFromMemory, parseChangelog } from './releaseNotes.js'
|
||||
import { gt } from './semver.js'
|
||||
import { loadMessageLogs } from './sessionStorage.js'
|
||||
|
|
@ -237,12 +239,33 @@ export function formatReleaseNoteForDisplay(
|
|||
}
|
||||
|
||||
/**
|
||||
* Gets the common logo display data used by both LogoV2 and CondensedLogo
|
||||
* Check if user is not logged in
|
||||
* User is considered logged in if they have CoStrict credentials or API key
|
||||
*/
|
||||
export function isNotLoggedIn(): boolean {
|
||||
// 1. CoStrict login (credentials file exists)
|
||||
if (hasCoStrictCredentialsSync()) return false
|
||||
|
||||
const settings = getInitialSettings()
|
||||
|
||||
// 2. Any provider configured via modelType (包括 anthropic/openai/bedrock 等)
|
||||
// 用户通过 /login 选择 provider 后会设置 modelType
|
||||
if (settings.modelType) {
|
||||
return false
|
||||
}
|
||||
|
||||
// 3. Anthropic API Key configured (legacy way without modelType)
|
||||
if (getAnthropicApiKey() !== null) return false
|
||||
|
||||
// None of the above - not logged in
|
||||
return true
|
||||
}
|
||||
|
||||
export function getLogoDisplayData(): {
|
||||
version: string
|
||||
cwd: string
|
||||
billingType: string
|
||||
isLoggedIn: boolean
|
||||
agentName: string | undefined
|
||||
} {
|
||||
const version = process.env.DEMO_VERSION ?? MACRO.VERSION
|
||||
|
|
@ -253,15 +276,18 @@ export function getLogoDisplayData(): {
|
|||
const cwd = serverUrl
|
||||
? `${displayPath} in ${serverUrl.replace(/^https?:\/\//, '')}`
|
||||
: displayPath
|
||||
const billingType = isClaudeAISubscriber()
|
||||
? getSubscriptionName()
|
||||
: 'API Usage Billing'
|
||||
|
||||
const loggedIn = !isNotLoggedIn()
|
||||
const provider = getAPIProvider()
|
||||
const providerName = getProviderDisplayName(provider)
|
||||
const billingType = loggedIn ? providerName : 'Not logged in'
|
||||
const agentName = getInitialSettings().agent
|
||||
|
||||
return {
|
||||
version,
|
||||
cwd,
|
||||
billingType,
|
||||
isLoggedIn: loggedIn,
|
||||
agentName,
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,6 +35,32 @@ export function getAPIProviderForStatsig(): AnalyticsMetadata_I_VERIFIED_THIS_IS
|
|||
return getAPIProvider() as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a human-readable display name for the current API provider
|
||||
*/
|
||||
export function getProviderDisplayName(provider: APIProvider): string {
|
||||
switch (provider) {
|
||||
case 'firstParty':
|
||||
return 'Anthropic'
|
||||
case 'bedrock':
|
||||
return 'AWS Bedrock'
|
||||
case 'vertex':
|
||||
return 'Google Vertex'
|
||||
case 'foundry':
|
||||
return 'Foundry'
|
||||
case 'openai':
|
||||
return 'OpenAI'
|
||||
case 'gemini':
|
||||
return 'Google Gemini'
|
||||
case 'grok':
|
||||
return 'xAI Grok'
|
||||
case 'costrict':
|
||||
return 'CoStrict'
|
||||
default:
|
||||
return provider
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if ANTHROPIC_BASE_URL is a first-party Anthropic API URL.
|
||||
* Returns true if not set (default API) or points to api.anthropic.com
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user