Skip to content

Commit 2cb056f

Browse files
committed
Merge main
2 parents bb2937b + 6b8c21f commit 2cb056f

Some content is hidden

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

66 files changed

+1825
-175
lines changed

CHANGELOG.md

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

3+
## [3.28.16] - 2025-10-09
4+
5+
![3.28.16 Release - Expanded Context Window](/releases/3.28.16-release.png)
6+
7+
- feat: Add Claude Sonnet 4.5 1M context window support for Claude Code (thanks @ColbySerpa!)
8+
- feat: Identify cloud tasks in the extension bridge (thanks @cte!)
9+
- fix: Add the parent task ID in telemetry (thanks @mrubens!)
10+
11+
## [3.28.15] - 2025-10-03
12+
13+
![3.28.15 Release - Kangaroo Sliding Down a Chute](/releases/3.28.15-release.png)
14+
15+
- Add new DeepSeek and GLM models with detailed descriptions to the Chutes provider (thanks @mohammad154!)
16+
- Fix: properly reset cost limit tracking when user clicks "Reset and Continue" (#6889 by @alecoot, PR by app/roomote)
17+
- Fix: improve save button activation in prompts settings (#5780 by @beccare, PR by app/roomote)
18+
- Fix: overeager 'there are unsaved changes' dialog in settings (thanks @brunobergher!)
19+
- Fix: show send button when only images are selected in chat textarea (thanks app/roomote!)
20+
- Fix: Claude Sonnet 4.5 compatibility improvements (thanks @mrubens!)
21+
- Add UsageStats schema and type for better analytics tracking (thanks app/roomote!)
22+
- Include reasoning messages in cloud tasks (thanks @mrubens!)
23+
- Security: update dependency vite to v6.3.6 (thanks app/renovate!)
24+
- Deprecate free grok 4 fast model (thanks @mrubens!)
25+
- Remove unsupported Gemini 2.5 Flash Image Preview free model (thanks @SannidhyaSah!)
26+
- Add structured data to the homepage for better SEO (thanks @mrubens!)
27+
- Update dependency glob to v11.0.3 (thanks app/renovate!)
28+
329
## [3.28.14] - 2025-09-30
430

531
![3.28.14 Release - GLM-4.6 Model Support](/releases/3.28.14-release.png)

apps/web-roo-code/src/app/page.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ import {
1414
} from "@/components/homepage"
1515
import { EXTERNAL_LINKS } from "@/lib/constants"
1616
import { ArrowRight } from "lucide-react"
17+
import { StructuredData } from "@/components/structured-data"
1718

1819
// Invalidate cache when a request comes in, at most once every hour.
1920
export const revalidate = 3600
@@ -23,6 +24,7 @@ export default async function Home() {
2324

2425
return (
2526
<>
27+
<StructuredData />
2628
<section className="relative flex h-[calc(125vh-theme(spacing.12))] items-center overflow-hidden md:h-[calc(80svh-theme(spacing.12))]">
2729
<AnimatedBackground />
2830
<div className="container relative flex items-center h-full z-10 mx-auto px-4 sm:px-6 lg:px-8">
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { getStructuredData } from "@/lib/structured-data"
2+
3+
/**
4+
* StructuredData Component
5+
*
6+
* Renders JSON-LD structured data in the document head for SEO.
7+
*
8+
* The structured data includes:
9+
* - Organization information (brand, logo, social profiles)
10+
* - WebSite metadata (site name for Google Search)
11+
* - SoftwareApplication details (VS Code extension)
12+
*
13+
* @see https://developers.google.com/search/docs/appearance/structured-data/intro-structured-data
14+
*/
15+
export function StructuredData() {
16+
const structuredData = getStructuredData()
17+
18+
return (
19+
<script
20+
type="application/ld+json"
21+
dangerouslySetInnerHTML={{
22+
__html: JSON.stringify(structuredData),
23+
}}
24+
/>
25+
)
26+
}

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ 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 and Beyond",
6+
title: "Roo Code – The AI dev team that gets things done",
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",
Lines changed: 127 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
import { SEO } from "./seo"
2+
import { EXTERNAL_LINKS } from "./constants"
3+
4+
/**
5+
* Type definitions for Schema.org structured data
6+
*/
7+
interface ImageObject {
8+
"@type": "ImageObject"
9+
url: string
10+
width: number
11+
height: number
12+
}
13+
14+
interface Organization {
15+
"@type": "Organization"
16+
"@id": string
17+
name: string
18+
url: string
19+
logo: ImageObject
20+
alternateName: string[]
21+
sameAs: string[]
22+
}
23+
24+
interface WebSite {
25+
"@type": "WebSite"
26+
"@id": string
27+
url: string
28+
name: string
29+
alternateName: string[]
30+
publisher: { "@id": string }
31+
}
32+
33+
interface SoftwareApplication {
34+
"@type": "SoftwareApplication"
35+
"@id": string
36+
name: string
37+
applicationCategory: string
38+
operatingSystem: string
39+
url: string
40+
downloadUrl: string
41+
offers: {
42+
"@type": "Offer"
43+
price: string
44+
priceCurrency: string
45+
}
46+
isAccessibleForFree: boolean
47+
publisher: { "@id": string }
48+
}
49+
50+
interface StructuredDataGraph {
51+
"@context": "https://schema.org"
52+
"@graph": [Organization, WebSite, SoftwareApplication]
53+
}
54+
55+
/**
56+
* Generates the complete JSON-LD structured data for SEO
57+
*
58+
* This includes:
59+
* - Organization schema (brand identity, logo, social profiles)
60+
* - WebSite schema (site name for Google Search)
61+
* - SoftwareApplication schema (VS Code extension metadata)
62+
*
63+
* @returns Complete structured data object ready for JSON-LD injection
64+
*/
65+
export function getStructuredData(): StructuredDataGraph {
66+
// Organization ID - used to link all entities
67+
const orgId = `${SEO.url}#org`
68+
69+
const organization: Organization = {
70+
"@type": "Organization",
71+
"@id": orgId,
72+
name: SEO.name,
73+
url: SEO.url,
74+
logo: {
75+
"@type": "ImageObject",
76+
url: `${SEO.url}/android-chrome-512x512.png`,
77+
width: 512,
78+
height: 512,
79+
},
80+
alternateName: ["RooCode"],
81+
sameAs: [
82+
EXTERNAL_LINKS.GITHUB,
83+
EXTERNAL_LINKS.MARKETPLACE,
84+
EXTERNAL_LINKS.X,
85+
EXTERNAL_LINKS.LINKEDIN,
86+
EXTERNAL_LINKS.REDDIT,
87+
EXTERNAL_LINKS.DISCORD,
88+
EXTERNAL_LINKS.YOUTUBE,
89+
],
90+
}
91+
92+
const website: WebSite = {
93+
"@type": "WebSite",
94+
"@id": `${SEO.url}#website`,
95+
url: SEO.url,
96+
name: SEO.name,
97+
alternateName: ["RooCode"],
98+
publisher: { "@id": orgId },
99+
}
100+
101+
const softwareApplication: SoftwareApplication = {
102+
"@type": "SoftwareApplication",
103+
"@id": `${SEO.url}#vscode-extension`,
104+
name: "Roo Code (VS Code extension)",
105+
applicationCategory: "DeveloperApplication",
106+
operatingSystem: "Windows, macOS, Linux",
107+
url: SEO.url,
108+
downloadUrl: EXTERNAL_LINKS.MARKETPLACE,
109+
offers: {
110+
"@type": "Offer",
111+
price: "0",
112+
priceCurrency: "USD",
113+
},
114+
isAccessibleForFree: true,
115+
publisher: { "@id": orgId },
116+
}
117+
118+
return {
119+
"@context": "https://schema.org",
120+
"@graph": [organization, website, softwareApplication],
121+
}
122+
}
123+
124+
/**
125+
* Type export for use in components
126+
*/
127+
export type { StructuredDataGraph }

packages/cloud/src/CloudService.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,12 @@ export class CloudService extends EventEmitter<CloudServiceEvents> implements Di
8383
return this._retryQueue
8484
}
8585

86+
private _isCloudAgent = false
87+
88+
public get isCloudAgent() {
89+
return this._isCloudAgent
90+
}
91+
8692
private constructor(context: ExtensionContext, log?: (...args: unknown[]) => void) {
8793
super()
8894

@@ -117,6 +123,7 @@ export class CloudService extends EventEmitter<CloudServiceEvents> implements Di
117123

118124
if (cloudToken && cloudToken.length > 0) {
119125
this._authService = new StaticTokenAuthService(this.context, cloudToken, this.log)
126+
this._isCloudAgent = true
120127
} else {
121128
this._authService = new WebAuthService(this.context, this.log)
122129
}
@@ -141,19 +148,19 @@ export class CloudService extends EventEmitter<CloudServiceEvents> implements Di
141148

142149
this._cloudAPI = new CloudAPI(this._authService, this.log)
143150

144-
// Initialize retry queue with auth header provider
151+
// Initialize retry queue with auth header provider.
145152
this._retryQueue = new RetryQueue(
146153
this.context,
147-
undefined, // Use default config
154+
undefined, // Use default config.
148155
this.log,
149156
() => {
150-
// Provide fresh auth headers for retries
157+
// Provide fresh auth headers for retries.
151158
const sessionToken = this._authService?.getSessionToken()
159+
152160
if (sessionToken) {
153-
return {
154-
Authorization: `Bearer ${sessionToken}`,
155-
}
161+
return { Authorization: `Bearer ${sessionToken}` }
156162
}
163+
157164
return undefined
158165
},
159166
)

packages/cloud/src/bridge/BaseChannel.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ export interface BaseChannelOptions {
77
instanceId: string
88
appProperties: StaticAppProperties
99
gitProperties?: GitProperties
10+
isCloudAgent: boolean
1011
}
1112

1213
/**
@@ -22,11 +23,13 @@ export abstract class BaseChannel<TCommand = unknown, TEventName extends string
2223
protected readonly instanceId: string
2324
protected readonly appProperties: StaticAppProperties
2425
protected readonly gitProperties?: GitProperties
26+
protected readonly isCloudAgent: boolean
2527

2628
constructor(options: BaseChannelOptions) {
2729
this.instanceId = options.instanceId
2830
this.appProperties = options.appProperties
2931
this.gitProperties = options.gitProperties
32+
this.isCloudAgent = options.isCloudAgent
3033
}
3134

3235
/**

packages/cloud/src/bridge/BridgeOrchestrator.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ export interface BridgeOrchestratorOptions {
2323
socketBridgeUrl: string
2424
token: string
2525
provider: TaskProviderLike
26-
sessionId?: string
26+
sessionId: string
27+
isCloudAgent: boolean
2728
}
2829

2930
/**
@@ -44,6 +45,7 @@ export class BridgeOrchestrator {
4445
private readonly instanceId: string
4546
private readonly appProperties: StaticAppProperties
4647
private readonly gitProperties?: GitProperties
48+
private readonly isCloudAgent?: boolean
4749

4850
// Components
4951
private socketTransport: SocketTransport
@@ -96,6 +98,7 @@ export class BridgeOrchestrator {
9698
if (!instance) {
9799
try {
98100
console.log(`[BridgeOrchestrator#connectOrDisconnect] Connecting...`)
101+
99102
// Populate telemetry properties before registering the instance.
100103
await options.provider.getTelemetryProperties()
101104

@@ -174,6 +177,7 @@ export class BridgeOrchestrator {
174177
this.instanceId = options.sessionId || crypto.randomUUID()
175178
this.appProperties = { ...options.provider.appProperties, hostname: os.hostname() }
176179
this.gitProperties = options.provider.gitProperties
180+
this.isCloudAgent = options.isCloudAgent
177181

178182
this.socketTransport = new SocketTransport({
179183
url: this.socketBridgeUrl,
@@ -200,12 +204,14 @@ export class BridgeOrchestrator {
200204
gitProperties: this.gitProperties,
201205
userId: this.userId,
202206
provider: this.provider,
207+
isCloudAgent: this.isCloudAgent,
203208
})
204209

205210
this.taskChannel = new TaskChannel({
206211
instanceId: this.instanceId,
207212
appProperties: this.appProperties,
208213
gitProperties: this.gitProperties,
214+
isCloudAgent: this.isCloudAgent,
209215
})
210216
}
211217

packages/cloud/src/bridge/ExtensionChannel.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@ export class ExtensionChannel extends BaseChannel<
4141
instanceId: options.instanceId,
4242
appProperties: options.appProperties,
4343
gitProperties: options.gitProperties,
44+
isCloudAgent: options.isCloudAgent,
4445
})
4546

4647
this.userId = options.userId
@@ -55,6 +56,7 @@ export class ExtensionChannel extends BaseChannel<
5556
lastHeartbeat: Date.now(),
5657
task: { taskId: "", taskStatus: TaskStatus.None },
5758
taskHistory: [],
59+
isCloudAgent: this.isCloudAgent,
5860
}
5961

6062
this.setupListeners()

packages/cloud/src/bridge/__tests__/ExtensionChannel.test.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ describe("ExtensionChannel", () => {
9595
appProperties,
9696
userId,
9797
provider: mockProvider,
98+
isCloudAgent: false,
9899
})
99100
})
100101

@@ -176,6 +177,7 @@ describe("ExtensionChannel", () => {
176177
appProperties,
177178
userId,
178179
provider: mockProvider,
180+
isCloudAgent: false,
179181
})
180182

181183
// Each event should have exactly 2 listeners (one from each channel)

0 commit comments

Comments
 (0)