Skip to content

Commit 25d2e76

Browse files
committed
Merge branch 'main' into cte/web-evals-port-3446
2 parents bcb45c1 + 205f3e4 commit 25d2e76

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

86 files changed

+1200
-123
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,14 @@
11
# Roo Code Changelog
22

3+
## [3.28.7] - 2025-09-23
4+
5+
![3.28.7 Release - Hidden Thinking](/releases/3.28.7-release.png)
6+
7+
- UX: Collapse thinking blocks by default with UI settings to always show them (thanks @brunobergher!)
8+
- Fix: Resolve checkpoint restore popover positioning issue (#8219 by @NaccOll, PR by @app/roomote)
9+
- Add cloud account switcher functionality (thanks @mrubens!)
10+
- Add support for zai-org/GLM-4.5-turbo model in Chutes provider (#8155 by @mugnimaestra, PR by @app/roomote)
11+
312
## [3.28.6] - 2025-09-23
413

514
![3.28.6 Release - Kangaroo studying ancient codex](/releases/3.28.6-release.png)
428 KB
Loading

apps/web-roo-code/src/lib/seo.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,15 +3,15 @@ const SITE_URL = process.env.NEXT_PUBLIC_SITE_URL ?? "https://roocode.com"
33
export const SEO = {
44
url: SITE_URL,
55
name: "Roo Code",
6-
title: "Roo Code – Your AI-Powered Dev Team in VS Code",
6+
title: "Roo Code – Your AI-Powered Dev Team in VS Code and Beyond",
77
description:
88
"Roo Code puts an entire AI dev team right in your editor, outpacing closed tools with deep project-wide context, multi-step agentic coding, and unmatched developer-centric flexibility.",
99
locale: "en_US",
1010
ogImage: {
11-
url: "/android-chrome-512x512.png",
12-
width: 512,
13-
height: 512,
14-
alt: "Roo Code Logo",
11+
url: "/opengraph.png",
12+
width: 1200,
13+
height: 600,
14+
alt: "Roo Code",
1515
},
1616
keywords: [
1717
"Roo Code",

packages/cloud/src/CloudService.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import type {
88
AuthService,
99
SettingsService,
1010
CloudUserInfo,
11+
CloudOrganizationMembership,
1112
OrganizationAllowList,
1213
OrganizationSettings,
1314
ShareVisibility,
@@ -242,6 +243,21 @@ export class CloudService extends EventEmitter<CloudServiceEvents> implements Di
242243
return this.authService!.handleCallback(code, state, organizationId)
243244
}
244245

246+
public async switchOrganization(organizationId: string | null): Promise<void> {
247+
this.ensureInitialized()
248+
249+
// Perform the organization switch
250+
// StaticTokenAuthService will throw an error if organization switching is not supported
251+
await this.authService!.switchOrganization(organizationId)
252+
}
253+
254+
public async getOrganizationMemberships(): Promise<CloudOrganizationMembership[]> {
255+
this.ensureInitialized()
256+
257+
// StaticTokenAuthService will throw an error if organization memberships are not supported
258+
return await this.authService!.getOrganizationMemberships()
259+
}
260+
245261
// SettingsService
246262

247263
public getAllowList(): OrganizationAllowList {

packages/cloud/src/StaticTokenAuthService.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,14 @@ export class StaticTokenAuthService extends EventEmitter<AuthServiceEvents> impl
6363
throw new Error("Authentication methods are disabled in StaticTokenAuthService")
6464
}
6565

66+
public async switchOrganization(_organizationId: string | null): Promise<void> {
67+
throw new Error("Authentication methods are disabled in StaticTokenAuthService")
68+
}
69+
70+
public async getOrganizationMemberships(): Promise<import("@roo-code/types").CloudOrganizationMembership[]> {
71+
throw new Error("Authentication methods are disabled in StaticTokenAuthService")
72+
}
73+
6674
public getState(): AuthState {
6775
return this.state
6876
}

packages/cloud/src/WebAuthService.ts

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -141,7 +141,8 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
141141
if (
142142
this.credentials === null ||
143143
this.credentials.clientToken !== credentials.clientToken ||
144-
this.credentials.sessionId !== credentials.sessionId
144+
this.credentials.sessionId !== credentials.sessionId ||
145+
this.credentials.organizationId !== credentials.organizationId
145146
) {
146147
this.transitionToAttemptingSession(credentials)
147148
}
@@ -174,6 +175,7 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
174175

175176
this.changeState("attempting-session")
176177

178+
this.timer.stop()
177179
this.timer.start()
178180
}
179181

@@ -469,6 +471,42 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
469471
return this.credentials?.organizationId || null
470472
}
471473

474+
/**
475+
* Switch to a different organization context
476+
* @param organizationId The organization ID to switch to, or null for personal account
477+
*/
478+
public async switchOrganization(organizationId: string | null): Promise<void> {
479+
if (!this.credentials) {
480+
throw new Error("Cannot switch organization: not authenticated")
481+
}
482+
483+
// Update the stored credentials with the new organization ID
484+
const updatedCredentials: AuthCredentials = {
485+
...this.credentials,
486+
organizationId: organizationId,
487+
}
488+
489+
// Store the updated credentials, handleCredentialsChange will handle the update
490+
await this.storeCredentials(updatedCredentials)
491+
}
492+
493+
/**
494+
* Get all organization memberships for the current user
495+
* @returns Array of organization memberships
496+
*/
497+
public async getOrganizationMemberships(): Promise<CloudOrganizationMembership[]> {
498+
if (!this.credentials) {
499+
return []
500+
}
501+
502+
try {
503+
return await this.clerkGetOrganizationMemberships()
504+
} catch (error) {
505+
this.log(`[auth] Failed to get organization memberships: ${error}`)
506+
return []
507+
}
508+
}
509+
472510
private async clerkSignIn(ticket: string): Promise<AuthCredentials> {
473511
const formData = new URLSearchParams()
474512
formData.append("strategy", "ticket")
@@ -653,9 +691,14 @@ export class WebAuthService extends EventEmitter<AuthServiceEvents> implements A
653691
}
654692

655693
private async clerkGetOrganizationMemberships(): Promise<CloudOrganizationMembership[]> {
694+
if (!this.credentials) {
695+
this.log("[auth] Cannot get organization memberships: missing credentials")
696+
return []
697+
}
698+
656699
const response = await fetch(`${getClerkBaseUrl()}/v1/me/organization_memberships`, {
657700
headers: {
658-
Authorization: `Bearer ${this.credentials!.clientToken}`,
701+
Authorization: `Bearer ${this.credentials.clientToken}`,
659702
"User-Agent": this.userAgent(),
660703
},
661704
signal: AbortSignal.timeout(10000),

packages/types/src/cloud.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -242,6 +242,7 @@ export interface AuthService extends EventEmitter<AuthServiceEvents> {
242242
login(landingPageSlug?: string): Promise<void>
243243
logout(): Promise<void>
244244
handleCallback(code: string | null, state: string | null, organizationId?: string | null): Promise<void>
245+
switchOrganization(organizationId: string | null): Promise<void>
245246

246247
// State methods
247248
getState(): AuthState
@@ -253,6 +254,9 @@ export interface AuthService extends EventEmitter<AuthServiceEvents> {
253254
getSessionToken(): string | undefined
254255
getUserInfo(): CloudUserInfo | null
255256
getStoredOrganizationId(): string | null
257+
258+
// Organization management
259+
getOrganizationMemberships(): Promise<CloudOrganizationMembership[]>
256260
}
257261

258262
/**

packages/types/src/global-settings.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ export const globalSettingsSchema = z.object({
147147
enhancementApiConfigId: z.string().optional(),
148148
includeTaskHistoryInEnhance: z.boolean().optional(),
149149
historyPreviewCollapsed: z.boolean().optional(),
150+
reasoningBlockCollapsed: z.boolean().optional(),
150151
profileThresholds: z.record(z.string(), z.number()).optional(),
151152
hasOpenedModeSelector: z.boolean().optional(),
152153
lastModeExportPath: z.string().optional(),

packages/types/src/providers/chutes.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ export type ChutesModelId =
2929
| "tngtech/DeepSeek-R1T-Chimera"
3030
| "zai-org/GLM-4.5-Air"
3131
| "zai-org/GLM-4.5-FP8"
32+
| "zai-org/GLM-4.5-turbo"
3233
| "moonshotai/Kimi-K2-Instruct-75k"
3334
| "moonshotai/Kimi-K2-Instruct-0905"
3435
| "Qwen/Qwen3-235B-A22B-Thinking-2507"
@@ -274,6 +275,15 @@ export const chutesModels = {
274275
description:
275276
"GLM-4.5-FP8 model with 128k token context window, optimized for agent-based applications with MoE architecture.",
276277
},
278+
"zai-org/GLM-4.5-turbo": {
279+
maxTokens: 32768,
280+
contextWindow: 131072,
281+
supportsImages: false,
282+
supportsPromptCache: false,
283+
inputPrice: 1,
284+
outputPrice: 3,
285+
description: "GLM-4.5-turbo model with 128K token context window, optimized for fast inference.",
286+
},
277287
"Qwen/Qwen3-Coder-480B-A35B-Instruct-FP8": {
278288
maxTokens: 32768,
279289
contextWindow: 262144,

releases/3.28.7-release.png

970 KB
Loading

0 commit comments

Comments
 (0)