Skip to content

Commit ac66758

Browse files
committed
feat(cli): Refactor to TanStack Query with improved login flow
- Add @tanstack/react-query v5.62.8 for data fetching - Create useAuthQuery, useLoginMutation, useLogoutMutation hooks - Set up QueryClientProvider with CLI-optimized defaults - Fix login polling infinite loop using useRef for stable callbacks - Replace TanStack Query polling with plain fetch for reliability - Fix getUserInfoFromApiKey to use actual fields parameter - Add comprehensive emoji-tagged logging throughout login flow - Compress login modal UI to prevent scrolling - Remove "Welcome to Codebuff CLI" message from modal The login flow now properly detects browser authentication and automatically closes the modal after successful credential validation.
1 parent 422e2a4 commit ac66758

File tree

6 files changed

+475
-206
lines changed

6 files changed

+475
-206
lines changed

bun.lock

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@
8686
"@codebuff/sdk": "workspace:*",
8787
"@opentui/core": "^0.1.28",
8888
"@opentui/react": "^0.1.28",
89+
"@tanstack/react-query": "^5.62.8",
8990
"commander": "^14.0.1",
9091
"immer": "^10.1.3",
9192
"open": "^10.1.0",

cli/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"@codebuff/sdk": "workspace:*",
3636
"@opentui/core": "^0.1.28",
3737
"@opentui/react": "^0.1.28",
38+
"@tanstack/react-query": "^5.62.8",
3839
"commander": "^14.0.1",
3940
"immer": "^10.1.3",
4041
"open": "^10.1.0",

cli/src/chat.tsx

Lines changed: 59 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { useRenderer, useTerminalDimensions } from '@opentui/react'
22
import React, { useCallback, useEffect, useMemo, useRef, useState } from 'react'
3-
import { useShallow } from 'zustand/react/shallow'
43
import stringWidth from 'string-width'
4+
import { useShallow } from 'zustand/react/shallow'
55

66
import { AgentModeToggle } from './components/agent-mode-toggle'
77
import { LoginModal } from './components/login-modal'
@@ -13,6 +13,7 @@ import { Separator } from './components/separator'
1313
import { StatusIndicator, useHasStatus } from './components/status-indicator'
1414
import { SuggestionMenu } from './components/suggestion-menu'
1515
import { SLASH_COMMANDS } from './data/slash-commands'
16+
import { useAuthQuery, useLogoutMutation } from './hooks/use-auth-query'
1617
import { useClipboard } from './hooks/use-clipboard'
1718
import { useInputHistory } from './hooks/use-input-history'
1819
import { useKeyboardHandlers } from './hooks/use-keyboard-handlers'
@@ -23,17 +24,16 @@ import { useSendMessage } from './hooks/use-send-message'
2324
import { useSuggestionEngine } from './hooks/use-suggestion-engine'
2425
import { useSystemThemeDetector } from './hooks/use-system-theme-detector'
2526
import { useChatStore } from './state/chat-store'
27+
import { flushAnalytics } from './utils/analytics'
28+
import { getUserCredentials } from './utils/auth'
2629
import { createChatScrollAcceleration } from './utils/chat-scroll-accel'
2730
import { formatQueuedPreview } from './utils/helpers'
2831
import { loadLocalAgents } from './utils/local-agent-registry'
29-
import { flushAnalytics } from './utils/analytics'
3032
import { logger } from './utils/logger'
3133
import { buildMessageTree } from './utils/message-tree-utils'
3234
import { chatThemes, createMarkdownPalette } from './utils/theme-system'
3335

3436
import type { User } from './utils/auth'
35-
import { logoutUser } from './utils/auth'
36-
3737
import type { ToolName } from '@codebuff/sdk'
3838
import type { ScrollBoxRenderable } from '@opentui/core'
3939

@@ -122,7 +122,10 @@ export const App = ({
122122
)
123123
const lastSigintTimeRef = useRef<number>(0)
124124

125-
// Track authentication state
125+
// Track authentication state using TanStack Query
126+
const authQuery = useAuthQuery()
127+
const logoutMutation = useLogoutMutation()
128+
126129
// If requireAuth is null (checking), assume not authenticated until proven otherwise
127130
const [isAuthenticated, setIsAuthenticated] = useState(
128131
requireAuth === false ? true : false
@@ -136,6 +139,27 @@ export const App = ({
136139
}
137140
}, [requireAuth])
138141

142+
// Update authentication state based on query results
143+
useEffect(() => {
144+
if (authQuery.isSuccess && authQuery.data) {
145+
setIsAuthenticated(true)
146+
if (!user) {
147+
// Convert authQuery data to User format if needed
148+
const userCredentials = getUserCredentials()
149+
const userData: User = {
150+
id: authQuery.data.id,
151+
name: userCredentials?.name || '',
152+
email: authQuery.data.email || '',
153+
authToken: userCredentials?.authToken || '',
154+
}
155+
setUser(userData)
156+
}
157+
} else if (authQuery.isError) {
158+
setIsAuthenticated(false)
159+
setUser(null)
160+
}
161+
}, [authQuery.isSuccess, authQuery.isError, authQuery.data, user])
162+
139163
// Log app initialization
140164
useEffect(() => {
141165
logger.debug(
@@ -204,11 +228,32 @@ export const App = ({
204228
// Handle successful login
205229
const handleLoginSuccess = useCallback(
206230
(loggedInUser: User) => {
231+
logger.info(
232+
{
233+
userName: loggedInUser.name,
234+
userEmail: loggedInUser.email,
235+
userId: loggedInUser.id,
236+
},
237+
'🎊 handleLoginSuccess called - updating UI state',
238+
)
239+
240+
logger.info('🔄 Resetting chat store...')
207241
resetChatStore()
242+
logger.info('✅ Chat store reset')
243+
244+
logger.info('🎯 Setting input focused...')
208245
setInputFocused(true)
246+
logger.info('✅ Input focused')
247+
248+
logger.info('👤 Setting user state...')
209249
setUser(loggedInUser)
250+
logger.info('✅ User state set')
251+
252+
logger.info('🔓 Setting isAuthenticated to true...')
210253
setIsAuthenticated(true)
211-
logger.info({ user: loggedInUser.name }, 'User logged in successfully')
254+
logger.info('✅ isAuthenticated set to true - modal should close now')
255+
256+
logger.info({ user: loggedInUser.name }, '🎉 Login flow completed successfully!')
212257
},
213258
[resetChatStore, setInputFocused],
214259
)
@@ -678,13 +723,12 @@ export const App = ({
678723
return
679724
}
680725
if (cmd === 'logout' || cmd === 'signout') {
681-
;(async () => {
682-
try {
683-
await logoutUser()
684-
} finally {
685-
abortControllerRef.current?.abort()
686-
stopStreaming()
687-
setCanProcessQueue(false)
726+
abortControllerRef.current?.abort()
727+
stopStreaming()
728+
setCanProcessQueue(false)
729+
730+
logoutMutation.mutate(undefined, {
731+
onSettled: () => {
688732
const msg = {
689733
id: `sys-${Date.now()}`,
690734
variant: 'ai' as const,
@@ -697,8 +741,8 @@ export const App = ({
697741
setUser(null)
698742
setIsAuthenticated(false)
699743
}, 300)
700-
}
701-
})()
744+
},
745+
})
702746
return
703747
}
704748

0 commit comments

Comments
 (0)