Matt Rubens 2 месяцев назад
Родитель
Сommit
236957b818
44 измененных файлов с 480 добавлено и 1182 удалено
  1. 1 20
      packages/cloud/src/CloudAPI.ts
  2. 0 81
      packages/cloud/src/__tests__/CloudAPI.test.ts
  3. 0 29
      packages/types/src/cloud.ts
  4. 6 10
      packages/types/src/providers/chutes.ts
  5. 3 2
      src/core/webview/ClineProvider.ts
  6. 0 267
      src/core/webview/__tests__/webviewMessageHandler.cloudAgents.test.ts
  7. 0 49
      src/core/webview/webviewMessageHandler.ts
  8. 0 3
      src/shared/ExtensionMessage.ts
  9. 0 1
      src/shared/WebviewMessage.ts
  10. 2 2
      webview-ui/src/components/chat/ChatTextArea.tsx
  11. 56 31
      webview-ui/src/components/chat/ChatView.tsx
  12. 3 5
      webview-ui/src/components/chat/TaskHeader.tsx
  13. 59 30
      webview-ui/src/components/chat/__tests__/ChatView.spec.tsx
  14. 0 133
      webview-ui/src/components/cloud/CloudAgents.tsx
  15. 0 214
      webview-ui/src/components/cloud/__tests__/CloudAgents.spec.tsx
  16. 7 10
      webview-ui/src/components/history/HistoryPreview.tsx
  17. 2 2
      webview-ui/src/components/history/TaskItem.tsx
  18. 2 2
      webview-ui/src/components/history/TaskItemFooter.tsx
  19. 21 0
      webview-ui/src/components/history/__tests__/HistoryPreview.spec.tsx
  20. 15 0
      webview-ui/src/components/history/__tests__/TaskItem.spec.tsx
  21. 3 3
      webview-ui/src/components/welcome/RooHero.tsx
  22. 23 26
      webview-ui/src/components/welcome/RooTips.tsx
  23. 1 1
      webview-ui/src/components/welcome/WelcomeView.tsx
  24. 0 2
      webview-ui/src/context/ExtensionStateContext.tsx
  25. 15 14
      webview-ui/src/i18n/locales/ca/chat.json
  26. 15 14
      webview-ui/src/i18n/locales/de/chat.json
  27. 16 15
      webview-ui/src/i18n/locales/en/chat.json
  28. 1 1
      webview-ui/src/i18n/locales/en/cloud.json
  29. 1 1
      webview-ui/src/i18n/locales/en/history.json
  30. 15 14
      webview-ui/src/i18n/locales/es/chat.json
  31. 15 14
      webview-ui/src/i18n/locales/fr/chat.json
  32. 15 14
      webview-ui/src/i18n/locales/hi/chat.json
  33. 16 15
      webview-ui/src/i18n/locales/id/chat.json
  34. 15 14
      webview-ui/src/i18n/locales/it/chat.json
  35. 15 14
      webview-ui/src/i18n/locales/ja/chat.json
  36. 15 14
      webview-ui/src/i18n/locales/ko/chat.json
  37. 15 14
      webview-ui/src/i18n/locales/nl/chat.json
  38. 15 14
      webview-ui/src/i18n/locales/pl/chat.json
  39. 15 14
      webview-ui/src/i18n/locales/pt-BR/chat.json
  40. 14 14
      webview-ui/src/i18n/locales/ru/chat.json
  41. 16 15
      webview-ui/src/i18n/locales/tr/chat.json
  42. 16 15
      webview-ui/src/i18n/locales/vi/chat.json
  43. 16 15
      webview-ui/src/i18n/locales/zh-CN/chat.json
  44. 15 14
      webview-ui/src/i18n/locales/zh-TW/chat.json

+ 1 - 20
packages/cloud/src/CloudAPI.ts

@@ -1,13 +1,6 @@
 import { z } from "zod"
 
-import {
-	type AuthService,
-	type ShareVisibility,
-	type ShareResponse,
-	shareResponseSchema,
-	type CloudAgent,
-	cloudAgentsResponseSchema,
-} from "@roo-code/types"
+import { type AuthService, type ShareVisibility, type ShareResponse, shareResponseSchema } from "@roo-code/types"
 
 import { getRooCodeApiUrl } from "./config.js"
 import { getUserAgent } from "./utils.js"
@@ -141,16 +134,4 @@ export class CloudAPI {
 					.parse(data),
 		})
 	}
-
-	async getCloudAgents(): Promise<CloudAgent[]> {
-		this.log("[CloudAPI] Fetching cloud agents")
-
-		const agents = await this.request<CloudAgent[]>("/api/cloud-agents", {
-			method: "GET",
-			parseResponse: (data) => cloudAgentsResponseSchema.parse(data).data,
-		})
-
-		this.log("[CloudAPI] Cloud agents response:", agents)
-		return agents
-	}
 }

+ 0 - 81
packages/cloud/src/__tests__/CloudAPI.test.ts

@@ -1,81 +0,0 @@
-import { describe, it, expect, vi, beforeEach } from "vitest"
-import { CloudAPI } from "../CloudAPI.js"
-import { AuthenticationError } from "../errors.js"
-import type { AuthService } from "@roo-code/types"
-
-// Mock fetch globally
-global.fetch = vi.fn()
-
-describe("CloudAPI", () => {
-	let mockAuthService: Partial<AuthService>
-	let cloudAPI: CloudAPI
-
-	beforeEach(() => {
-		// Mock only the methods we need for testing
-		mockAuthService = {
-			getSessionToken: vi.fn().mockReturnValue("test-token"),
-		}
-
-		cloudAPI = new CloudAPI(mockAuthService as AuthService)
-		vi.clearAllMocks()
-	})
-
-	describe("getCloudAgents", () => {
-		it("should return cloud agents on success", async () => {
-			const mockAgents = [
-				{ id: "1", name: "Agent 1", type: "code", icon: "code" },
-				{ id: "2", name: "Agent 2", type: "chat", icon: "chat" },
-			]
-
-			// Mock successful response with schema-compliant format
-			;(global.fetch as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
-				ok: true,
-				json: async () => ({ success: true, data: mockAgents }),
-			})
-
-			const agents = await cloudAPI.getCloudAgents()
-
-			expect(agents).toEqual(mockAgents)
-			expect(global.fetch).toHaveBeenCalledWith(
-				expect.stringContaining("/api/cloud-agents"),
-				expect.objectContaining({
-					method: "GET",
-					headers: expect.objectContaining({
-						Authorization: "Bearer test-token",
-					}),
-				}),
-			)
-		})
-
-		it("should throw AuthenticationError on 401 response", async () => {
-			// Mock 401 response
-			;(global.fetch as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
-				ok: false,
-				status: 401,
-				statusText: "Unauthorized",
-				json: async () => ({ error: "Authentication required" }),
-			})
-
-			await expect(cloudAPI.getCloudAgents()).rejects.toThrow(AuthenticationError)
-		})
-
-		it("should throw AuthenticationError when no session token", async () => {
-			// Mock no session token
-			mockAuthService.getSessionToken = vi.fn().mockReturnValue(null)
-
-			await expect(cloudAPI.getCloudAgents()).rejects.toThrow(AuthenticationError)
-		})
-
-		it("should return empty array when agents array is empty", async () => {
-			// Mock response with empty agents array
-			;(global.fetch as ReturnType<typeof vi.fn>).mockResolvedValueOnce({
-				ok: true,
-				json: async () => ({ success: true, data: [] }),
-			})
-
-			const agents = await cloudAPI.getCloudAgents()
-
-			expect(agents).toEqual([])
-		})
-	})
-})

+ 0 - 29
packages/types/src/cloud.ts

@@ -723,35 +723,6 @@ export type LeaveResponse = {
 	timestamp?: string
 }
 
-/**
- * CloudAgent
- */
-
-export interface CloudAgent {
-	id: string
-	name: string
-	type: string // e.g., "PR Reviewer", "Documentation Writer"
-	icon?: string // e.g., "pr-reviewer", "documentation-writer"
-}
-
-/**
- * CloudAgents API Response
- */
-
-export const cloudAgentsResponseSchema = z.object({
-	success: z.boolean(),
-	data: z.array(
-		z.object({
-			id: z.string(),
-			name: z.string(),
-			type: z.string(),
-			icon: z.string().optional(),
-		}),
-	),
-})
-
-export type CloudAgentsResponse = z.infer<typeof cloudAgentsResponseSchema>
-
 /**
  * UsageStats
  */

+ 6 - 10
packages/types/src/providers/chutes.ts

@@ -87,8 +87,7 @@ export const chutesModels = {
 		supportsPromptCache: false,
 		inputPrice: 0.23,
 		outputPrice: 0.9,
-		description:
-			"DeepSeek‑V3.1‑Terminus is an update to V3.1 that improves language consistency by reducing CN/EN mix‑ups and eliminating random characters, while strengthening agent capabilities with notably better Code Agent and Search Agent performance.",
+		description: "DeepSeek‑V3.1‑Terminus is an update to V3.1 that improves language consistency by reducing CN/EN mix‑ups and eliminating random characters, while strengthening agent capabilities with notably better Code Agent and Search Agent performance.",
 	},
 	"deepseek-ai/DeepSeek-V3.1-turbo": {
 		maxTokens: 32768,
@@ -97,8 +96,7 @@ export const chutesModels = {
 		supportsPromptCache: false,
 		inputPrice: 1.0,
 		outputPrice: 3.0,
-		description:
-			"DeepSeek-V3.1-turbo is an FP8, speculative-decoding turbo variant optimized for ultra-fast single-shot queries (~200 TPS), with outputs close to the originals and solid function calling/reasoning/structured output, priced at $1/M input and $3/M output tokens, using 2× quota per request and not intended for bulk workloads.",
+		description: "DeepSeek-V3.1-turbo is an FP8, speculative-decoding turbo variant optimized for ultra-fast single-shot queries (~200 TPS), with outputs close to the originals and solid function calling/reasoning/structured output, priced at $1/M input and $3/M output tokens, using 2× quota per request and not intended for bulk workloads.",
 	},
 	"deepseek-ai/DeepSeek-V3.2-Exp": {
 		maxTokens: 163840,
@@ -107,8 +105,7 @@ export const chutesModels = {
 		supportsPromptCache: false,
 		inputPrice: 0.25,
 		outputPrice: 0.35,
-		description:
-			"DeepSeek-V3.2-Exp is an experimental LLM that introduces DeepSeek Sparse Attention to improve long‑context training and inference efficiency while maintaining performance comparable to V3.1‑Terminus.",
+		description: "DeepSeek-V3.2-Exp is an experimental LLM that introduces DeepSeek Sparse Attention to improve long‑context training and inference efficiency while maintaining performance comparable to V3.1‑Terminus.",
 	},
 	"unsloth/Llama-3.3-70B-Instruct": {
 		maxTokens: 32768, // From Groq
@@ -390,9 +387,8 @@ export const chutesModels = {
 		contextWindow: 262144,
 		supportsImages: true,
 		supportsPromptCache: false,
-		inputPrice: 0.16,
-		outputPrice: 0.65,
-		description:
-			"Qwen3‑VL‑235B‑A22B‑Thinking is an open‑weight MoE vision‑language model (235B total, ~22B activated) optimized for deliberate multi‑step reasoning with strong text‑image‑video understanding and long‑context capabilities.",
+		inputPrice: 0.1600,
+		outputPrice: 0.6500,
+		description: "Qwen3‑VL‑235B‑A22B‑Thinking is an open‑weight MoE vision‑language model (235B total, ~22B activated) optimized for deliberate multi‑step reasoning with strong text‑image‑video understanding and long‑context capabilities.",
 	},
 } as const satisfies Record<string, ModelInfo>

+ 3 - 2
src/core/webview/ClineProvider.ts

@@ -1034,11 +1034,12 @@ export class ClineProvider
 				window.__vite_plugin_react_preamble_installed__ = true
 			</script>
 		`
+
 		const csp = [
 			"default-src 'none'",
 			`font-src ${webview.cspSource} data:`,
 			`style-src ${webview.cspSource} 'unsafe-inline' https://* http://${localServerUrl} http://0.0.0.0:${localPort}`,
-			`img-src ${webview.cspSource} https://storage.googleapis.com https://img.clerk.com ${getRooCodeApiUrl()} data:`,
+			`img-src ${webview.cspSource} https://storage.googleapis.com https://img.clerk.com data:`,
 			`media-src ${webview.cspSource}`,
 			`script-src 'unsafe-eval' ${webview.cspSource} https://* https://*.posthog.com http://${localServerUrl} http://0.0.0.0:${localPort} 'nonce-${nonce}'`,
 			`connect-src ${webview.cspSource} https://* https://*.posthog.com ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort}`,
@@ -1123,7 +1124,7 @@ export class ClineProvider
             <meta charset="utf-8">
             <meta name="viewport" content="width=device-width,initial-scale=1,shrink-to-fit=no">
             <meta name="theme-color" content="#000000">
-            <meta http-equiv="Content-Security-Policy" content="default-src 'none'; font-src ${webview.cspSource} data:; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} https://storage.googleapis.com https://img.clerk.com ${getRooCodeApiUrl()} data:; media-src ${webview.cspSource}; script-src ${webview.cspSource} 'wasm-unsafe-eval' 'nonce-${nonce}' https://us-assets.i.posthog.com 'strict-dynamic'; connect-src ${webview.cspSource} https://openrouter.ai https://api.requesty.ai https://us.i.posthog.com https://us-assets.i.posthog.com;">
+            <meta http-equiv="Content-Security-Policy" content="default-src 'none'; font-src ${webview.cspSource} data:; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} https://storage.googleapis.com https://img.clerk.com data:; media-src ${webview.cspSource}; script-src ${webview.cspSource} 'wasm-unsafe-eval' 'nonce-${nonce}' https://us-assets.i.posthog.com 'strict-dynamic'; connect-src ${webview.cspSource} https://openrouter.ai https://api.requesty.ai https://us.i.posthog.com https://us-assets.i.posthog.com;">
             <link rel="stylesheet" type="text/css" href="${stylesUri}">
 			<link href="${codiconsUri}" rel="stylesheet" />
 			<script nonce="${nonce}">

+ 0 - 267
src/core/webview/__tests__/webviewMessageHandler.cloudAgents.test.ts

@@ -1,267 +0,0 @@
-import { describe, it, expect, vi, beforeEach, type Mock } from "vitest"
-import * as vscode from "vscode"
-import { webviewMessageHandler } from "../webviewMessageHandler"
-import type { ClineProvider } from "../ClineProvider"
-
-// Mock vscode with all required exports
-vi.mock("vscode", () => ({
-	window: {
-		showErrorMessage: vi.fn(),
-		showInformationMessage: vi.fn(),
-		showWarningMessage: vi.fn(),
-	},
-	workspace: {
-		workspaceFolders: [],
-		getConfiguration: vi.fn(() => ({
-			get: vi.fn(),
-			update: vi.fn(),
-		})),
-	},
-	Uri: {
-		parse: vi.fn((str: string) => ({ fsPath: str })),
-		file: vi.fn((str: string) => ({ fsPath: str })),
-	},
-	commands: {
-		executeCommand: vi.fn(),
-	},
-	env: {
-		openExternal: vi.fn(),
-		clipboard: {
-			writeText: vi.fn(),
-		},
-	},
-}))
-
-// Create AuthenticationError class for testing
-class AuthenticationError extends Error {
-	constructor(message = "Authentication required") {
-		super(message)
-		this.name = "AuthenticationError"
-	}
-}
-
-// Mock CloudService with a factory function to allow resetting
-const createMockCloudService = () => {
-	let instance: any = null
-	return {
-		hasInstance: vi.fn(() => !!instance),
-		instance: null as any,
-		setInstance: (newInstance: any) => {
-			instance = newInstance
-			return instance
-		},
-		getInstance: () => instance,
-	}
-}
-
-let mockCloudService = createMockCloudService()
-
-// Mock CloudService
-vi.mock("@roo-code/cloud", () => ({
-	CloudService: {
-		get hasInstance() {
-			return mockCloudService.hasInstance
-		},
-		get instance() {
-			return mockCloudService.getInstance()
-		},
-	},
-}))
-
-// Mock i18n
-vi.mock("../../../i18n", () => ({
-	t: (key: string) => key,
-	changeLanguage: vi.fn(),
-}))
-
-// Mock other dependencies that might be imported
-vi.mock("../../task-persistence", () => ({
-	saveTaskMessages: vi.fn(),
-}))
-
-vi.mock("../../../utils/safeWriteJson", () => ({
-	safeWriteJson: vi.fn(),
-}))
-
-vi.mock("../../../shared/package", () => ({
-	Package: {
-		name: "test-package",
-	},
-}))
-
-vi.mock("../../../shared/api", () => ({
-	toRouterName: vi.fn((name: string) => name),
-}))
-
-vi.mock("../../../shared/experiments", () => ({
-	experimentDefault: {},
-}))
-
-vi.mock("../../../shared/modes", () => ({
-	defaultModeSlug: "code",
-}))
-
-vi.mock("../generateSystemPrompt", () => ({
-	generateSystemPrompt: vi.fn(),
-}))
-
-vi.mock("../messageEnhancer", () => ({
-	MessageEnhancer: {
-		enhanceMessage: vi.fn(),
-		captureTelemetry: vi.fn(),
-	},
-}))
-
-vi.mock("@roo-code/telemetry", () => ({
-	TelemetryService: {
-		hasInstance: vi.fn(() => false),
-		instance: null,
-	},
-	TelemetryEventName: {},
-}))
-
-describe("webviewMessageHandler - getCloudAgents", () => {
-	let mockProvider: Partial<ClineProvider>
-	let postMessageToWebview: Mock
-	let log: Mock
-
-	beforeEach(() => {
-		vi.clearAllMocks()
-		// Reset CloudService mock for each test
-		mockCloudService = createMockCloudService()
-
-		postMessageToWebview = vi.fn()
-		log = vi.fn()
-
-		mockProvider = {
-			postMessageToWebview,
-			log,
-			// Add other required provider properties as needed
-		}
-	})
-
-	it("should handle CloudService not initialized", async () => {
-		// CloudService.hasInstance will return false because instance is null
-
-		await webviewMessageHandler(mockProvider as ClineProvider, { type: "getCloudAgents" })
-
-		expect(log).toHaveBeenCalledWith("[getCloudAgents] CloudService not initialized")
-		expect(postMessageToWebview).toHaveBeenCalledWith({
-			type: "cloudAgents",
-			agents: [],
-			error: "CloudService not initialized",
-		})
-	})
-
-	it("should handle CloudAPI not available", async () => {
-		// Set instance with null cloudAPI
-		mockCloudService.setInstance({
-			cloudAPI: null,
-		})
-
-		await webviewMessageHandler(mockProvider as ClineProvider, { type: "getCloudAgents" })
-
-		expect(log).toHaveBeenCalledWith("[getCloudAgents] CloudAPI not available")
-		expect(postMessageToWebview).toHaveBeenCalledWith({
-			type: "cloudAgents",
-			agents: [],
-			error: "CloudAPI not available",
-		})
-	})
-
-	it("should successfully fetch cloud agents", async () => {
-		const mockAgents = [
-			{ id: "1", name: "Agent 1", type: "code", icon: "code" },
-			{ id: "2", name: "Agent 2", type: "chat", icon: "chat" },
-		]
-
-		const mockCloudAPI = {
-			getCloudAgents: vi.fn().mockResolvedValue(mockAgents),
-		}
-
-		// Set instance with mock cloudAPI
-		mockCloudService.setInstance({
-			cloudAPI: mockCloudAPI,
-		})
-
-		await webviewMessageHandler(mockProvider as ClineProvider, { type: "getCloudAgents" })
-
-		expect(log).toHaveBeenCalledWith("[getCloudAgents] Fetching cloud agents")
-		expect(log).toHaveBeenCalledWith("[getCloudAgents] Fetched 2 cloud agents")
-		expect(postMessageToWebview).toHaveBeenCalledWith({
-			type: "cloudAgents",
-			agents: mockAgents,
-		})
-	})
-
-	it("should handle authentication errors silently", async () => {
-		const authError = new AuthenticationError("Authentication required")
-
-		const mockCloudAPI = {
-			getCloudAgents: vi.fn().mockRejectedValue(authError),
-		}
-
-		// Set instance with mock cloudAPI
-		mockCloudService.setInstance({
-			cloudAPI: mockCloudAPI,
-		})
-
-		await webviewMessageHandler(mockProvider as ClineProvider, { type: "getCloudAgents" })
-
-		expect(log).toHaveBeenCalledWith("[getCloudAgents] Error fetching cloud agents: Authentication required")
-		expect(postMessageToWebview).toHaveBeenCalledWith({
-			type: "cloudAgents",
-			agents: [],
-			error: "Authentication required",
-		})
-		// Should NOT show error message - handled silently
-		expect(vscode.window.showErrorMessage).not.toHaveBeenCalled()
-	})
-
-	it("should handle general errors without showing auth message", async () => {
-		const genericError = new Error("Network error")
-
-		const mockCloudAPI = {
-			getCloudAgents: vi.fn().mockRejectedValue(genericError),
-		}
-
-		// Set instance with mock cloudAPI
-		mockCloudService.setInstance({
-			cloudAPI: mockCloudAPI,
-		})
-
-		await webviewMessageHandler(mockProvider as ClineProvider, { type: "getCloudAgents" })
-
-		expect(log).toHaveBeenCalledWith("[getCloudAgents] Error fetching cloud agents: Network error")
-		expect(postMessageToWebview).toHaveBeenCalledWith({
-			type: "cloudAgents",
-			agents: [],
-			error: "Network error",
-		})
-		// Should NOT show auth error message for general errors
-		expect(vscode.window.showErrorMessage).not.toHaveBeenCalled()
-	})
-
-	it("should handle 401 errors silently", async () => {
-		const error401 = new Error("HTTP 401: Unauthorized")
-
-		const mockCloudAPI = {
-			getCloudAgents: vi.fn().mockRejectedValue(error401),
-		}
-
-		// Set instance with mock cloudAPI
-		mockCloudService.setInstance({
-			cloudAPI: mockCloudAPI,
-		})
-
-		await webviewMessageHandler(mockProvider as ClineProvider, { type: "getCloudAgents" })
-
-		expect(postMessageToWebview).toHaveBeenCalledWith({
-			type: "cloudAgents",
-			agents: [],
-			error: "HTTP 401: Unauthorized",
-		})
-		// Should NOT show error message - handled silently
-		expect(vscode.window.showErrorMessage).not.toHaveBeenCalled()
-	})
-})

+ 0 - 49
src/core/webview/webviewMessageHandler.ts

@@ -2431,55 +2431,6 @@ export const webviewMessageHandler = async (
 			}
 			break
 		}
-		case "getCloudAgents": {
-			try {
-				// Ensure CloudService is initialized
-				if (!CloudService.hasInstance()) {
-					provider.log("[getCloudAgents] CloudService not initialized")
-					await provider.postMessageToWebview({
-						type: "cloudAgents",
-						agents: [],
-						error: "CloudService not initialized",
-					})
-					break
-				}
-
-				// Fetch cloud agents using the CloudAPI instance
-				const cloudAPI = CloudService.instance.cloudAPI
-				if (!cloudAPI) {
-					provider.log("[getCloudAgents] CloudAPI not available")
-					await provider.postMessageToWebview({
-						type: "cloudAgents",
-						agents: [],
-						error: "CloudAPI not available",
-					})
-					break
-				}
-
-				provider.log("[getCloudAgents] Fetching cloud agents")
-				const agents = await cloudAPI.getCloudAgents()
-				provider.log(`[getCloudAgents] Fetched ${agents.length} cloud agents`)
-
-				// Send the agents back to the webview
-				await provider.postMessageToWebview({
-					type: "cloudAgents",
-					agents: agents,
-				})
-			} catch (error) {
-				provider.log(
-					`[getCloudAgents] Error fetching cloud agents: ${error instanceof Error ? error.message : String(error)}`,
-				)
-
-				// Send response to stop loading state in UI
-				// The CloudAgents component will handle this gracefully by returning null
-				await provider.postMessageToWebview({
-					type: "cloudAgents",
-					agents: [],
-					error: error instanceof Error ? error.message : String(error),
-				})
-			}
-			break
-		}
 
 		case "saveCodeIndexSettingsAtomic": {
 			if (!message.codeIndexSettings) {

+ 0 - 3
src/shared/ExtensionMessage.ts

@@ -14,7 +14,6 @@ import type {
 	OrganizationAllowList,
 	ShareVisibility,
 	QueuedMessage,
-	CloudAgent,
 } from "@roo-code/types"
 
 import { GitCommit } from "../utils/git"
@@ -127,7 +126,6 @@ export interface ExtensionMessage {
 		| "insertTextIntoTextarea"
 		| "dismissedUpsells"
 		| "organizationSwitchResult"
-		| "cloudAgents"
 	text?: string
 	payload?: any // Add a generic payload for now, can refine later
 	action?:
@@ -207,7 +205,6 @@ export interface ExtensionMessage {
 	queuedMessages?: QueuedMessage[]
 	list?: string[] // For dismissedUpsells
 	organizationId?: string | null // For organizationSwitchResult
-	agents?: CloudAgent[] // For cloudAgents
 }
 
 export type ExtensionState = Pick<

+ 0 - 1
src/shared/WebviewMessage.ts

@@ -185,7 +185,6 @@ export interface WebviewMessage {
 		| "rooCloudSignOut"
 		| "rooCloudManualUrl"
 		| "switchOrganization"
-		| "getCloudAgents"
 		| "condenseTaskContextRequest"
 		| "requestIndexingStatus"
 		| "startIndexing"

+ 2 - 2
webview-ui/src/components/chat/ChatTextArea.tsx

@@ -979,7 +979,7 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
 								"flex-col-reverse",
 								"min-h-0",
 								"overflow-hidden",
-								"rounded-lg",
+								"rounded",
 							)}>
 							<div
 								ref={highlightLayerRef}
@@ -1005,7 +1005,7 @@ export const ChatTextArea = forwardRef<HTMLTextAreaElement, ChatTextAreaProps>(
 									isEditMode ? "pr-20" : "pr-9",
 									"z-10",
 									"forced-color-adjust-none",
-									"rounded-lg",
+									"rounded",
 								)}
 								style={{
 									color: "transparent",

+ 56 - 31
webview-ui/src/components/chat/ChatView.tsx

@@ -44,6 +44,7 @@ import { CloudUpsellDialog } from "@src/components/cloud/CloudUpsellDialog"
 
 import TelemetryBanner from "../common/TelemetryBanner"
 import VersionIndicator from "../common/VersionIndicator"
+import { useTaskSearch } from "../history/useTaskSearch"
 import HistoryPreview from "../history/HistoryPreview"
 import Announcement from "./Announcement"
 import BrowserSessionRow from "./BrowserSessionRow"
@@ -57,7 +58,6 @@ import { QueuedMessages } from "./QueuedMessages"
 import DismissibleUpsell from "../common/DismissibleUpsell"
 import { useCloudUpsell } from "@src/hooks/useCloudUpsell"
 import { Cloud } from "lucide-react"
-import CloudAgents from "../cloud/CloudAgents"
 
 export interface ChatViewProps {
 	isHidden: boolean
@@ -118,6 +118,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 		customModes,
 		telemetrySetting,
 		hasSystemPromptOverride,
+		historyPreviewCollapsed, // Added historyPreviewCollapsed
 		soundEnabled,
 		soundVolume,
 		cloudIsAuthenticated,
@@ -130,6 +131,20 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 		messagesRef.current = messages
 	}, [messages])
 
+	const { tasks } = useTaskSearch()
+
+	// Initialize expanded state based on the persisted setting (default to expanded if undefined)
+	const [isExpanded, setIsExpanded] = useState(
+		historyPreviewCollapsed === undefined ? true : !historyPreviewCollapsed,
+	)
+
+	const toggleExpanded = useCallback(() => {
+		const newState = !isExpanded
+		setIsExpanded(newState)
+		// Send message to extension to persist the new collapsed state
+		vscode.postMessage({ type: "setHistoryPreviewCollapsed", bool: !newState })
+	}, [isExpanded])
+
 	// Leaving this less safe version here since if the first message is not a
 	// task, then the extension is in a bad state and needs to be debugged (see
 	// Cline.abort).
@@ -1802,42 +1817,53 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 					)}
 				</>
 			) : (
-				<div className="flex flex-col h-full justify-center p-6 min-h-0 overflow-y-auto gap-4 relative">
-					<div className="flex flex-col items-start gap-2 justify-center max-w-md h-full">
+				<div className="flex-1 min-h-0 overflow-y-auto flex flex-col gap-4 relative">
+					{/* Moved Task Bar Header Here */}
+					{tasks.length !== 0 && (
+						<div className="flex text-vscode-descriptionForeground w-full mx-auto px-5 pt-3">
+							<div className="flex items-center gap-1 cursor-pointer" onClick={toggleExpanded}>
+								{tasks.length < 10 && (
+									<span className={`font-medium text-xs `}>{t("history:recentTasks")}</span>
+								)}
+								<span
+									className={`codicon  ${isExpanded ? "codicon-eye" : "codicon-eye-closed"} scale-90`}
+								/>
+							</div>
+						</div>
+					)}
+					<div
+						className={` w-full flex flex-col gap-4 m-auto ${isExpanded && tasks.length > 0 ? "mt-0" : ""} px-3.5 min-[370px]:px-10 pt-5 transition-all duration-300`}>
+						{/* Version indicator in top-right corner - only on welcome screen */}
 						<VersionIndicator
 							onClick={() => setShowAnnouncementModal(true)}
 							className="absolute top-2 right-3 z-10"
 						/>
 
-						<div className="flex flex-col gap-4 w-full">
-							<RooHero />
-
-							{/* New users should see tips */}
-							{taskHistory.length < 4 && <RooTips />}
+						<RooHero />
 
-							{/* Everyone should see their task history if any */}
-							{taskHistory.length > 0 && <HistoryPreview />}
+						<div className="mb-2.5">
+							{cloudIsAuthenticated || taskHistory.length < 4 ? (
+								<RooTips />
+							) : (
+								<>
+									<DismissibleUpsell
+										upsellId="taskList"
+										icon={<Cloud className="size-4 mt-0.5 shrink-0" />}
+										onClick={() => openUpsell()}
+										dismissOnClick={false}
+										className="bg-vscode-editor-background p-4 !text-base">
+										<Trans
+											i18nKey="cloud:upsell.taskList"
+											components={{
+												learnMoreLink: <VSCodeLink href="#" />,
+											}}
+										/>
+									</DismissibleUpsell>
+								</>
+							)}
 						</div>
-
-						{cloudIsAuthenticated ? (
-							// Logged in users should always see their agents (or be upsold)
-							<CloudAgents />
-						) : (
-							// Logged out users should be upsold at least once on Cloud
-							<DismissibleUpsell
-								upsellId="taskList"
-								icon={<Cloud className="size-5 mt-0.5 shrink-0" />}
-								onClick={() => openUpsell()}
-								dismissOnClick={false}
-								className="!bg-vscode-editor-background mt-6 border-border rounded-xl pl-4 pr-3 py-3 !text-base">
-								<Trans
-									i18nKey="cloud:upsell.taskList"
-									components={{
-										learnMoreLink: <VSCodeLink href="#" />,
-									}}
-								/>
-							</DismissibleUpsell>
-						)}
+						{/* Show the task history preview if expanded and tasks exist */}
+						{taskHistory.length > 0 && isExpanded && <HistoryPreview />}
 					</div>
 				</div>
 			)}
@@ -1963,7 +1989,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 					}
 				}}
 			/>
-
 			<ChatTextArea
 				ref={textAreaRef}
 				inputValue={inputValue}

+ 3 - 5
webview-ui/src/components/chat/TaskHeader.tsx

@@ -112,10 +112,10 @@ const TaskHeader = ({
 			)}
 			<div
 				className={cn(
-					"px-3 pt-2.5 pb-2 flex flex-col gap-1.5 relative z-1 cursor-pointer",
+					"px-2.5 pt-2.5 pb-2 flex flex-col gap-1.5 relative z-1 cursor-pointer",
 					"bg-vscode-input-background hover:bg-vscode-input-background/90",
 					"text-vscode-foreground/80 hover:text-vscode-foreground",
-					"shadow-sm shadow-black/30 rounded-xl",
+					"shadow-sm shadow-black/30 rounded-md",
 					hasTodos && "border-b-0",
 				)}
 				onClick={(e) => {
@@ -163,9 +163,7 @@ const TaskHeader = ({
 					</div>
 				</div>
 				{!isTaskExpanded && contextWindow > 0 && (
-					<div
-						className="flex items-center gap-2 text-sm text-muted-foreground/70"
-						onClick={(e) => e.stopPropagation()}>
+					<div className="flex items-center gap-2 text-sm" onClick={(e) => e.stopPropagation()}>
 						<StandardTooltip
 							content={
 								<div className="space-y-1">

+ 59 - 30
webview-ui/src/components/chat/__tests__/ChatView.spec.tsx

@@ -61,13 +61,6 @@ vi.mock("../AutoApproveMenu", () => ({
 	default: () => null,
 }))
 
-// Mock CloudAgents component
-vi.mock("../../cloud/CloudAgents", () => ({
-	default: function MockCloudAgents() {
-		return <div data-testid="cloud-agents">Cloud Agents</div>
-	},
-}))
-
 // Mock VersionIndicator - returns null by default to prevent rendering in tests
 vi.mock("../../common/VersionIndicator", () => ({
 	default: vi.fn(() => null),
@@ -1275,10 +1268,10 @@ describe("ChatView - Version Indicator Tests", () => {
 	})
 })
 
-describe("ChatView - DismissibleUpsell and RooTips Display Tests", () => {
+describe("ChatView - DismissibleUpsell Display Tests", () => {
 	beforeEach(() => vi.clearAllMocks())
 
-	it("does not show DismissibleUpsell when user is authenticated to Cloud", async () => {
+	it("does not show DismissibleUpsell when user is authenticated to Cloud", () => {
 		const { queryByTestId } = renderChatView()
 
 		// Hydrate state with user authenticated to cloud
@@ -1293,16 +1286,29 @@ describe("ChatView - DismissibleUpsell and RooTips Display Tests", () => {
 			clineMessages: [], // No active task
 		})
 
-		// Wait for the state to be updated and component to re-render
-		await waitFor(() => {
-			// CloudAgents should be shown instead of DismissibleUpsell when authenticated
-			expect(queryByTestId("cloud-agents")).toBeInTheDocument()
-			// Should not show DismissibleUpsell when authenticated
-			expect(queryByTestId("dismissible-upsell")).not.toBeInTheDocument()
+		// Should not show DismissibleUpsell when authenticated
+		expect(queryByTestId("dismissible-upsell")).not.toBeInTheDocument()
+	})
+
+	it("does not show DismissibleUpsell when user has only run 3 tasks in their history", () => {
+		const { queryByTestId } = renderChatView()
+
+		// Hydrate state with user not authenticated but only 3 tasks
+		mockPostMessage({
+			cloudIsAuthenticated: false,
+			taskHistory: [
+				{ id: "1", ts: Date.now() - 2000 },
+				{ id: "2", ts: Date.now() - 1000 },
+				{ id: "3", ts: Date.now() },
+			],
+			clineMessages: [], // No active task
 		})
+
+		// Should not show DismissibleUpsell with less than 4 tasks
+		expect(queryByTestId("dismissible-upsell")).not.toBeInTheDocument()
 	})
 
-	it("shows DismissibleUpsell when user is not authenticated", async () => {
+	it("shows DismissibleUpsell when user is not authenticated and has run 4 or more tasks", async () => {
 		const { getByTestId } = renderChatView()
 
 		// Hydrate state with user not authenticated and 4 tasks
@@ -1323,7 +1329,29 @@ describe("ChatView - DismissibleUpsell and RooTips Display Tests", () => {
 		})
 	})
 
-	it("does not show any home screen elements when there is an active task (regardless of auth status)", async () => {
+	it("shows DismissibleUpsell when user is not authenticated and has run 5 tasks", async () => {
+		const { getByTestId } = renderChatView()
+
+		// Hydrate state with user not authenticated and 5 tasks
+		mockPostMessage({
+			cloudIsAuthenticated: false,
+			taskHistory: [
+				{ id: "1", ts: Date.now() - 4000 },
+				{ id: "2", ts: Date.now() - 3000 },
+				{ id: "3", ts: Date.now() - 2000 },
+				{ id: "4", ts: Date.now() - 1000 },
+				{ id: "5", ts: Date.now() },
+			],
+			clineMessages: [], // No active task
+		})
+
+		// Wait for component to render and show DismissibleUpsell
+		await waitFor(() => {
+			expect(getByTestId("dismissible-upsell")).toBeInTheDocument()
+		})
+	})
+
+	it("does not show DismissibleUpsell when there is an active task (regardless of auth status)", async () => {
 		const { queryByTestId } = renderChatView()
 
 		// Hydrate state with active task
@@ -1356,13 +1384,14 @@ describe("ChatView - DismissibleUpsell and RooTips Display Tests", () => {
 		})
 	})
 
-	it("shows RooTips when the user has less than 4 tasks", () => {
-		const { queryByTestId } = renderChatView()
+	it("shows RooTips when user is authenticated (instead of DismissibleUpsell)", () => {
+		const { queryByTestId, getByTestId } = renderChatView()
 
 		// Hydrate state with user authenticated to cloud
 		mockPostMessage({
 			cloudIsAuthenticated: true,
 			taskHistory: [
+				{ id: "1", ts: Date.now() - 3000 },
 				{ id: "2", ts: Date.now() - 2000 },
 				{ id: "3", ts: Date.now() - 1000 },
 				{ id: "4", ts: Date.now() },
@@ -1371,27 +1400,27 @@ describe("ChatView - DismissibleUpsell and RooTips Display Tests", () => {
 		})
 
 		// Should not show DismissibleUpsell but should show RooTips
-		expect(queryByTestId("roo-tips")).toBeInTheDocument()
+		expect(queryByTestId("dismissible-upsell")).not.toBeInTheDocument()
+		expect(getByTestId("roo-tips")).toBeInTheDocument()
 	})
 
-	it("does not show RooTips when the user has more than 4 tasks", () => {
-		const { queryByTestId } = renderChatView()
+	it("shows RooTips when user has fewer than 4 tasks (instead of DismissibleUpsell)", () => {
+		const { queryByTestId, getByTestId } = renderChatView()
 
-		// Hydrate state with user authenticated to cloud
+		// Hydrate state with user not authenticated but fewer than 4 tasks
 		mockPostMessage({
-			cloudIsAuthenticated: true,
+			cloudIsAuthenticated: false,
 			taskHistory: [
-				{ id: "0", ts: Date.now() - 4000 },
-				{ id: "1", ts: Date.now() - 3000 },
-				{ id: "2", ts: Date.now() - 2000 },
-				{ id: "3", ts: Date.now() - 1000 },
-				{ id: "4", ts: Date.now() },
+				{ id: "1", ts: Date.now() - 2000 },
+				{ id: "2", ts: Date.now() - 1000 },
+				{ id: "3", ts: Date.now() },
 			],
 			clineMessages: [], // No active task
 		})
 
 		// Should not show DismissibleUpsell but should show RooTips
-		expect(queryByTestId("roo-tips")).toBeInTheDocument()
+		expect(queryByTestId("dismissible-upsell")).not.toBeInTheDocument()
+		expect(getByTestId("roo-tips")).toBeInTheDocument()
 	})
 })
 

+ 0 - 133
webview-ui/src/components/cloud/CloudAgents.tsx

@@ -1,133 +0,0 @@
-import React, { useEffect, useState } from "react"
-import { Cloud, Hammer, Plus, SquarePen } from "lucide-react"
-import type { CloudAgent } from "@roo-code/types"
-import { useTranslation } from "react-i18next"
-import { vscode } from "@/utils/vscode"
-import { useExtensionState } from "@/context/ExtensionStateContext"
-
-const CloudAgents: React.FC = () => {
-	const { t } = useTranslation()
-	const { cloudIsAuthenticated, cloudUserInfo, cloudApiUrl } = useExtensionState()
-	const [agents, setAgents] = useState<CloudAgent[]>([])
-	const [loading, setLoading] = useState(true)
-	const [error, setError] = useState(false)
-
-	useEffect(() => {
-		const getCloudAgents = () => {
-			// Only fetch agents if user is authenticated
-			if (!cloudIsAuthenticated) {
-				setAgents([])
-				setLoading(false)
-				setError(false)
-				return
-			}
-
-			setLoading(true)
-			setError(false)
-			vscode.postMessage({ type: "getCloudAgents" })
-		}
-
-		// Set up message listener for the response
-		const handleMessage = (event: MessageEvent) => {
-			const message = event.data
-			if (message.type === "cloudAgents") {
-				if (message.error) {
-					setError(true)
-					setAgents([])
-				} else {
-					setAgents(message.agents || [])
-				}
-
-				setLoading(false)
-			}
-		}
-
-		window.addEventListener("message", handleMessage)
-		getCloudAgents()
-
-		// Cleanup listener on unmount
-		return () => {
-			window.removeEventListener("message", handleMessage)
-		}
-	}, [cloudIsAuthenticated, cloudUserInfo?.organizationId]) // agents is excluded intentionally as it's set by the response
-
-	if (!cloudIsAuthenticated || error) {
-		return null
-	}
-
-	// Don't show loading state, just render nothing until data is ready
-	if (loading) {
-		return null
-	}
-
-	const handleAgentClick = (agentId: string) => {
-		vscode.postMessage({ type: "openExternal", url: `${cloudApiUrl}/cloud-agents/${agentId}/run` })
-	}
-
-	const handleCreateClick = () => {
-		vscode.postMessage({ type: "openExternal", url: `${cloudApiUrl}/cloud-agents/create` })
-	}
-
-	return (
-		<div className="flex flex-col gap-3 mt-6 w-full">
-			<div className="flex flex-wrap items-center justify-between mt-4 mb-1">
-				<h2 className="font-semibold text-lg shrink-0 m-0">{t("chat:cloudAgents.title")}</h2>
-				{agents.length > 0 && (
-					<button
-						onClick={handleCreateClick}
-						className="text-base flex items-center gap-1 text-vscode-descriptionForeground hover:text-vscode-textLink-foreground transition-colors cursor-pointer"
-						title={t("chat:cloudAgents.create")}>
-						<Plus className="h-4 w-4" />
-						{t("chat:cloudAgents.create")}
-					</button>
-				)}
-			</div>
-
-			{agents.length === 0 ? (
-				<div className="flex items-center gap-3 px-4 rounded-xl bg-vscode-editor-background">
-					<Cloud className="size-5 shrink-0" />
-					<p className="text-base text-vscode-descriptionForeground">
-						{t("chat:cloudAgents.description")}
-						<button
-							className="inline-flex ml-1 cursor-pointer text-vscode-textLink-foreground hover:underline"
-							onClick={handleCreateClick}>
-							{t("chat:cloudAgents.createFirst")}
-						</button>
-					</p>
-				</div>
-			) : (
-				<div className="flex flex-col gap-1">
-					{agents.map((agent) => (
-						<div
-							key={agent.id}
-							className="flex items-center relative group gap-2 px-4 py-3 rounded-xl bg-vscode-editor-background hover:bg-vscode-list-hoverBackground cursor-pointer transition-colors"
-							onClick={() => handleAgentClick(agent.id)}
-							aria-label={t("chat:cloudAgents.clickToRun", { name: agent.name })}>
-							{agent.icon ? (
-								<span
-									className="text-xl size-5 bg-foreground"
-									role="img"
-									aria-label={agent.type}
-									style={{
-										mask: `url('${agent.icon}') no-repeat center`,
-										maskSize: "contain",
-									}}></span>
-							) : (
-								<Hammer className="size-5 text-vscode-descriptionForeground shrink-0" />
-							)}
-							<div className="flex-1 min-w-0">
-								<div className="text-base font-medium text-vscode-foreground truncate">
-									{agent.name}
-								</div>
-								<div className="text-sm font-light text-vscode-descriptionForeground">{agent.type}</div>
-							</div>
-							<SquarePen className="size-4 opacity-0 group-hover:opacity-100 transition-opacity" />
-						</div>
-					))}
-				</div>
-			)}
-		</div>
-	)
-}
-
-export default CloudAgents

+ 0 - 214
webview-ui/src/components/cloud/__tests__/CloudAgents.spec.tsx

@@ -1,214 +0,0 @@
-import React from "react"
-import { render, screen, waitFor, fireEvent } from "@testing-library/react"
-import { describe, it, expect, vi, beforeEach, afterEach } from "vitest"
-import CloudAgents from "../CloudAgents"
-import type { CloudAgent } from "@roo-code/types"
-
-const MOCK_AGENTS: CloudAgent[] = [
-	{
-		id: "agent1",
-		name: "Code Assistant",
-		type: "assistant",
-		icon: "assistant",
-	},
-	{
-		id: "agent2",
-		name: "Test Agent",
-		type: "test",
-		icon: "test",
-	},
-]
-
-// Mock vscode postMessage
-const mockPostMessage = vi.fn()
-vi.mock("@/utils/vscode", () => ({
-	vscode: {
-		postMessage: (message: any) => mockPostMessage(message),
-	},
-}))
-
-// Mock useExtensionState
-const mockCloudIsAuthenticated = vi.fn()
-const mockCloudUserInfo = vi.fn()
-const mockCloudApiUrl = vi.fn()
-
-vi.mock("@/context/ExtensionStateContext", () => ({
-	useExtensionState: () => ({
-		cloudIsAuthenticated: mockCloudIsAuthenticated(),
-		cloudUserInfo: mockCloudUserInfo(),
-		cloudApiUrl: mockCloudApiUrl(),
-	}),
-}))
-
-// Helper function to simulate message from extension
-const simulateExtensionMessage = (data: any) => {
-	const event = new MessageEvent("message", { data })
-	window.dispatchEvent(event)
-}
-
-describe("CloudAgents", () => {
-	beforeEach(() => {
-		mockPostMessage.mockClear()
-		// Set default mocked values
-		mockCloudIsAuthenticated.mockReturnValue(true)
-		mockCloudUserInfo.mockReturnValue({ organizationId: "org123" })
-		mockCloudApiUrl.mockReturnValue("https://api.test.com")
-	})
-
-	afterEach(() => {
-		vi.clearAllMocks()
-	})
-
-	it("should not render when not authenticated", () => {
-		mockCloudIsAuthenticated.mockReturnValue(false)
-		const { container } = render(<CloudAgents />)
-
-		// Component should render nothing when not authenticated
-		expect(container.firstChild).toBeNull()
-		expect(mockPostMessage).not.toHaveBeenCalled()
-	})
-
-	it("should request cloud agents on mount when authenticated", async () => {
-		render(<CloudAgents />)
-
-		// Should request cloud agents from extension
-		expect(mockPostMessage).toHaveBeenCalledWith({ type: "getCloudAgents" })
-
-		// Simulate response from extension
-		simulateExtensionMessage({
-			type: "cloudAgents",
-			agents: MOCK_AGENTS,
-		})
-
-		// Wait for the component to render agents
-		await waitFor(() => {
-			expect(screen.getByText("chat:cloudAgents.title")).toBeInTheDocument()
-			expect(screen.getByText("Code Assistant")).toBeInTheDocument()
-			expect(screen.getByText("Test Agent")).toBeInTheDocument()
-		})
-	})
-
-	it("should handle agent click and open correct URL", async () => {
-		render(<CloudAgents />)
-
-		// Simulate response from extension
-		simulateExtensionMessage({
-			type: "cloudAgents",
-			agents: MOCK_AGENTS,
-		})
-
-		await waitFor(() => {
-			expect(screen.getByText("Code Assistant")).toBeInTheDocument()
-		})
-
-		const agentElement = screen.getByText("Code Assistant").closest("div.cursor-pointer")
-		fireEvent.click(agentElement!)
-
-		expect(mockPostMessage).toHaveBeenCalledWith({
-			type: "openExternal",
-			url: "https://api.test.com/cloud-agents/agent1/run",
-		})
-	})
-
-	it("should handle create button click", async () => {
-		render(<CloudAgents />)
-
-		// Simulate response from extension with agents
-		simulateExtensionMessage({
-			type: "cloudAgents",
-			agents: MOCK_AGENTS,
-		})
-
-		await waitFor(() => {
-			expect(screen.getByText("chat:cloudAgents.title")).toBeInTheDocument()
-			expect(screen.getByText("Code Assistant")).toBeInTheDocument()
-			expect(screen.getByText("Test Agent")).toBeInTheDocument()
-		})
-
-		const createButton = screen.getByTitle("chat:cloudAgents.create")
-		fireEvent.click(createButton)
-
-		expect(mockPostMessage).toHaveBeenCalledWith({
-			type: "openExternal",
-			url: "https://api.test.com/cloud-agents/create",
-		})
-	})
-
-	it("should show empty state when no agents and handle create button", async () => {
-		render(<CloudAgents />)
-
-		// Simulate response from extension with empty agents
-		simulateExtensionMessage({
-			type: "cloudAgents",
-			agents: [],
-		})
-
-		await waitFor(() => {
-			expect(screen.getByText("chat:cloudAgents.createFirst")).toBeInTheDocument()
-		})
-
-		// Find and click the "Create your first" button in the empty state
-		const createFirstButton = screen.getByText("chat:cloudAgents.createFirst")
-		fireEvent.click(createFirstButton)
-
-		expect(mockPostMessage).toHaveBeenCalledWith({
-			type: "openExternal",
-			url: "https://api.test.com/cloud-agents/create",
-		})
-	})
-
-	it("should handle error gracefully and show nothing", async () => {
-		render(<CloudAgents />)
-
-		// Simulate error response from extension
-		simulateExtensionMessage({
-			type: "cloudAgents",
-			error: "Failed to fetch agents",
-			agents: [],
-		})
-
-		// Wait for the component to process the error
-		await waitFor(() => {
-			// Component should render nothing on error
-			expect(screen.queryByText("chat:cloudAgents.title")).not.toBeInTheDocument()
-		})
-	})
-
-	it("should not render anything while loading", () => {
-		const { container } = render(<CloudAgents />)
-
-		// Before receiving the message response, component should render nothing
-		expect(container.firstChild).toBeNull()
-		expect(screen.queryByText("Cloud Agents")).not.toBeInTheDocument()
-	})
-
-	it("should re-fetch agents when organization changes", async () => {
-		const { rerender } = render(<CloudAgents />)
-
-		expect(mockPostMessage).toHaveBeenCalledTimes(1)
-		expect(mockPostMessage).toHaveBeenCalledWith({ type: "getCloudAgents" })
-
-		// Clear previous calls
-		mockPostMessage.mockClear()
-
-		// Change organization
-		mockCloudUserInfo.mockReturnValue({ organizationId: "org456" })
-		rerender(<CloudAgents />)
-
-		// Should request agents again with new org
-		expect(mockPostMessage).toHaveBeenCalledTimes(1)
-		expect(mockPostMessage).toHaveBeenCalledWith({ type: "getCloudAgents" })
-	})
-
-	it("should properly clean up message listener on unmount", () => {
-		const removeEventListenerSpy = vi.spyOn(window, "removeEventListener")
-
-		const { unmount } = render(<CloudAgents />)
-
-		unmount()
-
-		expect(removeEventListenerSpy).toHaveBeenCalledWith("message", expect.any(Function))
-
-		removeEventListenerSpy.mockRestore()
-	})
-})

+ 7 - 10
webview-ui/src/components/history/HistoryPreview.tsx

@@ -15,21 +15,18 @@ const HistoryPreview = () => {
 	}
 
 	return (
-		<div className="flex flex-col gap-1">
-			<div className="flex flex-wrap items-center justify-between mt-4 mb-2">
-				<h2 className="font-semibold text-lg grow m-0">{t("history:recentTasks")}</h2>
-				<button
-					onClick={handleViewAllHistory}
-					className="text-base text-vscode-descriptionForeground hover:text-vscode-textLink-foreground transition-colors cursor-pointer"
-					aria-label={t("history:viewAllHistory")}>
-					{t("history:viewAllHistory")}
-				</button>
-			</div>
+		<div className="flex flex-col gap-3">
 			{tasks.length !== 0 && (
 				<>
 					{tasks.slice(0, 3).map((item) => (
 						<TaskItem key={item.id} item={item} variant="compact" />
 					))}
+					<button
+						onClick={handleViewAllHistory}
+						className="text-base text-vscode-descriptionForeground hover:text-vscode-textLink-foreground transition-colors cursor-pointer text-center w-full"
+						aria-label={t("history:viewAllHistory")}>
+						{t("history:viewAllHistory")}
+					</button>
 				</>
 			)}
 		</div>

+ 2 - 2
webview-ui/src/components/history/TaskItem.tsx

@@ -47,7 +47,7 @@ const TaskItem = ({
 			key={item.id}
 			data-testid={`task-item-${item.id}`}
 			className={cn(
-				"cursor-pointer group bg-vscode-editor-background rounded-xl relative overflow-hidden border border-transparent hover:bg-vscode-editor-foreground/10 transition-colors",
+				"cursor-pointer group bg-vscode-editor-background rounded relative overflow-hidden border border-transparent hover:bg-vscode-list-hoverBackground transition-colors",
 				className,
 			)}
 			onClick={handleClick}>
@@ -70,7 +70,7 @@ const TaskItem = ({
 				<div className="flex-1 min-w-0">
 					<div
 						className={cn(
-							"overflow-hidden whitespace-pre-wrap font-light text-vscode-foreground text-ellipsis line-clamp-3",
+							"overflow-hidden whitespace-pre-wrap text-vscode-foreground text-ellipsis line-clamp-2",
 							{
 								"text-base": !isCompact,
 							},

+ 2 - 2
webview-ui/src/components/history/TaskItemFooter.tsx

@@ -16,7 +16,7 @@ export interface TaskItemFooterProps {
 const TaskItemFooter: React.FC<TaskItemFooterProps> = ({ item, variant, isSelectionMode = false, onDelete }) => {
 	return (
 		<div className="text-xs text-vscode-descriptionForeground flex justify-between items-center">
-			<div className="flex gap-1 items-center text-vscode-descriptionForeground/60">
+			<div className="flex gap-2 items-center text-vscode-descriptionForeground/60">
 				{/* Datetime with time-ago format */}
 				<StandardTooltip content={new Date(item.ts).toLocaleString()}>
 					<span className="first-letter:uppercase">{formatTimeAgo(item.ts)}</span>
@@ -32,7 +32,7 @@ const TaskItemFooter: React.FC<TaskItemFooterProps> = ({ item, variant, isSelect
 
 			{/* Action Buttons for non-compact view */}
 			{!isSelectionMode && (
-				<div className="flex flex-row gap-0 -mx-2 items-center text-vscode-descriptionForeground/60 hover:text-vscode-descriptionForeground">
+				<div className="flex flex-row gap-0 items-center text-vscode-descriptionForeground/60 hover:text-vscode-descriptionForeground">
 					<CopyButton itemTask={item.task} />
 					{variant === "full" && <ExportButton itemId={item.id} />}
 					{onDelete && <DeleteButton itemId={item.id} onDelete={onDelete} />}

+ 21 - 0
webview-ui/src/components/history/__tests__/HistoryPreview.spec.tsx

@@ -97,7 +97,10 @@ describe("HistoryPreview", () => {
 			setShowAllWorkspaces: vi.fn(),
 		})
 
+		const { container } = render(<HistoryPreview />)
+
 		// Should render the container but no task items
+		expect(container.firstChild).toHaveClass("flex", "flex-col", "gap-3")
 		expect(screen.queryByTestId(/task-item-/)).not.toBeInTheDocument()
 	})
 
@@ -207,4 +210,22 @@ describe("HistoryPreview", () => {
 			expect.anything(),
 		)
 	})
+
+	it("renders with correct container classes", () => {
+		mockUseTaskSearch.mockReturnValue({
+			tasks: mockTasks.slice(0, 1),
+			searchQuery: "",
+			setSearchQuery: vi.fn(),
+			sortOption: "newest",
+			setSortOption: vi.fn(),
+			lastNonRelevantSort: null,
+			setLastNonRelevantSort: vi.fn(),
+			showAllWorkspaces: false,
+			setShowAllWorkspaces: vi.fn(),
+		})
+
+		const { container } = render(<HistoryPreview />)
+
+		expect(container.firstChild).toHaveClass("flex", "flex-col", "gap-3")
+	})
 })

+ 15 - 0
webview-ui/src/components/history/__tests__/TaskItem.spec.tsx

@@ -94,4 +94,19 @@ describe("TaskItem", () => {
 		// Should display time ago format
 		expect(screen.getByText(/ago/)).toBeInTheDocument()
 	})
+
+	it("applies hover effect class", () => {
+		render(
+			<TaskItem
+				item={mockTask}
+				variant="full"
+				isSelected={false}
+				onToggleSelection={vi.fn()}
+				isSelectionMode={false}
+			/>,
+		)
+
+		const taskItem = screen.getByTestId("task-item-1")
+		expect(taskItem).toHaveClass("hover:bg-vscode-list-hoverBackground")
+	})
 })

+ 3 - 3
webview-ui/src/components/welcome/RooHero.tsx

@@ -7,7 +7,7 @@ const RooHero = () => {
 	})
 
 	return (
-		<div className="pb-4 forced-color-adjust-none">
+		<div className="flex flex-col items-center justify-center pb-4 forced-color-adjust-none">
 			<div
 				style={{
 					backgroundColor: "var(--vscode-foreground)",
@@ -18,8 +18,8 @@ const RooHero = () => {
 					maskRepeat: "no-repeat",
 					maskSize: "contain",
 				}}
-				className="mx-auto  hover:animate-bounce">
-				<img src={imagesBaseUri + "/roo-logo.svg"} alt="Roo logo" className="h-8 opacity-0 " />
+				className="mx-auto">
+				<img src={imagesBaseUri + "/roo-logo.svg"} alt="Roo logo" className="h-8 opacity-0" />
 			</div>
 		</div>
 	)

+ 23 - 26
webview-ui/src/components/welcome/RooTips.tsx

@@ -3,20 +3,19 @@ import { useTranslation } from "react-i18next"
 import { Trans } from "react-i18next"
 
 import { buildDocLink } from "@src/utils/docLinks"
-import { ReplaceAll, Users } from "lucide-react"
 
 const tips = [
 	{
-		icon: <Users className="size-4 shrink-0 mt-0.5" />,
+		icon: "codicon-account",
 		href: buildDocLink("basic-usage/using-modes", "tips"),
 		titleKey: "rooTips.customizableModes.title",
 		descriptionKey: "rooTips.customizableModes.description",
 	},
 	{
-		icon: <ReplaceAll className="size-4 shrink-0 mt-0.5" />,
-		href: buildDocLink("getting-started/connecting-api-provider", "tips"),
-		titleKey: "rooTips.modelAgnostic.title",
-		descriptionKey: "rooTips.modelAgnostic.description",
+		icon: "codicon-list-tree",
+		href: buildDocLink("features/boomerang-tasks", "tips"),
+		titleKey: "rooTips.boomerangTasks.title",
+		descriptionKey: "rooTips.boomerangTasks.description",
 	},
 ]
 
@@ -24,16 +23,27 @@ const RooTips = () => {
 	const { t } = useTranslation("chat")
 
 	return (
-		<div className="flex flex-col gap-2 mb-4 max-w-[450px] font-light text-vscode-descriptionForeground">
-			<p className="my-0 pr-8">
-				<Trans i18nKey="chat:about" />
+		<div>
+			<p className="text-vscode-editor-foreground leading-tight font-vscode-font-family text-center text-balance max-w-[380px] mx-auto my-0">
+				<Trans
+					i18nKey="chat:about"
+					components={{
+						DocsLink: (
+							<a href={buildDocLink("", "welcome")} target="_blank" rel="noopener noreferrer">
+								the docs
+							</a>
+						),
+					}}
+				/>
 			</p>
-			<div className="gap-4">
+			<div className="flex flex-col items-center justify-center px-5 py-2.5 gap-4">
 				{tips.map((tip) => (
-					<div key={tip.titleKey} className="flex items-start gap-2 mt-2 mr-6 leading-relaxed">
-						{tip.icon}
+					<div
+						key={tip.titleKey}
+						className="flex items-center gap-2 text-vscode-editor-foreground font-vscode max-w-[250px]">
+						<span className={`codicon ${tip.icon}`}></span>
 						<span>
-							<VSCodeLink className="text-muted-foreground underline" href={tip.href}>
+							<VSCodeLink className="forced-color-adjust-none" href={tip.href}>
 								{t(tip.titleKey)}
 							</VSCodeLink>
 							: {t(tip.descriptionKey)}
@@ -41,19 +51,6 @@ const RooTips = () => {
 					</div>
 				))}
 			</div>
-			<p className="my-0 pr-8">
-				<Trans
-					i18nKey="chat:docs"
-					components={{
-						DocsLink: (
-							<VSCodeLink
-								className="text-muted-foreground underline"
-								href={buildDocLink("", "welcome")}
-							/>
-						),
-					}}
-				/>
-			</p>
 		</div>
 	)
 }

+ 1 - 1
webview-ui/src/components/welcome/WelcomeView.tsx

@@ -62,7 +62,7 @@ const WelcomeView = () => {
 		<Tab>
 			<TabContent className="flex flex-col gap-4 p-6">
 				<RooHero />
-				<h2 className="mt-0 mb-4 text-xl">{t("welcome:greeting")}</h2>
+				<h2 className="mt-0 mb-4 text-xl text-center">{t("welcome:greeting")}</h2>
 
 				<div className="text-base text-vscode-foreground py-2 px-2 mb-4">
 					<p className="mb-3 leading-relaxed">

+ 0 - 2
webview-ui/src/context/ExtensionStateContext.tsx

@@ -41,7 +41,6 @@ export interface ExtensionStateContextType extends ExtensionState {
 	organizationSettingsVersion: number
 	cloudIsAuthenticated: boolean
 	cloudOrganizations?: CloudOrganizationMembership[]
-	cloudApiUrl: string
 	sharingEnabled: boolean
 	maxConcurrentFileReads?: number
 	mdmCompliant?: boolean
@@ -436,7 +435,6 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
 		routerModels: extensionRouterModels,
 		cloudIsAuthenticated: state.cloudIsAuthenticated ?? false,
 		cloudOrganizations: state.cloudOrganizations ?? [],
-		cloudApiUrl: state.cloudApiUrl || "https://app.roocode.com",
 		organizationSettingsVersion: state.organizationSettingsVersion ?? -1,
 		marketplaceItems,
 		marketplaceInstalledMetadata,

+ 15 - 14
webview-ui/src/i18n/locales/ca/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "Cancel·la l'operació actual"
 	},
 	"scrollToBottom": "Desplaça't al final del xat",
-	"about": "Roo Code és un equip de desenvolupament d'IA sencer al teu editor.",
-	"docs": "Consulta la nostra <DocsLink>documentació</DocsLink> per aprendre més.",
+	"about": "Genera, refactoritza i depura codi amb l'ajuda de la IA. Consulta la nostra <DocsLink>documentació</DocsLink> per obtenir més informació.",
+	"onboarding": "<strong> La vostra llista de tasques en aquest espai de treball està buida. </strong> Comença escrivint una tasca a continuació. \nNo esteu segur per on començar? \nMés informació sobre què pot fer Roo als documents.",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "Orquestració de Tasques",
+			"description": "Divideix les tasques en parts més petites i manejables."
+		},
+		"stickyModels": {
+			"title": "Modes persistents",
+			"description": "Cada mode recorda el vostre darrer model utilitzat"
+		},
+		"tools": {
+			"title": "Eines",
+			"description": "Permet que la IA resolgui problemes navegant per la web, executant ordres i molt més."
+		},
 		"customizableModes": {
 			"title": "Modes personalitzables",
-			"description": "Personatges especialitzats que es mantenen a la tasca i compleixen."
-		},
-		"modelAgnostic": {
-			"title": "Porta el teu propi model",
-			"description": "Fes servir la teva pròpia clau de proveïdor o fins i tot executa inferència local — sense sobrecost, sense bloqueig, sense restriccions"
+			"description": "Personalitats especialitzades amb comportaments propis i models assignats"
 		}
 	},
 	"selectMode": "Selecciona el mode d'interacció",
@@ -404,12 +412,5 @@
 		"problems": "Problemes",
 		"terminal": "Terminal",
 		"url": "Enganxa la URL per obtenir-ne el contingut"
-	},
-	"cloudAgents": {
-		"create": "Crear",
-		"title": "Agents al núvol",
-		"description": "Encara no has creat cap Agent al núvol.",
-		"createFirst": "Crea el teu primer",
-		"clickToRun": "Fes clic per executar {{name}}"
 	}
 }

+ 15 - 14
webview-ui/src/i18n/locales/de/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "Aktuelle Operation abbrechen"
 	},
 	"scrollToBottom": "Zum Chat-Ende scrollen",
-	"about": "Roo Code ist ein ganzes KI-Entwicklerteam in deinem Editor.",
-	"docs": "Schau in unsere <DocsLink>Dokumentation</DocsLink>, um mehr zu erfahren.",
+	"about": "Generiere, überarbeite und debugge Code mit KI-Unterstützung. Weitere Informationen findest du in unserer <DocsLink>Dokumentation</DocsLink>.",
+	"onboarding": "<strong>Deine Aufgabenliste in diesem Arbeitsbereich ist leer.</strong> Beginne mit der Eingabe einer Aufgabe unten. Du bist dir nicht sicher, wie du anfangen sollst? Lies mehr darüber, was Roo für dich tun kann, in <DocsLink>den Dokumenten</DocsLink>.",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "Aufgaben-Orchestrierung",
+			"description": "Teile Aufgaben in kleinere, überschaubare Teile auf."
+		},
+		"stickyModels": {
+			"title": "Sticky Modi",
+			"description": "Jeder Modus merkt sich dein zuletzt verwendetes Modell"
+		},
+		"tools": {
+			"title": "Tools",
+			"description": "Erlaube der KI, Probleme durch Surfen im Web, Ausführen von Befehlen und mehr zu lösen."
+		},
 		"customizableModes": {
 			"title": "Anpassbare Modi",
-			"description": "Spezialisierte Personas, die bei der Sache bleiben und Ergebnisse liefern."
-		},
-		"modelAgnostic": {
-			"title": "Bring dein eigenes Modell mit",
-			"description": "Verwende deinen eigenen Anbieter-Schlüssel oder führe sogar lokale Inferenz aus — kein Aufpreis, keine Bindung, keine Einschränkungen"
+			"description": "Spezialisierte Personas mit eigenem Verhalten und zugewiesenen Modellen"
 		}
 	},
 	"selectMode": "Interaktionsmodus auswählen",
@@ -404,12 +412,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo möchte einen Slash-Befehl ausführen",
 		"didRun": "Roo hat einen Slash-Befehl ausgeführt"
-	},
-	"cloudAgents": {
-		"create": "Erstellen",
-		"title": "Cloud-Agenten",
-		"description": "Du hast noch keine Cloud-Agenten erstellt.",
-		"createFirst": "Erstelle deinen ersten",
-		"clickToRun": "Klicke, um {{name}} auszuführen"
 	}
 }

+ 16 - 15
webview-ui/src/i18n/locales/en/chat.json

@@ -96,16 +96,24 @@
 		"placeholder": "Edit your message..."
 	},
 	"scrollToBottom": "Scroll to bottom of chat",
-	"about": "Roo Code is a whole AI dev team in your editor.",
-	"docs": "Check our <DocsLink>docs</DocsLink> to learn more.",
+	"about": "Generate, refactor, and debug code with AI assistance. Check out our <DocsLink>documentation</DocsLink> to learn more.",
+	"onboarding": "Your task list in this workspace is empty.",
 	"rooTips": {
-		"customizableModes": {
-			"title": "Customizable modes",
-			"description": "Specialized personas that stay on-task and deliver."
+		"boomerangTasks": {
+			"title": "Task Orchestration",
+			"description": "Split tasks into smaller, manageable parts"
+		},
+		"stickyModels": {
+			"title": "Sticky Models",
+			"description": "Each mode remembers your last used model"
+		},
+		"tools": {
+			"title": "Tools",
+			"description": "Allow the AI to solve problems by browsing the web, running commands, and more"
 		},
-		"modelAgnostic": {
-			"title": "Bring your own model",
-			"description": "Use your own provider key or even run local inference — no markup, lock-in, no restrictions"
+		"customizableModes": {
+			"title": "Customizable Modes",
+			"description": "Specialized personas with their own behaviors and assigned models"
 		}
 	},
 	"selectMode": "Select mode for interaction",
@@ -398,12 +406,5 @@
 		"problems": "Problems",
 		"terminal": "Terminal",
 		"url": "Paste URL to fetch contents"
-	},
-	"cloudAgents": {
-		"create": "Create",
-		"title": "Cloud Agents",
-		"description": "You haven’t created any Cloud Agents yet.",
-		"createFirst": "Create your first",
-		"clickToRun": "Click to run {{name}}"
 	}
 }

+ 1 - 1
webview-ui/src/i18n/locales/en/cloud.json

@@ -29,6 +29,6 @@
 	"upsell": {
 		"autoApprovePowerUser": "Giving Roo some independence? Control it from anywhere with Roo Code Cloud. <learnMoreLink>Learn more</learnMoreLink>.",
 		"longRunningTask": "This might take a while. Continue from anywhere with Cloud.",
-		"taskList": "Get token usage stats, continue coding from anywhere, run agents in the cloud and more: <learnMoreLink>check out Roo Code Cloud</learnMoreLink>."
+		"taskList": "Roo Code Cloud is here: follow and control your tasks from anywhere. <learnMoreLink>Learn more</learnMoreLink>."
 	}
 }

+ 1 - 1
webview-ui/src/i18n/locales/en/history.json

@@ -41,5 +41,5 @@
 		"mostTokens": "Most Tokens",
 		"mostRelevant": "Most Relevant"
 	},
-	"viewAllHistory": "View all"
+	"viewAllHistory": "View all tasks"
 }

+ 15 - 14
webview-ui/src/i18n/locales/es/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "Cancelar la operación actual"
 	},
 	"scrollToBottom": "Desplazarse al final del chat",
-	"about": "Roo Code es un equipo de desarrollo de IA completo en tu editor.",
-	"docs": "Consulta nuestros <DocsLink>documentos</DocsLink> para obtener más información.",
+	"about": "Genera, refactoriza y depura código con asistencia de IA. Consulta nuestra <DocsLink>documentación</DocsLink> para obtener más información.",
+	"onboarding": "<strong>Tu lista de tareas en este espacio de trabajo está vacía.</strong> Comienza escribiendo una tarea abajo. ¿No estás seguro cómo empezar? Lee más sobre lo que Roo puede hacer por ti en <DocsLink>la documentación</DocsLink>.",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "Orquestación de Tareas",
+			"description": "Divide las tareas en partes más pequeñas y manejables."
+		},
+		"stickyModels": {
+			"title": "Modos persistentes",
+			"description": "Cada modo recuerda tu último modelo utilizado"
+		},
+		"tools": {
+			"title": "Herramientas",
+			"description": "Permite que la IA resuelva problemas navegando por la web, ejecutando comandos y mucho más."
+		},
 		"customizableModes": {
 			"title": "Modos personalizables",
-			"description": "Personas especializadas que se mantienen en la tarea y cumplen."
-		},
-		"modelAgnostic": {
-			"title": "Trae tu propio modelo",
-			"description": "Usa tu propia clave de proveedor o incluso ejecuta inferencia local — sin sobrecostos, sin ataduras, sin restricciones"
+			"description": "Personalidades especializadas con sus propios comportamientos y modelos asignados"
 		}
 	},
 	"selectMode": "Seleccionar modo de interacción",
@@ -404,12 +412,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo quiere ejecutar un comando slash",
 		"didRun": "Roo ejecutó un comando slash"
-	},
-	"cloudAgents": {
-		"create": "Crear",
-		"title": "Agentes en la nube",
-		"description": "Aún no has creado ningún Agente en la nube.",
-		"createFirst": "Crea tu primero",
-		"clickToRun": "Haz clic para ejecutar {{name}}"
 	}
 }

+ 15 - 14
webview-ui/src/i18n/locales/fr/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "Annuler l'opération actuelle"
 	},
 	"scrollToBottom": "Défiler jusqu'au bas du chat",
-	"about": "Roo Code est une équipe de développement IA complète dans votre éditeur.",
-	"docs": "Consultez notre <DocsLink>documentation</DocsLink> pour en savoir plus.",
+	"about": "Générer, refactoriser et déboguer du code avec l'assistance de l'IA. Consultez notre <DocsLink>documentation</DocsLink> pour en savoir plus.",
+	"onboarding": "Grâce aux dernières avancées en matière de capacités de codage agent, je peux gérer des tâches complexes de développement logiciel étape par étape. Avec des outils qui me permettent de créer et d'éditer des fichiers, d'explorer des projets complexes, d'utiliser le navigateur et d'exécuter des commandes de terminal (après votre autorisation), je peux vous aider de manières qui vont au-delà de la complétion de code ou du support technique. Je peux même utiliser MCP pour créer de nouveaux outils et étendre mes propres capacités.",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "Orchestration de Tâches",
+			"description": "Divisez les tâches en parties plus petites et gérables."
+		},
+		"stickyModels": {
+			"title": "Modes persistants",
+			"description": "Chaque mode se souvient de votre dernier modèle utilisé"
+		},
+		"tools": {
+			"title": "Outils",
+			"description": "Permettez à l'IA de résoudre des problèmes en naviguant sur le Web, en exécutant des commandes, et plus encore."
+		},
 		"customizableModes": {
 			"title": "Modes personnalisables",
-			"description": "Des personas spécialisés qui restent concentrés sur la tâche et livrent des résultats."
-		},
-		"modelAgnostic": {
-			"title": "Apportez votre propre modèle",
-			"description": "Utilisez votre propre clé de fournisseur ou exécutez même une inférence locale — sans majoration, sans verrouillage, sans restrictions"
+			"description": "Des personas spécialisés avec leurs propres comportements et modèles assignés"
 		}
 	},
 	"selectMode": "Sélectionner le mode d'interaction",
@@ -404,12 +412,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo veut exécuter une commande slash",
 		"didRun": "Roo a exécuté une commande slash"
-	},
-	"cloudAgents": {
-		"create": "Créer",
-		"title": "Agents Cloud",
-		"description": "Tu n'as pas encore créé d'Agents Cloud.",
-		"createFirst": "Crée ton premier",
-		"clickToRun": "Clique pour exécuter {{name}}"
 	}
 }

+ 15 - 14
webview-ui/src/i18n/locales/hi/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "वर्तमान ऑपरेशन रद्द करें"
 	},
 	"scrollToBottom": "चैट के निचले हिस्से तक स्क्रॉल करें",
-	"about": "रू कोड आपके संपादक में एक पूरी एआई देव टीम है।",
-	"docs": "अधिक जानने के लिए हमारे <DocsLink>दस्तावेज़</DocsLink> देखें।",
+	"about": "एआई सहायता से कोड जेनरेट करें, रिफैक्टर करें और डिबग करें। अधिक जानने के लिए हमारे <DocsLink>दस्तावेज़</DocsLink> देखें।",
+	"onboarding": "एजेंटिक कोडिंग क्षमताओं में नवीनतम प्रगति के कारण, मैं जटिल सॉफ्टवेयर विकास कार्यों को चरण-दर-चरण संभाल सकता हूं। ऐसे उपकरणों के साथ जो मुझे फ़ाइलें बनाने और संपादित करने, जटिल प्रोजेक्ट का अन्वेषण करने, ब्राउज़र का उपयोग करने और टर्मिनल कमांड (आपकी अनुमति के बाद) निष्पादित करने की अनुमति देते हैं, मैं आपकी मदद कोड पूर्णता या तकनीकी समर्थन से परे तरीकों से कर सकता हूं। मैं अपनी क्षमताओं का विस्तार करने और नए उपकरण बनाने के लिए MCP का भी उपयोग कर सकता हूं।",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "कार्य संयोजन",
+			"description": "कार्यों को छोटे, प्रबंधनीय भागों में विभाजित करें।"
+		},
+		"stickyModels": {
+			"title": "स्टिकी मोड",
+			"description": "प्रत्येक मोड आपके अंतिम उपयोग किए गए मॉडल को याद रखता है"
+		},
+		"tools": {
+			"title": "उपकरण",
+			"description": "एआई को वेब ब्राउज़ करके, कमांड चलाकर और अधिक समस्याओं को हल करने की अनुमति दें।"
+		},
 		"customizableModes": {
 			"title": "अनुकूलन योग्य मोड",
-			"description": "विशेषज्ञ व्यक्ति जो कार्य पर बने रहते हैं और वितरित करते हैं।"
-		},
-		"modelAgnostic": {
-			"title": "अपना खुद का मॉडल लाओ",
-			"description": "अपने स्वयं के प्रदाता कुंजी का उपयोग करें या यहां तक ​​कि स्थानीय अनुमान चलाएं - कोई मार्कअप नहीं, कोई लॉक-इन नहीं, कोई प्रतिबंध नहीं"
+			"description": "विशिष्ट प्रोफाइल अपने व्यवहार और निर्धारित मॉडल के साथ"
 		}
 	},
 	"selectMode": "इंटरैक्शन मोड चुनें",
@@ -404,12 +412,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo एक स्लैश कमांड चलाना चाहता है",
 		"didRun": "Roo ने एक स्लैश कमांड चलाया"
-	},
-	"cloudAgents": {
-		"create": "बनाएं",
-		"title": "क्लाउड एजेंट",
-		"description": "आपने अभी तक कोई क्लाउड एजेंट नहीं बनाया है।",
-		"createFirst": "अपना पहला बनाएं",
-		"clickToRun": "{{name}} चलाने के लिए क्लिक करें"
 	}
 }

+ 16 - 15
webview-ui/src/i18n/locales/id/chat.json

@@ -99,16 +99,24 @@
 		"tooltip": "Batalkan operasi saat ini"
 	},
 	"scrollToBottom": "Gulir ke bawah chat",
-	"about": "Roo Code adalah seluruh tim pengembang AI di editor Anda.",
-	"docs": "Lihat <DocsLink>dokumentasi</DocsLink> kami untuk mempelajari lebih lanjut.",
+	"about": "Buat, refaktor, dan debug kode dengan bantuan AI.<br />Lihat <DocsLink>dokumentasi</DocsLink> kami untuk mempelajari lebih lanjut.",
+	"onboarding": "Daftar tugas di workspace ini kosong.",
 	"rooTips": {
-		"customizableModes": {
-			"title": "Mode yang dapat disesuaikan",
-			"description": "Persona khusus yang tetap fokus pada tugas dan memberikan hasil."
+		"boomerangTasks": {
+			"title": "Orkestrasi Tugas",
+			"description": "Bagi tugas menjadi bagian-bagian kecil yang dapat dikelola"
+		},
+		"stickyModels": {
+			"title": "Model Sticky",
+			"description": "Setiap mode mengingat model terakhir yang kamu gunakan"
+		},
+		"tools": {
+			"title": "Tools",
+			"description": "Izinkan AI menyelesaikan masalah dengan browsing web, menjalankan perintah, dan lainnya"
 		},
-		"modelAgnostic": {
-			"title": "Bawa model Anda sendiri",
-			"description": "Gunakan kunci penyedia Anda sendiri atau bahkan jalankan inferensi lokal — tanpa markup, tanpa kunci, tanpa batasan"
+		"customizableModes": {
+			"title": "Mode yang Dapat Disesuaikan",
+			"description": "Persona khusus dengan perilaku dan model yang ditugaskan sendiri"
 		}
 	},
 	"selectMode": "Pilih mode untuk interaksi",
@@ -410,12 +418,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo ingin menjalankan perintah slash",
 		"didRun": "Roo telah menjalankan perintah slash"
-	},
-	"cloudAgents": {
-		"create": "Buat",
-		"title": "Agen Cloud",
-		"description": "Anda belum membuat Agen Cloud apa pun.",
-		"createFirst": "Buat yang pertama",
-		"clickToRun": "Klik untuk menjalankan {{name}}"
 	}
 }

+ 15 - 14
webview-ui/src/i18n/locales/it/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "Annulla l'operazione corrente"
 	},
 	"scrollToBottom": "Scorri fino alla fine della chat",
-	"about": "Roo Code è un intero team di sviluppo AI nel tuo editor.",
-	"docs": "Consulta la nostra <DocsLink>documentazione</DocsLink> per saperne di più.",
+	"about": "Genera, refactor e debug del codice con l'assistenza dell'IA. Consulta la nostra <DocsLink>documentazione</DocsLink> per saperne di più.",
+	"onboarding": "Grazie alle più recenti innovazioni nelle capacità di codifica agentica, posso gestire complesse attività di sviluppo software passo dopo passo. Con strumenti che mi permettono di creare e modificare file, esplorare progetti complessi, utilizzare il browser ed eseguire comandi da terminale (dopo la tua autorizzazione), posso aiutarti in modi che vanno oltre il completamento del codice o il supporto tecnico. Posso persino usare MCP per creare nuovi strumenti ed estendere le mie capacità.",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "Orchestrazione di Attività",
+			"description": "Dividi le attività in parti più piccole e gestibili."
+		},
+		"stickyModels": {
+			"title": "Modalità persistenti",
+			"description": "Ogni modalità ricorda il tuo ultimo modello utilizzato"
+		},
+		"tools": {
+			"title": "Strumenti",
+			"description": "Consenti all'IA di risolvere i problemi navigando sul Web, eseguendo comandi e altro ancora."
+		},
 		"customizableModes": {
 			"title": "Modalità personalizzabili",
-			"description": "Personaggi specializzati che rimangono concentrati sull'attività e producono risultati."
-		},
-		"modelAgnostic": {
-			"title": "Porta il tuo modello",
-			"description": "Usa la tua chiave provider o esegui persino l'inferenza locale — senza markup, senza vincoli, senza restrizioni"
+			"description": "Personalità specializzate con comportamenti propri e modelli assegnati"
 		}
 	},
 	"selectMode": "Seleziona modalità di interazione",
@@ -404,12 +412,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo vuole eseguire un comando slash",
 		"didRun": "Roo ha eseguito un comando slash"
-	},
-	"cloudAgents": {
-		"create": "Crea",
-		"title": "Agenti Cloud",
-		"description": "Non hai ancora creato alcun Agente Cloud.",
-		"createFirst": "Crea il tuo primo",
-		"clickToRun": "Clicca per eseguire {{name}}"
 	}
 }

+ 15 - 14
webview-ui/src/i18n/locales/ja/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "現在の操作をキャンセル"
 	},
 	"scrollToBottom": "チャットの最下部にスクロール",
-	"about": "Roo Codeはエディターの中にいるAI開発チーム全体です。",
-	"docs": "詳細については、<DocsLink>ドキュメント</DocsLink>を確認してください。",
+	"about": "AI支援でコードを生成、リファクタリング、デバッグします。詳細については、<DocsLink>ドキュメント</DocsLink>をご覧ください。",
+	"onboarding": "最新のエージェント型コーディング能力の進歩により、複雑なソフトウェア開発タスクをステップバイステップで処理できます。ファイルの作成や編集、複雑なプロジェクトの探索、ブラウザの使用、ターミナルコマンドの実行(許可後)を可能にするツールにより、コード補完や技術サポート以上の方法であなたをサポートできます。MCPを使用して新しいツールを作成し、自分の能力を拡張することもできます。",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "タスクオーケストレーション",
+			"description": "タスクをより小さく、管理しやすい部分に分割します。"
+		},
+		"stickyModels": {
+			"title": "スティッキーモード",
+			"description": "各モードは、最後に使用したモデルを記憶しています"
+		},
+		"tools": {
+			"title": "ツール",
+			"description": "AIがWebの閲覧、コマンドの実行などによって問題を解決できるようにします。"
+		},
 		"customizableModes": {
 			"title": "カスタマイズ可能なモード",
-			"description": "タスクに集中し、成果を出す専門のペルソナ。"
-		},
-		"modelAgnostic": {
-			"title": "独自のモデルを使用",
-			"description": "独自のプロバイダーキーを使用したり、ローカル推論を実行したりできます — マークアップ、ロックイン、制限なし"
+			"description": "独自の動作と割り当てられたモデルを持つ専門的なペルソナ"
 		}
 	},
 	"selectMode": "対話モードを選択",
@@ -404,12 +412,5 @@
 	"slashCommand": {
 		"wantsToRun": "Rooはスラッシュコマンドを実行したい",
 		"didRun": "Rooはスラッシュコマンドを実行しました"
-	},
-	"cloudAgents": {
-		"create": "作成",
-		"title": "クラウドエージェント",
-		"description": "まだクラウドエージェントを作成していません。",
-		"createFirst": "最初に作成する",
-		"clickToRun": "クリックして{{name}}を実行"
 	}
 }

+ 15 - 14
webview-ui/src/i18n/locales/ko/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "현재 작업 취소"
 	},
 	"scrollToBottom": "채팅 하단으로 스크롤",
-	"about": "Roo Code는 편집기 안에 있는 전체 AI 개발팀입니다.",
-	"docs": "더 자세히 알아보려면 <DocsLink>문서</DocsLink>를 확인하세요.",
+	"about": "AI 지원으로 코드를 생성, 리팩터링 및 디버깅합니다. 자세한 내용은 <DocsLink>문서</DocsLink>를 확인하세요.",
+	"onboarding": "<strong>이 작업 공간의 작업 목록이 비어 있습니다.</strong> 아래에 작업을 입력하여 시작하세요. 어떻게 시작해야 할지 모르겠나요? Roo가 무엇을 할 수 있는지 <DocsLink>문서</DocsLink>에서 자세히 알아보세요.",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "작업 오케스트레이션",
+			"description": "작업을 더 작고 관리하기 쉬운 부분으로 나눕니다."
+		},
+		"stickyModels": {
+			"title": "스티키 모드",
+			"description": "각 모드는 마지막으로 사용한 모델을 기억합니다."
+		},
+		"tools": {
+			"title": "도구",
+			"description": "AI가 웹 탐색, 명령 실행 등으로 문제를 해결하도록 허용합니다."
+		},
 		"customizableModes": {
 			"title": "사용자 정의 모드",
-			"description": "작업에 집중하고 결과물을 전달하는 전문화된 페르소나."
-		},
-		"modelAgnostic": {
-			"title": "자신만의 모델 가져오기",
-			"description": "자신만의 공급자 키를 사용하거나 로컬 추론을 실행하세요 — 마크업, 종속, 제한 없음"
+			"description": "고유한 동작과 할당된 모델을 가진 전문 페르소나"
 		}
 	},
 	"selectMode": "상호작용 모드 선택",
@@ -404,12 +412,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo가 슬래시 명령어를 실행하려고 합니다",
 		"didRun": "Roo가 슬래시 명령어를 실행했습니다"
-	},
-	"cloudAgents": {
-		"create": "만들기",
-		"title": "클라우드 에이전트",
-		"description": "아직 클라우드 에이전트를 만들지 않았습니다.",
-		"createFirst": "첫 번째 만들기",
-		"clickToRun": "클릭하여 {{name}} 실행"
 	}
 }

+ 15 - 14
webview-ui/src/i18n/locales/nl/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "Annuleer de huidige bewerking"
 	},
 	"scrollToBottom": "Scroll naar onderaan de chat",
-	"about": "Roo Code is een heel AI-ontwikkelteam in je editor.",
-	"docs": "Bekijk onze <DocsLink>documentatie</DocsLink> voor meer informatie.",
+	"about": "Genereer, refactor en debug code met AI-assistentie. Bekijk onze <DocsLink>documentatie</DocsLink> voor meer informatie.",
+	"onboarding": "Je takenlijst in deze werkruimte is leeg.",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "Taak Orchestratie",
+			"description": "Splits taken op in kleinere, beheersbare delen"
+		},
+		"stickyModels": {
+			"title": "Vastgezette modellen",
+			"description": "Elke modus onthoudt je laatst gebruikte model"
+		},
+		"tools": {
+			"title": "Tools",
+			"description": "Laat de AI problemen oplossen door te browsen, commando's uit te voeren en meer"
+		},
 		"customizableModes": {
 			"title": "Aanpasbare modi",
-			"description": "Gespecialiseerde persona's die bij de taak blijven en leveren."
-		},
-		"modelAgnostic": {
-			"title": "Gebruik je eigen model",
-			"description": "Gebruik je eigen provider key of voer zelfs lokale inferentie uit — geen markup, geen lock-in, geen beperkingen"
+			"description": "Gespecialiseerde persona's met hun eigen gedrag en toegewezen modellen"
 		}
 	},
 	"selectMode": "Selecteer modus voor interactie",
@@ -404,12 +412,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo wil een slash commando uitvoeren",
 		"didRun": "Roo heeft een slash commando uitgevoerd"
-	},
-	"cloudAgents": {
-		"create": "Aanmaken",
-		"title": "Cloud Agents",
-		"description": "Je hebt nog geen Cloud Agents aangemaakt.",
-		"createFirst": "Maak je eerste aan",
-		"clickToRun": "Klik om {{name}} uit te voeren"
 	}
 }

+ 15 - 14
webview-ui/src/i18n/locales/pl/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "Anuluj bieżącą operację"
 	},
 	"scrollToBottom": "Przewiń do dołu czatu",
-	"about": "Roo Code to cały zespół deweloperów AI w Twoim edytorze.",
-	"docs": "Sprawdź naszą <DocsLink>dokumentację</DocsLink>, aby dowiedzieć się więcej.",
+	"about": "Generuj, refaktoryzuj i debuguj kod z pomocą sztucznej inteligencji. Sprawdź naszą <DocsLink>dokumentację</DocsLink>, aby dowiedzieć się więcej.",
+	"onboarding": "<strong>Twoja lista zadań w tym obszarze roboczym jest pusta.</strong> Zacznij od wpisania zadania poniżej. Nie wiesz, jak zacząć? Przeczytaj więcej o tym, co Roo może dla Ciebie zrobić w <DocsLink>dokumentacji</DocsLink>.",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "Orkiestracja Zadań",
+			"description": "Podziel zadania na mniejsze, łatwiejsze do zarządzania części."
+		},
+		"stickyModels": {
+			"title": "Tryby trwałe",
+			"description": "Każdy tryb zapamiętuje ostatnio używany model"
+		},
+		"tools": {
+			"title": "Narzędzia",
+			"description": "Pozwól sztucznej inteligencji rozwiązywać problemy, przeglądając sieć, uruchamiając polecenia i nie tylko."
+		},
 		"customizableModes": {
 			"title": "Konfigurowalne tryby",
-			"description": "Specjalistyczne persony, które trzymają się zadania i dostarczają wyniki."
-		},
-		"modelAgnostic": {
-			"title": "Przynieś własny model",
-			"description": "Użyj własnego klucza dostawcy lub uruchom lokalną inferencję — bez narzutów, bez blokad, bez ograniczeń"
+			"description": "Wyspecjalizowane persona z własnymi zachowaniami i przypisanymi modelami"
 		}
 	},
 	"selectMode": "Wybierz tryb interakcji",
@@ -404,12 +412,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo chce uruchomić komendę slash",
 		"didRun": "Roo uruchomił komendę slash"
-	},
-	"cloudAgents": {
-		"create": "Utwórz",
-		"title": "Agenci w chmurze",
-		"description": "Nie utworzyłeś jeszcze żadnych Agentów w chmurze.",
-		"createFirst": "Utwórz swojego pierwszego",
-		"clickToRun": "Kliknij, aby uruchomić {{name}}"
 	}
 }

+ 15 - 14
webview-ui/src/i18n/locales/pt-BR/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "Cancelar a operação atual"
 	},
 	"scrollToBottom": "Rolar para o final do chat",
-	"about": "O Roo Code é uma equipe inteira de desenvolvimento de IA em seu editor.",
-	"docs": "Confira nossa <DocsLink>documentação</DocsLink> para saber mais.",
+	"about": "Gere, refatore e depure código com assistência de IA. Confira nossa <DocsLink>documentação</DocsLink> para saber mais.",
+	"onboarding": "<strong>Sua lista de tarefas neste espaço de trabalho está vazia.</strong> Comece digitando uma tarefa abaixo. Não sabe como começar? Leia mais sobre o que o Roo pode fazer por você nos <DocsLink>documentos</DocsLink>.",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "Orquestração de Tarefas",
+			"description": "Divida as tarefas em partes menores e gerenciáveis."
+		},
+		"stickyModels": {
+			"title": "Modos Fixos",
+			"description": "Cada modo lembra o seu último modelo usado"
+		},
+		"tools": {
+			"title": "Ferramentas",
+			"description": "Permita que a IA resolva problemas navegando na web, executando comandos e muito mais."
+		},
 		"customizableModes": {
 			"title": "Modos personalizáveis",
-			"description": "Personas especializadas que se mantêm na tarefa e entregam resultados."
-		},
-		"modelAgnostic": {
-			"title": "Traga seu próprio modelo",
-			"description": "Use sua própria chave de provedor ou até mesmo execute inferência local — sem taxas extras, sem aprisionamento, sem restrições"
+			"description": "Personas especializadas com comportamentos próprios e modelos atribuídos"
 		}
 	},
 	"selectMode": "Selecionar modo de interação",
@@ -404,12 +412,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo quer executar um comando slash",
 		"didRun": "Roo executou um comando slash"
-	},
-	"cloudAgents": {
-		"create": "Criar",
-		"title": "Agentes da Nuvem",
-		"description": "Você ainda não criou nenhum Agente da Nuvem.",
-		"createFirst": "Crie o seu primeiro",
-		"clickToRun": "Clique para executar {{name}}"
 	}
 }

+ 14 - 14
webview-ui/src/i18n/locales/ru/chat.json

@@ -85,16 +85,23 @@
 		"tooltip": "Отменить текущую операцию"
 	},
 	"scrollToBottom": "Прокрутить чат вниз",
-	"about": "Roo Code — это целая команда разработчиков ИИ в вашем редакторе.",
-	"docs": "Ознакомьтесь с нашей <DocsLink>документацией</DocsLink>, чтобы узнать больше.",
+	"about": "Создавайте, рефакторите и отлаживайте код с помощью ИИ. Подробнее см. в нашей <DocsLink>документации</DocsLink>.",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "Оркестрация задач",
+			"description": "Разделяйте задачи на более мелкие, управляемые части"
+		},
+		"stickyModels": {
+			"title": "Липкие режимы",
+			"description": "Каждый режим запоминает вашу последнюю использованную модель"
+		},
+		"tools": {
+			"title": "Инструменты",
+			"description": "Разрешите ИИ решать проблемы, просматривая веб-страницы, выполняя команды и т. д."
+		},
 		"customizableModes": {
 			"title": "Настраиваемые режимы",
-			"description": "Специализированные персонажи, которые следят за выполнением задачи и добиваются результата."
-		},
-		"modelAgnostic": {
-			"title": "Используйте свою модель",
-			"description": "Используйте собственный ключ провайдера или даже запускайте локальный инференс — без наценки, без привязки, без ограничений"
+			"description": "Специализированные персонажи с собственным поведением и назначенными моделями"
 		}
 	},
 	"onboarding": "<strong>Ваш список задач в этом рабочем пространстве пуст.</strong> Начните с ввода задачи ниже. Не знаете, с чего начать? Подробнее о возможностях Roo читайте в <DocsLink>документации</DocsLink>.",
@@ -406,12 +413,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo хочет выполнить слеш-команду",
 		"didRun": "Roo выполнил слеш-команду"
-	},
-	"cloudAgents": {
-		"create": "Создать",
-		"title": "Облачные агенты",
-		"description": "Вы еще не создали ни одного облачного агента.",
-		"createFirst": "Создайте своего первого",
-		"clickToRun": "Нажмите, чтобы запустить {{name}}"
 	}
 }

+ 16 - 15
webview-ui/src/i18n/locales/tr/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "Mevcut işlemi iptal et"
 	},
 	"scrollToBottom": "Sohbetin altına kaydır",
-	"about": "Roo Code, düzenleyicinizde bütün bir AI geliştirme ekibidir.",
-	"docs": "Daha fazla bilgi edinmek için <DocsLink>belgelerimize</DocsLink> göz atın.",
+	"about": "AI yardımıyla kod oluşturun, yeniden düzenleyin ve hatalarını ayıklayın. Daha fazla bilgi edinmek için <DocsLink>belgelerimize</DocsLink> göz atın.",
+	"onboarding": "<strong>Bu çalışma alanındaki görev listeniz boş.</strong> Aşağıya bir görev yazarak başlayın. Nasıl başlayacağınızdan emin değil misiniz? Roo'nun sizin için neler yapabileceği hakkında daha fazla bilgiyi <DocsLink>belgelerde</DocsLink> okuyun.",
 	"rooTips": {
-		"customizableModes": {
-			"title": "Özelleştirilebilir modlar",
-			"description": "Göreve sadık kalan ve sonuç veren özel kişilikler."
+		"boomerangTasks": {
+			"title": "Görev Orkestrasyonu",
+			"description": "Görevleri daha küçük, yönetilebilir parçalara ayırın."
+		},
+		"stickyModels": {
+			"title": "Yapışkan Modlar",
+			"description": "Her mod, en son kullandığınız modeli hatırlar"
+		},
+		"tools": {
+			"title": "Araçlar",
+			"description": "AI'nın web'e göz atarak, komutlar çalıştırarak ve daha fazlasını yaparak sorunları çözmesine izin verin."
 		},
-		"modelAgnostic": {
-			"title": "Kendi modelini getir",
-			"description": "Kendi sağlayıcı anahtarınızı kullanın veya hatta yerel çıkarım çalıştırın — ek ücret yok, kilitlenme yok, kısıtlama yok"
+		"customizableModes": {
+			"title": "Özelleştirilebilir Modlar",
+			"description": "Kendi davranışları ve atanmış modelleri ile özelleştirilmiş kişilikler"
 		}
 	},
 	"selectMode": "Etkileşim modunu seçin",
@@ -405,12 +413,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo bir slash komutu çalıştırmak istiyor",
 		"didRun": "Roo bir slash komutu çalıştırdı"
-	},
-	"cloudAgents": {
-		"create": "Oluştur",
-		"title": "Bulut Aracıları",
-		"description": "Henüz herhangi bir Bulut Aracısı oluşturmadınız.",
-		"createFirst": "İlkini oluştur",
-		"clickToRun": "{{name}}'i çalıştırmak için tıklayın"
 	}
 }

+ 16 - 15
webview-ui/src/i18n/locales/vi/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "Hủy thao tác hiện tại"
 	},
 	"scrollToBottom": "Cuộn xuống cuối cuộc trò chuyện",
-	"about": "Roo Code là một đội ngũ phát triển AI toàn diện ngay trong trình soạn thảo của bạn.",
-	"docs": "Kiểm tra <DocsLink>tài liệu</DocsLink> của chúng tôi để tìm hiểu thêm.",
+	"about": "Tạo, tái cấu trúc và gỡ lỗi mã bằng sự hỗ trợ của AI. Kiểm tra <DocsLink>tài liệu</DocsLink> của chúng tôi để tìm hiểu thêm.",
+	"onboarding": "<strong>Danh sách nhiệm vụ của bạn trong không gian làm việc này trống.</strong> Bắt đầu bằng cách nhập nhiệm vụ bên dưới. Bạn không chắc chắn nên bắt đầu như thế nào? Đọc thêm về những gì Roo có thể làm cho bạn trong <DocsLink>tài liệu</DocsLink>.",
 	"rooTips": {
-		"customizableModes": {
-			"title": "Chế độ có thể tùy chỉnh",
-			"description": "Các nhân vật chuyên biệt luôn tập trung vào nhiệm vụ và hoàn thành công việc."
+		"boomerangTasks": {
+			"title": "Điều phối Nhiệm vụ",
+			"description": "Chia nhỏ các nhiệm vụ thành các phần nhỏ hơn, dễ quản lý hơn."
+		},
+		"stickyModels": {
+			"title": "Chế độ dính",
+			"description": "Mỗi chế độ ghi nhớ mô hình đã sử dụng cuối cùng của bạn"
+		},
+		"tools": {
+			"title": "Công cụ",
+			"description": "Cho phép AI giải quyết vấn đề bằng cách duyệt web, chạy lệnh, v.v."
 		},
-		"modelAgnostic": {
-			"title": "Mang theo mô hình của riêng bạn",
-			"description": "Sử dụng khóa nhà cung cấp của riêng bạn hoặc thậm chí chạy suy luận cục bộ — không phụ phí, không ràng buộc, không giới hạn"
+		"customizableModes": {
+			"title": "Chế độ tùy chỉnh",
+			"description": "Các nhân vật chuyên biệt với hành vi riêng và mô hình được chỉ định"
 		}
 	},
 	"selectMode": "Chọn chế độ tương tác",
@@ -405,12 +413,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo muốn chạy lệnh slash",
 		"didRun": "Roo đã chạy lệnh slash"
-	},
-	"cloudAgents": {
-		"create": "Tạo",
-		"title": "Agents trên Cloud",
-		"description": "Bạn chưa tạo Agents trên Cloud nào.",
-		"createFirst": "Tạo agent đầu tiên của bạn",
-		"clickToRun": "Nhấp để chạy {{name}}"
 	}
 }

+ 16 - 15
webview-ui/src/i18n/locales/zh-CN/chat.json

@@ -85,16 +85,24 @@
 		"tooltip": "取消当前操作"
 	},
 	"scrollToBottom": "滚动到聊天底部",
-	"about": "Roo Code 是您编辑器中的整个 AI 开发团队。",
-	"docs": "查看我们的 <DocsLink>文档</DocsLink> 了解更多信息。",
+	"about": "通过 AI 辅助生成、重构和调试代码。查看我们的 <DocsLink>文档</DocsLink> 了解更多信息。",
+	"onboarding": "<strong>此工作区中的任务列表为空。</strong> 请在下方输入任务开始。 不确定如何开始? 在 <DocsLink>文档</DocsLink> 中阅读更多关于 Roo 可以为您做什么的信息。",
 	"rooTips": {
-		"customizableModes": {
-			"title": "可自定义模式",
-			"description": "专注于任务并交付成果的专业角色。"
+		"boomerangTasks": {
+			"title": "任务编排",
+			"description": "将任务拆分为更小、更易于管理的部分。"
+		},
+		"stickyModels": {
+			"title": "粘性模式",
+			"description": "每个模式 都会记住 您上次使用的模型"
+		},
+		"tools": {
+			"title": "工具",
+			"description": "允许 AI 通过浏览网络、运行命令等方式解决问题。"
 		},
-		"modelAgnostic": {
-			"title": "自带模型",
-			"description": "使用您自己的提供商密钥,甚至可以运行本地推理——无加价、无锁定、无限制"
+		"customizableModes": {
+			"title": "自定义模式",
+			"description": "具有专属行为和指定模型的特定角色"
 		}
 	},
 	"selectMode": "选择交互模式",
@@ -405,12 +413,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo 想要运行斜杠命令",
 		"didRun": "Roo 运行了斜杠命令"
-	},
-	"cloudAgents": {
-		"create": "创建",
-		"title": "云代理",
-		"description": "您还没有创建任何云代理。",
-		"createFirst": "创建您的第一个",
-		"clickToRun": "点击运行 {{name}}"
 	}
 }

+ 15 - 14
webview-ui/src/i18n/locales/zh-TW/chat.json

@@ -96,16 +96,24 @@
 		"placeholder": "編輯您的訊息..."
 	},
 	"scrollToBottom": "捲動至聊天室底部",
-	"about": "Roo Code 是您編輯器中的整個 AI 開發團隊。",
-	"docs": "查看我們的<DocsLink>文件</DocsLink>以了解更多信息。",
+	"about": "利用 AI 輔助產生、重構和偵錯程式碼。請參閱我們的<DocsLink>說明文件</DocsLink>以瞭解更多資訊。",
+	"onboarding": "此工作區的工作清單是空的。",
 	"rooTips": {
+		"boomerangTasks": {
+			"title": "工作編排",
+			"description": "將工作拆分為更小、更易於管理的部分。"
+		},
+		"stickyModels": {
+			"title": "記憶模型",
+			"description": "每個模式都會記住您上次使用的模型"
+		},
+		"tools": {
+			"title": "工具",
+			"description": "允許 AI 透過瀏覽網路、執行命令等方式解決問題。"
+		},
 		"customizableModes": {
 			"title": "可自訂模式",
-			"description": "專注於任務並交付成果的專業角色。"
-		},
-		"modelAgnostic": {
-			"title": "自備模型",
-			"description": "使用您自己的提供商密鑰,甚至可以運行本地推理——無加價、無鎖定、無限制"
+			"description": "具有專屬行為和指定模型的特定角色"
 		}
 	},
 	"selectMode": "選擇互動模式",
@@ -405,12 +413,5 @@
 	"slashCommand": {
 		"wantsToRun": "Roo 想要執行斜線指令",
 		"didRun": "Roo 執行了斜線指令"
-	},
-	"cloudAgents": {
-		"create": "創建",
-		"title": "雲端代理",
-		"description": "您尚未建立任何雲端代理程式。",
-		"createFirst": "建立您的第一個",
-		"clickToRun": "點擊以執行 {{name}}"
 	}
 }