mirror of
https://github.com/RooVetGit/Roo-Code.git
synced 2026-09-06 08:18:39 +00:00
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
This commit is contained in:
parent
900de7b401
commit
2fda064ae9
9 changed files with 68 additions and 28 deletions
|
|
@ -11,6 +11,7 @@ import { getClerkBaseUrl, getRooCodeApiUrl } from "./Config"
|
|||
import { RefreshTimer } from "./RefreshTimer"
|
||||
|
||||
export interface AuthServiceEvents {
|
||||
"inactive-session": [data: { previousState: AuthState }]
|
||||
"active-session": [data: { previousState: AuthState }]
|
||||
"logged-out": [data: { previousState: AuthState }]
|
||||
"user-info": [data: { userInfo: CloudUserInfo }]
|
||||
|
|
@ -92,11 +93,15 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
|
|||
|
||||
private transitionToInactiveSession(credentials: AuthCredentials): void {
|
||||
this.credentials = credentials
|
||||
|
||||
const previousState = this.state
|
||||
this.state = "inactive-session"
|
||||
|
||||
this.sessionToken = null
|
||||
this.userInfo = null
|
||||
|
||||
this.emit("inactive-session", { previousState })
|
||||
|
||||
this.timer.start()
|
||||
|
||||
console.log("[auth] Transitioned to inactive-session state")
|
||||
|
|
@ -281,14 +286,19 @@ export class AuthService extends EventEmitter<AuthServiceEvents> {
|
|||
return
|
||||
}
|
||||
|
||||
const previousState = this.state
|
||||
this.sessionToken = await this.clerkCreateSessionToken()
|
||||
this.state = "active-session"
|
||||
try {
|
||||
const previousState = this.state
|
||||
this.sessionToken = await this.clerkCreateSessionToken()
|
||||
this.state = "active-session"
|
||||
|
||||
if (previousState !== "active-session") {
|
||||
console.log("[auth] Transitioned to active-session state")
|
||||
this.emit("active-session", { previousState })
|
||||
this.fetchUserInfo()
|
||||
if (previousState !== "active-session") {
|
||||
console.log("[auth] Transitioned to active-session state")
|
||||
this.emit("active-session", { previousState })
|
||||
this.fetchUserInfo()
|
||||
}
|
||||
} catch (error) {
|
||||
console.error("[auth] Failed to refresh session", error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ export class CloudService {
|
|||
try {
|
||||
this.authService = await AuthService.createInstance(this.context)
|
||||
|
||||
this.authService.on("inactive-session", this.authListener)
|
||||
this.authService.on("active-session", this.authListener)
|
||||
this.authService.on("logged-out", this.authListener)
|
||||
this.authService.on("user-info", this.authListener)
|
||||
|
|
|
|||
|
|
@ -1300,6 +1300,7 @@ export class ClineProvider
|
|||
terminalCompressProgressBar,
|
||||
historyPreviewCollapsed,
|
||||
cloudUserInfo,
|
||||
cloudIsAuthenticated,
|
||||
organizationAllowList,
|
||||
maxConcurrentFileReads,
|
||||
condensingApiConfigId,
|
||||
|
|
@ -1398,6 +1399,7 @@ export class ClineProvider
|
|||
hasSystemPromptOverride,
|
||||
historyPreviewCollapsed: historyPreviewCollapsed ?? false,
|
||||
cloudUserInfo,
|
||||
cloudIsAuthenticated: cloudIsAuthenticated ?? false,
|
||||
organizationAllowList,
|
||||
condensingApiConfigId,
|
||||
customCondensingPrompt,
|
||||
|
|
@ -1453,6 +1455,16 @@ export class ClineProvider
|
|||
)
|
||||
}
|
||||
|
||||
let cloudIsAuthenticated: boolean = false
|
||||
|
||||
try {
|
||||
cloudIsAuthenticated = CloudService.instance.isAuthenticated()
|
||||
} catch (error) {
|
||||
console.error(
|
||||
`[getState] failed to get cloud authentication state: ${error instanceof Error ? error.message : String(error)}`,
|
||||
)
|
||||
}
|
||||
|
||||
// Return the same structure as before
|
||||
return {
|
||||
apiConfiguration: providerSettings,
|
||||
|
|
@ -1528,6 +1540,7 @@ export class ClineProvider
|
|||
: 1,
|
||||
historyPreviewCollapsed: stateValues.historyPreviewCollapsed ?? false,
|
||||
cloudUserInfo,
|
||||
cloudIsAuthenticated,
|
||||
organizationAllowList,
|
||||
// Explicitly add condensing settings
|
||||
condensingApiConfigId: stateValues.condensingApiConfigId,
|
||||
|
|
|
|||
|
|
@ -427,6 +427,7 @@ describe("ClineProvider", () => {
|
|||
organizationAllowList: ORGANIZATION_ALLOW_ALL,
|
||||
autoCondenseContext: true,
|
||||
autoCondenseContextPercent: 100,
|
||||
cloudIsAuthenticated: false,
|
||||
}
|
||||
|
||||
const message: ExtensionMessage = {
|
||||
|
|
|
|||
|
|
@ -219,6 +219,7 @@ export type ExtensionState = Pick<
|
|||
historyPreviewCollapsed?: boolean
|
||||
|
||||
cloudUserInfo: CloudUserInfo | null
|
||||
cloudIsAuthenticated: boolean
|
||||
organizationAllowList: OrganizationAllowList
|
||||
|
||||
autoCondenseContext: boolean
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ const App = () => {
|
|||
telemetryKey,
|
||||
machineId,
|
||||
cloudUserInfo,
|
||||
cloudIsAuthenticated,
|
||||
} = useExtensionState()
|
||||
|
||||
const [showAnnouncement, setShowAnnouncement] = useState(false)
|
||||
|
|
@ -127,7 +128,13 @@ const App = () => {
|
|||
{tab === "settings" && (
|
||||
<SettingsView ref={settingsRef} onDone={() => setTab("chat")} targetSection={currentSection} />
|
||||
)}
|
||||
{tab === "account" && <AccountView userInfo={cloudUserInfo} onDone={() => switchTab("chat")} />}
|
||||
{tab === "account" && (
|
||||
<AccountView
|
||||
userInfo={cloudUserInfo}
|
||||
isAuthenticated={cloudIsAuthenticated}
|
||||
onDone={() => switchTab("chat")}
|
||||
/>
|
||||
)}
|
||||
<ChatView
|
||||
ref={chatViewRef}
|
||||
isHidden={tab !== "chat"}
|
||||
|
|
|
|||
|
|
@ -7,10 +7,11 @@ import { vscode } from "@src/utils/vscode"
|
|||
|
||||
type AccountViewProps = {
|
||||
userInfo: CloudUserInfo | null
|
||||
isAuthenticated: boolean
|
||||
onDone: () => void
|
||||
}
|
||||
|
||||
export const AccountView = ({ userInfo, onDone }: AccountViewProps) => {
|
||||
export const AccountView = ({ userInfo, isAuthenticated, onDone }: AccountViewProps) => {
|
||||
const { t } = useAppTranslation()
|
||||
|
||||
const rooLogoUri = (window as any).IMAGES_BASE_URI + "/roo-logo.svg"
|
||||
|
|
@ -23,27 +24,29 @@ export const AccountView = ({ userInfo, onDone }: AccountViewProps) => {
|
|||
{t("settings:common.done")}
|
||||
</VSCodeButton>
|
||||
</div>
|
||||
{userInfo ? (
|
||||
{isAuthenticated ? (
|
||||
<>
|
||||
<div className="flex flex-col items-center mb-6">
|
||||
<div className="w-16 h-16 mb-3 rounded-full overflow-hidden">
|
||||
{userInfo?.picture ? (
|
||||
<img
|
||||
src={userInfo.picture}
|
||||
alt={t("account:profilePicture")}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full flex items-center justify-center bg-vscode-button-background text-vscode-button-foreground text-xl">
|
||||
{userInfo?.name?.charAt(0) || userInfo?.email?.charAt(0) || "?"}
|
||||
</div>
|
||||
)}
|
||||
{userInfo && (
|
||||
<div className="flex flex-col items-center mb-6">
|
||||
<div className="w-16 h-16 mb-3 rounded-full overflow-hidden">
|
||||
{userInfo?.picture ? (
|
||||
<img
|
||||
src={userInfo.picture}
|
||||
alt={t("account:profilePicture")}
|
||||
className="w-full h-full object-cover"
|
||||
/>
|
||||
) : (
|
||||
<div className="w-full h-full flex items-center justify-center bg-vscode-button-background text-vscode-button-foreground text-xl">
|
||||
{userInfo?.name?.charAt(0) || userInfo?.email?.charAt(0) || "?"}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
<h2 className="text-lg font-medium text-vscode-foreground mb-1">
|
||||
{userInfo?.name || t("account:unknownUser")}
|
||||
</h2>
|
||||
<p className="text-sm text-vscode-descriptionForeground">{userInfo?.email || ""}</p>
|
||||
</div>
|
||||
<h2 className="text-lg font-medium text-vscode-foreground mb-1">
|
||||
{userInfo?.name || t("account:unknownUser")}
|
||||
</h2>
|
||||
<p className="text-sm text-vscode-descriptionForeground">{userInfo?.email || ""}</p>
|
||||
</div>
|
||||
)}
|
||||
<div className="flex flex-col gap-2 mt-4">
|
||||
<VSCodeButton
|
||||
appearance="secondary"
|
||||
|
|
|
|||
|
|
@ -35,6 +35,7 @@ export interface ExtensionStateContextType extends ExtensionState {
|
|||
filePaths: string[]
|
||||
openedTabs: Array<{ label: string; isActive: boolean; path?: string }>
|
||||
organizationAllowList: OrganizationAllowList
|
||||
cloudIsAuthenticated: boolean
|
||||
maxConcurrentFileReads?: number
|
||||
condensingApiConfigId?: string
|
||||
setCondensingApiConfigId: (value: string) => void
|
||||
|
|
@ -199,6 +200,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
terminalCompressProgressBar: true, // Default to compress progress bar output
|
||||
historyPreviewCollapsed: false, // Initialize the new state (default to expanded)
|
||||
cloudUserInfo: null,
|
||||
cloudIsAuthenticated: false,
|
||||
organizationAllowList: ORGANIZATION_ALLOW_ALL,
|
||||
autoCondenseContext: true,
|
||||
autoCondenseContextPercent: 100,
|
||||
|
|
@ -317,6 +319,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
|
|||
writeDelayMs: state.writeDelayMs,
|
||||
screenshotQuality: state.screenshotQuality,
|
||||
routerModels: extensionRouterModels,
|
||||
cloudIsAuthenticated: state.cloudIsAuthenticated ?? false,
|
||||
setExperimentEnabled: (id, enabled) =>
|
||||
setState((prevState) => ({ ...prevState, experiments: { ...prevState.experiments, [id]: enabled } })),
|
||||
setApiConfiguration,
|
||||
|
|
|
|||
|
|
@ -207,6 +207,7 @@ describe("mergeExtensionState", () => {
|
|||
organizationAllowList: { allowAll: true, providers: {} },
|
||||
autoCondenseContext: true,
|
||||
autoCondenseContextPercent: 100,
|
||||
cloudIsAuthenticated: false,
|
||||
}
|
||||
|
||||
const prevState: ExtensionState = {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue