Skip to content

Commit 2fda064

Browse files
authored
Cloud: bugfixes: log refresh errors and allow logout from inactive-session (#4268)
* Cloud: log session refresh errors * Cloud: bugfix: allow logouts during the inactive-session state
1 parent 900de7b commit 2fda064

File tree

9 files changed

+68
-28
lines changed

9 files changed

+68
-28
lines changed

packages/cloud/src/AuthService.ts

Lines changed: 17 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import { getClerkBaseUrl, getRooCodeApiUrl } from "./Config"
1111
import { RefreshTimer } from "./RefreshTimer"
1212

1313
export interface AuthServiceEvents {
14+
"inactive-session": [data: { previousState: AuthState }]
1415
"active-session": [data: { previousState: AuthState }]
1516
"logged-out": [data: { previousState: AuthState }]
1617
"user-info": [data: { userInfo: CloudUserInfo }]
@@ -92,11 +93,15 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
9293

9394
private transitionToInactiveSession(credentials: AuthCredentials): void {
9495
this.credentials = credentials
96+
97+
const previousState = this.state
9598
this.state = "inactive-session"
9699

97100
this.sessionToken = null
98101
this.userInfo = null
99102

103+
this.emit("inactive-session", { previousState })
104+
100105
this.timer.start()
101106

102107
console.log("[auth] Transitioned to inactive-session state")
@@ -281,14 +286,19 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
281286
return
282287
}
283288

284-
const previousState = this.state
285-
this.sessionToken = await this.clerkCreateSessionToken()
286-
this.state = "active-session"
289+
try {
290+
const previousState = this.state
291+
this.sessionToken = await this.clerkCreateSessionToken()
292+
this.state = "active-session"
287293

288-
if (previousState !== "active-session") {
289-
console.log("[auth] Transitioned to active-session state")
290-
this.emit("active-session", { previousState })
291-
this.fetchUserInfo()
294+
if (previousState !== "active-session") {
295+
console.log("[auth] Transitioned to active-session state")
296+
this.emit("active-session", { previousState })
297+
this.fetchUserInfo()
298+
}
299+
} catch (error) {
300+
console.error("[auth] Failed to refresh session", error)
301+
throw error
292302
}
293303
}
294304

packages/cloud/src/CloudService.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export class CloudService {
3535
try {
3636
this.authService = await AuthService.createInstance(this.context)
3737

38+
this.authService.on("inactive-session", this.authListener)
3839
this.authService.on("active-session", this.authListener)
3940
this.authService.on("logged-out", this.authListener)
4041
this.authService.on("user-info", this.authListener)

src/core/webview/ClineProvider.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1300,6 +1300,7 @@ export class ClineProvider
13001300
terminalCompressProgressBar,
13011301
historyPreviewCollapsed,
13021302
cloudUserInfo,
1303+
cloudIsAuthenticated,
13031304
organizationAllowList,
13041305
maxConcurrentFileReads,
13051306
condensingApiConfigId,
@@ -1398,6 +1399,7 @@ export class ClineProvider
13981399
hasSystemPromptOverride,
13991400
historyPreviewCollapsed: historyPreviewCollapsed ?? false,
14001401
cloudUserInfo,
1402+
cloudIsAuthenticated: cloudIsAuthenticated ?? false,
14011403
organizationAllowList,
14021404
condensingApiConfigId,
14031405
customCondensingPrompt,
@@ -1453,6 +1455,16 @@ export class ClineProvider
14531455
)
14541456
}
14551457

1458+
let cloudIsAuthenticated: boolean = false
1459+
1460+
try {
1461+
cloudIsAuthenticated = CloudService.instance.isAuthenticated()
1462+
} catch (error) {
1463+
console.error(
1464+
`[getState] failed to get cloud authentication state: ${error instanceof Error ? error.message : String(error)}`,
1465+
)
1466+
}
1467+
14561468
// Return the same structure as before
14571469
return {
14581470
apiConfiguration: providerSettings,
@@ -1528,6 +1540,7 @@ export class ClineProvider
15281540
: 1,
15291541
historyPreviewCollapsed: stateValues.historyPreviewCollapsed ?? false,
15301542
cloudUserInfo,
1543+
cloudIsAuthenticated,
15311544
organizationAllowList,
15321545
// Explicitly add condensing settings
15331546
condensingApiConfigId: stateValues.condensingApiConfigId,

src/core/webview/__tests__/ClineProvider.test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -427,6 +427,7 @@ describe("ClineProvider", () => {
427427
organizationAllowList: ORGANIZATION_ALLOW_ALL,
428428
autoCondenseContext: true,
429429
autoCondenseContextPercent: 100,
430+
cloudIsAuthenticated: false,
430431
}
431432

432433
const message: ExtensionMessage = {

src/shared/ExtensionMessage.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -219,6 +219,7 @@ export type ExtensionState = Pick<
219219
historyPreviewCollapsed?: boolean
220220

221221
cloudUserInfo: CloudUserInfo | null
222+
cloudIsAuthenticated: boolean
222223
organizationAllowList: OrganizationAllowList
223224

224225
autoCondenseContext: boolean

webview-ui/src/App.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ const App = () => {
3737
telemetryKey,
3838
machineId,
3939
cloudUserInfo,
40+
cloudIsAuthenticated,
4041
} = useExtensionState()
4142

4243
const [showAnnouncement, setShowAnnouncement] = useState(false)
@@ -127,7 +128,13 @@ const App = () => {
127128
{tab === "settings" && (
128129
<SettingsView ref={settingsRef} onDone={() => setTab("chat")} targetSection={currentSection} />
129130
)}
130-
{tab === "account" && <AccountView userInfo={cloudUserInfo} onDone={() => switchTab("chat")} />}
131+
{tab === "account" && (
132+
<AccountView
133+
userInfo={cloudUserInfo}
134+
isAuthenticated={cloudIsAuthenticated}
135+
onDone={() => switchTab("chat")}
136+
/>
137+
)}
131138
<ChatView
132139
ref={chatViewRef}
133140
isHidden={tab !== "chat"}

webview-ui/src/components/account/AccountView.tsx

Lines changed: 23 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import { vscode } from "@src/utils/vscode"
77

88
type AccountViewProps = {
99
userInfo: CloudUserInfo | null
10+
isAuthenticated: boolean
1011
onDone: () => void
1112
}
1213

13-
export const AccountView = ({ userInfo, onDone }: AccountViewProps) => {
14+
export const AccountView = ({ userInfo, isAuthenticated, onDone }: AccountViewProps) => {
1415
const { t } = useAppTranslation()
1516

1617
const rooLogoUri = (window as any).IMAGES_BASE_URI + "/roo-logo.svg"
@@ -23,27 +24,29 @@ export const AccountView = ({ userInfo, onDone }: AccountViewProps) => {
2324
{t("settings:common.done")}
2425
</VSCodeButton>
2526
</div>
26-
{userInfo ? (
27+
{isAuthenticated ? (
2728
<>
28-
<div className="flex flex-col items-center mb-6">
29-
<div className="w-16 h-16 mb-3 rounded-full overflow-hidden">
30-
{userInfo?.picture ? (
31-
<img
32-
src={userInfo.picture}
33-
alt={t("account:profilePicture")}
34-
className="w-full h-full object-cover"
35-
/>
36-
) : (
37-
<div className="w-full h-full flex items-center justify-center bg-vscode-button-background text-vscode-button-foreground text-xl">
38-
{userInfo?.name?.charAt(0) || userInfo?.email?.charAt(0) || "?"}
39-
</div>
40-
)}
29+
{userInfo && (
30+
<div className="flex flex-col items-center mb-6">
31+
<div className="w-16 h-16 mb-3 rounded-full overflow-hidden">
32+
{userInfo?.picture ? (
33+
<img
34+
src={userInfo.picture}
35+
alt={t("account:profilePicture")}
36+
className="w-full h-full object-cover"
37+
/>
38+
) : (
39+
<div className="w-full h-full flex items-center justify-center bg-vscode-button-background text-vscode-button-foreground text-xl">
40+
{userInfo?.name?.charAt(0) || userInfo?.email?.charAt(0) || "?"}
41+
</div>
42+
)}
43+
</div>
44+
<h2 className="text-lg font-medium text-vscode-foreground mb-1">
45+
{userInfo?.name || t("account:unknownUser")}
46+
</h2>
47+
<p className="text-sm text-vscode-descriptionForeground">{userInfo?.email || ""}</p>
4148
</div>
42-
<h2 className="text-lg font-medium text-vscode-foreground mb-1">
43-
{userInfo?.name || t("account:unknownUser")}
44-
</h2>
45-
<p className="text-sm text-vscode-descriptionForeground">{userInfo?.email || ""}</p>
46-
</div>
49+
)}
4750
<div className="flex flex-col gap-2 mt-4">
4851
<VSCodeButton
4952
appearance="secondary"

webview-ui/src/context/ExtensionStateContext.tsx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ export interface ExtensionStateContextType extends ExtensionState {
3535
filePaths: string[]
3636
openedTabs: Array<{ label: string; isActive: boolean; path?: string }>
3737
organizationAllowList: OrganizationAllowList
38+
cloudIsAuthenticated: boolean
3839
maxConcurrentFileReads?: number
3940
condensingApiConfigId?: string
4041
setCondensingApiConfigId: (value: string) => void
@@ -199,6 +200,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
199200
terminalCompressProgressBar: true, // Default to compress progress bar output
200201
historyPreviewCollapsed: false, // Initialize the new state (default to expanded)
201202
cloudUserInfo: null,
203+
cloudIsAuthenticated: false,
202204
organizationAllowList: ORGANIZATION_ALLOW_ALL,
203205
autoCondenseContext: true,
204206
autoCondenseContextPercent: 100,
@@ -317,6 +319,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
317319
writeDelayMs: state.writeDelayMs,
318320
screenshotQuality: state.screenshotQuality,
319321
routerModels: extensionRouterModels,
322+
cloudIsAuthenticated: state.cloudIsAuthenticated ?? false,
320323
setExperimentEnabled: (id, enabled) =>
321324
setState((prevState) => ({ ...prevState, experiments: { ...prevState.experiments, [id]: enabled } })),
322325
setApiConfiguration,

webview-ui/src/context/__tests__/ExtensionStateContext.test.tsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -207,6 +207,7 @@ describe("mergeExtensionState", () => {
207207
organizationAllowList: { allowAll: true, providers: {} },
208208
autoCondenseContext: true,
209209
autoCondenseContextPercent: 100,
210+
cloudIsAuthenticated: false,
210211
}
211212

212213
const prevState: ExtensionState = {

0 commit comments

Comments
 (0)