Merge pull request #14 from Askhz/refactor/first-login
refactor: remove OAuth/preflight from onboarding and fix model picker reload after CoStrict login
This commit is contained in:
commit
1f68cd74e3
|
|
@ -32,7 +32,7 @@ export async function performLogout({ clearOnboarding = false }): Promise<void>
|
|||
await deleteCoStrictCredentials();
|
||||
clearModelCache();
|
||||
delete process.env.CLAUDE_CODE_USE_COSTRICT;
|
||||
updateSettingsForSource('userSettings', { modelType: 'anthropic' as any });
|
||||
updateSettingsForSource('userSettings', { modelType: undefined, model: undefined } as any);
|
||||
|
||||
await clearAuthRelatedCaches();
|
||||
saveGlobalConfig(current => {
|
||||
|
|
|
|||
|
|
@ -47,6 +47,7 @@ function ModelPickerWrapper({
|
|||
const mainLoopModelForSession = useAppState(s => s.mainLoopModelForSession);
|
||||
const isFastMode = useAppState(s => s.fastMode);
|
||||
const setAppState = useSetAppState();
|
||||
const [pickerKey, setPickerKey] = React.useState(0);
|
||||
|
||||
function handleCancel(): void {
|
||||
logEvent('tengu_model_command_menu', {
|
||||
|
|
@ -69,11 +70,9 @@ function ModelPickerWrapper({
|
|||
const machineId = generateMachineId();
|
||||
const loginUrl = buildCoStrictLoginURL(baseUrl, state, machineId);
|
||||
|
||||
// 打开浏览器
|
||||
// 打开浏览器(不调用 onDone,保持 picker 显示)
|
||||
await openBrowser(loginUrl);
|
||||
|
||||
onDone('Opening browser for CoStrict login...', { display: 'system' });
|
||||
|
||||
// 轮询等待登录完成
|
||||
const tokens = await pollLoginToken(baseUrl, state, machineId);
|
||||
|
||||
|
|
@ -96,22 +95,16 @@ function ModelPickerWrapper({
|
|||
updateSettingsForSource('userSettings', { modelType: 'costrict' as any } as any);
|
||||
process.env.CLAUDE_CODE_USE_COSTRICT = '1';
|
||||
|
||||
// 预取模型列表
|
||||
// 预取并缓存模型列表
|
||||
try {
|
||||
const { fetchCoStrictModels } = await import('../../costrict/provider/models.js');
|
||||
const models = await fetchCoStrictModels(baseUrl, tokens.access_token);
|
||||
if (models.length > 0) {
|
||||
// 登录成功,刷新模型列表
|
||||
onDone(`Successfully logged in to CoStrict! Found ${models.length} available models.`, {
|
||||
display: 'system',
|
||||
});
|
||||
return;
|
||||
}
|
||||
await fetchCoStrictModels(baseUrl, tokens.access_token);
|
||||
} catch {
|
||||
// 预取失败
|
||||
// 预取失败,picker 重载后会显示默认模型列表
|
||||
}
|
||||
|
||||
onDone('Successfully logged in to CoStrict!', { display: 'system' });
|
||||
// 登录成功后重载 ModelPicker,显示 CoStrict 模型选择界面
|
||||
setPickerKey(k => k + 1);
|
||||
} catch (err: any) {
|
||||
onDone(`Login failed: ${err.message || String(err)}`, { display: 'system' });
|
||||
}
|
||||
|
|
@ -166,6 +159,7 @@ function ModelPickerWrapper({
|
|||
|
||||
return (
|
||||
<ModelPicker
|
||||
key={pickerKey}
|
||||
initial={mainLoopModel}
|
||||
sessionModel={mainLoopModelForSession}
|
||||
onSelect={handleSelect}
|
||||
|
|
|
|||
|
|
@ -10,15 +10,12 @@ import {
|
|||
import { useExitOnCtrlCDWithKeybindings } from '../hooks/useExitOnCtrlCDWithKeybindings.js'
|
||||
import { Box, Link, Newline, Text, useTheme } from '@anthropic/ink'
|
||||
import { useKeybindings } from '../keybindings/useKeybinding.js'
|
||||
import { isAnthropicAuthEnabled } from '../utils/auth.js'
|
||||
import { normalizeApiKeyForConfig } from '../utils/authPortable.js'
|
||||
import { getCustomApiKeyStatus } from '../utils/config.js'
|
||||
import { env } from '../utils/env.js'
|
||||
import { isRunningOnHomespace } from '../utils/envUtils.js'
|
||||
import { PreflightStep } from '../utils/preflightChecks.js'
|
||||
import type { ThemeSetting } from '../utils/theme.js'
|
||||
import { ApproveApiKey } from './ApproveApiKey.js'
|
||||
import { ConsoleOAuthFlow } from './ConsoleOAuthFlow.js'
|
||||
import { Select } from './CustomSelect/select.js'
|
||||
import { WelcomeV2 } from './LogoV2/WelcomeV2.js'
|
||||
import { PressEnterToContinue } from './PressEnterToContinue.js'
|
||||
|
|
@ -26,9 +23,7 @@ import { ThemePicker } from './ThemePicker.js'
|
|||
import { OrderedList } from './ui/OrderedList.js'
|
||||
|
||||
type StepId =
|
||||
| 'preflight'
|
||||
| 'theme'
|
||||
| 'oauth'
|
||||
| 'api-key'
|
||||
| 'security'
|
||||
| 'terminal-setup'
|
||||
|
|
@ -44,15 +39,11 @@ type Props = {
|
|||
|
||||
export function Onboarding({ onDone }: Props): React.ReactNode {
|
||||
const [currentStepIndex, setCurrentStepIndex] = useState(0)
|
||||
const [skipOAuth, setSkipOAuth] = useState(false)
|
||||
const [oauthEnabled] = useState(() => isAnthropicAuthEnabled())
|
||||
const [theme, setTheme] = useTheme()
|
||||
|
||||
useEffect(() => {
|
||||
logEvent('tengu_began_setup', {
|
||||
oauthEnabled,
|
||||
})
|
||||
}, [oauthEnabled])
|
||||
logEvent('tengu_began_setup', {})
|
||||
}, [])
|
||||
|
||||
function goToNextStep() {
|
||||
if (currentStepIndex < steps.length - 1) {
|
||||
|
|
@ -60,7 +51,6 @@ export function Onboarding({ onDone }: Props): React.ReactNode {
|
|||
setCurrentStepIndex(nextIndex)
|
||||
|
||||
logEvent('tengu_onboarding_step', {
|
||||
oauthEnabled,
|
||||
stepId: steps[nextIndex]
|
||||
?.id as AnalyticsMetadata_I_VERIFIED_THIS_IS_NOT_CODE_OR_FILEPATHS,
|
||||
})
|
||||
|
|
@ -123,8 +113,7 @@ export function Onboarding({ onDone }: Props): React.ReactNode {
|
|||
</Box>
|
||||
)
|
||||
|
||||
const preflightStep = <PreflightStep onSuccess={goToNextStep} />
|
||||
// Create the steps array - determine which steps to include based on reAuth and oauthEnabled
|
||||
// Create the steps array
|
||||
const apiKeyNeedingApproval = useMemo(() => {
|
||||
// Add API key step if needed
|
||||
// On homespace, ANTHROPIC_API_KEY is preserved in process.env for child
|
||||
|
|
@ -140,17 +129,11 @@ export function Onboarding({ onDone }: Props): React.ReactNode {
|
|||
}
|
||||
}, [])
|
||||
|
||||
function handleApiKeyDone(approved: boolean) {
|
||||
if (approved) {
|
||||
setSkipOAuth(true)
|
||||
}
|
||||
function handleApiKeyDone(_approved: boolean) {
|
||||
goToNextStep()
|
||||
}
|
||||
|
||||
const steps: OnboardingStep[] = []
|
||||
if (oauthEnabled) {
|
||||
steps.push({ id: 'preflight', component: preflightStep })
|
||||
}
|
||||
steps.push({ id: 'theme', component: themeStep })
|
||||
|
||||
if (apiKeyNeedingApproval) {
|
||||
|
|
@ -165,17 +148,6 @@ export function Onboarding({ onDone }: Props): React.ReactNode {
|
|||
})
|
||||
}
|
||||
|
||||
if (oauthEnabled) {
|
||||
steps.push({
|
||||
id: 'oauth',
|
||||
component: (
|
||||
<SkippableStep skip={skipOAuth} onSkip={goToNextStep}>
|
||||
<ConsoleOAuthFlow onDone={goToNextStep} />
|
||||
</SkippableStep>
|
||||
),
|
||||
})
|
||||
}
|
||||
|
||||
steps.push({ id: 'security', component: securityStep })
|
||||
|
||||
if (shouldOfferTerminalSetup()) {
|
||||
|
|
@ -239,11 +211,11 @@ export function Onboarding({ onDone }: Props): React.ReactNode {
|
|||
} else {
|
||||
goToNextStep()
|
||||
}
|
||||
}, [currentStepIndex, steps.length, oauthEnabled, onDone])
|
||||
}, [currentStepIndex, steps.length, onDone])
|
||||
|
||||
const handleTerminalSetupSkip = useCallback(() => {
|
||||
goToNextStep()
|
||||
}, [currentStepIndex, steps.length, oauthEnabled, onDone])
|
||||
}, [currentStepIndex, steps.length, onDone])
|
||||
|
||||
useKeybindings(
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user