Преглед изворни кода

UI top down homescreen (#2951)

* isotrUpdate welcome screen UI components and fix unused variable

* Save collapsibility.

* Add persistence, locales.

* Top layout, expanded tips.

* Minimal 'tasks' language.

* Adjust announcement positioning/dimensions.

* Fix tests, defaults.

* Fix translations.

* Compromise-compromise.

* Final tweaks.

* More tweaks.

* More tweaks.

* Issues fix.

* Update translations, remove debug.

* Fix transparency issue.

---------

Co-authored-by: hannesrudolph <[email protected]>
Sacha Sayan пре 8 месеци
родитељ
комит
83133c6e6d
50 измењених фајлова са 632 додато и 301 уклоњено
  1. 1 0
      src/core/config/ContextProxy.ts
  2. 3 0
      src/core/webview/ClineProvider.ts
  3. 4 0
      src/core/webview/webviewMessageHandler.ts
  4. 1 0
      src/exports/roo-code.d.ts
  5. 1 0
      src/exports/types.ts
  6. 2 0
      src/schemas/index.ts
  7. 2 0
      src/shared/ExtensionMessage.ts
  8. 2 0
      src/shared/WebviewMessage.ts
  9. 0 1
      webview-ui/src/App.tsx
  10. 60 59
      webview-ui/src/components/chat/Announcement.tsx
  11. 80 91
      webview-ui/src/components/chat/ChatView.tsx
  12. 2 2
      webview-ui/src/components/chat/ContextMenu.tsx
  13. 0 1
      webview-ui/src/components/chat/__tests__/ChatView.auto-approve.test.tsx
  14. 0 1
      webview-ui/src/components/chat/__tests__/ChatView.test.tsx
  15. 45 96
      webview-ui/src/components/history/HistoryPreview.tsx
  16. 3 7
      webview-ui/src/components/welcome/RooHero.tsx
  17. 92 0
      webview-ui/src/components/welcome/RooTips.tsx
  18. 1 0
      webview-ui/src/components/welcome/WelcomeView.tsx
  19. 45 0
      webview-ui/src/components/welcome/__tests__/RooTips.test.tsx
  20. 5 0
      webview-ui/src/context/ExtensionStateContext.tsx
  21. 17 2
      webview-ui/src/i18n/locales/ca/chat.json
  22. 1 1
      webview-ui/src/i18n/locales/ca/history.json
  23. 17 2
      webview-ui/src/i18n/locales/de/chat.json
  24. 1 1
      webview-ui/src/i18n/locales/de/history.json
  25. 16 1
      webview-ui/src/i18n/locales/en/chat.json
  26. 1 1
      webview-ui/src/i18n/locales/en/history.json
  27. 17 2
      webview-ui/src/i18n/locales/es/chat.json
  28. 1 1
      webview-ui/src/i18n/locales/es/history.json
  29. 17 2
      webview-ui/src/i18n/locales/fr/chat.json
  30. 1 1
      webview-ui/src/i18n/locales/fr/history.json
  31. 17 2
      webview-ui/src/i18n/locales/hi/chat.json
  32. 1 1
      webview-ui/src/i18n/locales/hi/history.json
  33. 17 2
      webview-ui/src/i18n/locales/it/chat.json
  34. 1 1
      webview-ui/src/i18n/locales/it/history.json
  35. 17 2
      webview-ui/src/i18n/locales/ja/chat.json
  36. 17 2
      webview-ui/src/i18n/locales/ko/chat.json
  37. 1 1
      webview-ui/src/i18n/locales/ko/history.json
  38. 17 2
      webview-ui/src/i18n/locales/pl/chat.json
  39. 1 1
      webview-ui/src/i18n/locales/pl/history.json
  40. 17 2
      webview-ui/src/i18n/locales/pt-BR/chat.json
  41. 1 1
      webview-ui/src/i18n/locales/pt-BR/history.json
  42. 15 0
      webview-ui/src/i18n/locales/ru/chat.json
  43. 17 2
      webview-ui/src/i18n/locales/tr/chat.json
  44. 1 1
      webview-ui/src/i18n/locales/tr/history.json
  45. 17 2
      webview-ui/src/i18n/locales/vi/chat.json
  46. 1 1
      webview-ui/src/i18n/locales/vi/history.json
  47. 17 2
      webview-ui/src/i18n/locales/zh-CN/chat.json
  48. 1 1
      webview-ui/src/i18n/locales/zh-CN/history.json
  49. 17 2
      webview-ui/src/i18n/locales/zh-TW/chat.json
  50. 1 1
      webview-ui/src/i18n/locales/zh-TW/history.json

+ 1 - 0
src/core/config/ContextProxy.ts

@@ -53,6 +53,7 @@ export class ContextProxy {
 	public async initialize() {
 		for (const key of GLOBAL_STATE_KEYS) {
 			try {
+				// Revert to original assignment
 				this.stateCache[key] = this.originalContext.globalState.get(key)
 			} catch (error) {
 				logger.error(`Error loading global ${key}: ${error instanceof Error ? error.message : String(error)}`)

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

@@ -1213,6 +1213,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 			language,
 			maxReadFileLine,
 			terminalCompressProgressBar,
+			historyPreviewCollapsed,
 		} = await this.getState()
 
 		const telemetryKey = process.env.POSTHOG_API_KEY
@@ -1298,6 +1299,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 			settingsImportedAt: this.settingsImportedAt,
 			terminalCompressProgressBar: terminalCompressProgressBar ?? true,
 			hasSystemPromptOverride,
+			historyPreviewCollapsed: historyPreviewCollapsed ?? false,
 		}
 	}
 
@@ -1386,6 +1388,7 @@ export class ClineProvider extends EventEmitter<ClineProviderEvents> implements
 			telemetrySetting: stateValues.telemetrySetting || "unset",
 			showRooIgnoredFiles: stateValues.showRooIgnoredFiles ?? true,
 			maxReadFileLine: stateValues.maxReadFileLine ?? 500,
+			historyPreviewCollapsed: stateValues.historyPreviewCollapsed ?? false,
 		}
 	}
 

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

@@ -843,6 +843,10 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We
 			await updateGlobalState("maxReadFileLine", message.value)
 			await provider.postStateToWebview()
 			break
+		case "setHistoryPreviewCollapsed": // Add the new case handler
+			await updateGlobalState("historyPreviewCollapsed", message.bool ?? false)
+			// No need to call postStateToWebview here as the UI already updated optimistically
+			break
 		case "toggleApiConfigPin":
 			if (message.text) {
 				const currentPinned = getGlobalState("pinnedApiConfigs") ?? {}

+ 1 - 0
src/exports/roo-code.d.ts

@@ -287,6 +287,7 @@ type GlobalSettings = {
 		  }
 		| undefined
 	enhancementApiConfigId?: string | undefined
+	historyPreviewCollapsed?: boolean | undefined
 }
 
 type ClineMessage = {

+ 1 - 0
src/exports/types.ts

@@ -290,6 +290,7 @@ type GlobalSettings = {
 		  }
 		| undefined
 	enhancementApiConfigId?: string | undefined
+	historyPreviewCollapsed?: boolean | undefined
 }
 
 export type { GlobalSettings }

+ 2 - 0
src/schemas/index.ts

@@ -573,6 +573,7 @@ export const globalSettingsSchema = z.object({
 	customModePrompts: customModePromptsSchema.optional(),
 	customSupportPrompts: customSupportPromptsSchema.optional(),
 	enhancementApiConfigId: z.string().optional(),
+	historyPreviewCollapsed: z.boolean().optional(),
 })
 
 export type GlobalSettings = z.infer<typeof globalSettingsSchema>
@@ -650,6 +651,7 @@ const globalSettingsRecord: GlobalSettingsRecord = {
 	customSupportPrompts: undefined,
 	enhancementApiConfigId: undefined,
 	cachedChromeHostUrl: undefined,
+	historyPreviewCollapsed: undefined, 
 }
 
 export const GLOBAL_SETTINGS_KEYS = Object.keys(globalSettingsRecord) as Keys<GlobalSettings>[]

+ 2 - 0
src/shared/ExtensionMessage.ts

@@ -66,6 +66,7 @@ export interface ExtensionMessage {
 		| "fileSearchResults"
 		| "toggleApiConfigPin"
 		| "acceptInput"
+		| "setHistoryPreviewCollapsed"
 	text?: string
 	action?:
 		| "chatButtonClicked"
@@ -197,6 +198,7 @@ export type ExtensionState = Pick<
 
 	renderContext: "sidebar" | "editor"
 	settingsImportedAt?: number
+	historyPreviewCollapsed?: boolean
 }
 
 export type { ClineMessage, ClineAsk, ClineSay }

+ 2 - 0
src/shared/WebviewMessage.ts

@@ -124,6 +124,7 @@ export interface WebviewMessage {
 		| "maxReadFileLine"
 		| "searchFiles"
 		| "toggleApiConfigPin"
+		| "setHistoryPreviewCollapsed"
 	text?: string
 	disabled?: boolean
 	askResponse?: ClineAskResponse
@@ -150,6 +151,7 @@ export interface WebviewMessage {
 	requestId?: string
 	ids?: string[]
 	hasSystemPromptOverride?: boolean
+	historyPreviewCollapsed?: boolean
 }
 
 export const checkoutDiffPayloadSchema = z.object({

+ 0 - 1
webview-ui/src/App.tsx

@@ -123,7 +123,6 @@ const App = () => {
 				isHidden={tab !== "chat"}
 				showAnnouncement={showAnnouncement}
 				hideAnnouncement={() => setShowAnnouncement(false)}
-				showHistoryView={() => switchTab("history")}
 			/>
 			<HumanRelayDialog
 				isOpen={humanRelayDialogState.isOpen}

+ 60 - 59
webview-ui/src/components/chat/Announcement.tsx

@@ -4,13 +4,12 @@ import { useAppTranslation } from "@/i18n/TranslationContext"
 import { Trans } from "react-i18next"
 
 interface AnnouncementProps {
-	version: string
 	hideAnnouncement: () => void
 }
 /*
 You must update the latestAnnouncementId in ClineProvider for new announcements to show to users. This new id will be compared with whats in state for the 'last announcement shown', and if it's different then the announcement will render. As soon as an announcement is shown, the id will be updated in state. This ensures that announcements are not shown more than once, even if the user doesn't close it themselves.
 */
-const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
+const Announcement = ({ hideAnnouncement }: AnnouncementProps) => {
 	const { t } = useAppTranslation()
 
 	const discordLink = (
@@ -42,69 +41,71 @@ const Announcement = ({ version, hideAnnouncement }: AnnouncementProps) => {
 	)
 
 	return (
-		<div
-			style={{
-				backgroundColor: "var(--vscode-editor-inactiveSelectionBackground)",
-				borderRadius: "3px",
-				padding: "12px 16px",
-				margin: "5px 15px 5px 15px",
-				position: "relative",
-				flexShrink: 0,
-			}}>
-			<VSCodeButton
-				appearance="icon"
-				onClick={hideAnnouncement}
-				title={t("chat:announcement.hideButton")}
-				style={{ position: "absolute", top: "8px", right: "8px" }}>
-				<span className="codicon codicon-close"></span>
-			</VSCodeButton>
-			<h2 style={{ margin: "0 0 8px" }}>{t("chat:announcement.title")}</h2>
+		<div className="flex flex-col justify-center absolute top-0 bottom-0 left-0 right-0 z-50 p-10 bg-black/50">
+			<div
+				style={{
+					backgroundColor: "var(--vscode-editor-background)",
+					borderRadius: "3px",
+					padding: "12px 16px",
+					margin: "5px 15px 5px 15px",
+					position: "relative",
+					flexShrink: 0,
+				}}>
+				<VSCodeButton
+					appearance="icon"
+					onClick={hideAnnouncement}
+					title={t("chat:announcement.hideButton")}
+					style={{ position: "absolute", top: "8px", right: "8px" }}>
+					<span className="codicon codicon-close"></span>
+				</VSCodeButton>
+				<h2 style={{ margin: "0 0 8px" }}>{t("chat:announcement.title")}</h2>
 
-			<p style={{ margin: "5px 0px" }}>{t("chat:announcement.description")}</p>
+				<p style={{ margin: "5px 0px" }}>{t("chat:announcement.description")}</p>
 
-			<h3 style={{ margin: "12px 0 5px", fontSize: "14px" }}>{t("chat:announcement.whatsNew")}</h3>
-			<ul style={{ margin: "5px 0" }}>
-				<li>
-					•{" "}
-					<Trans
-						i18nKey="chat:announcement.feature1"
-						components={{
-							bold: <b />,
-							code: <code />,
-						}}
-					/>
-				</li>
-				<li>
-					•{" "}
-					<Trans
-						i18nKey="chat:announcement.feature2"
-						components={{
-							bold: <b />,
-							code: <code />,
-						}}
-					/>
-				</li>
-				<li>
-					•{" "}
+				<h3 style={{ margin: "12px 0 5px", fontSize: "14px" }}>{t("chat:announcement.whatsNew")}</h3>
+				<ul style={{ margin: "5px 0" }}>
+					<li>
+						•{" "}
+						<Trans
+							i18nKey="chat:announcement.feature1"
+							components={{
+								bold: <b />,
+								code: <code />,
+							}}
+						/>
+					</li>
+					<li>
+						•{" "}
+						<Trans
+							i18nKey="chat:announcement.feature2"
+							components={{
+								bold: <b />,
+								code: <code />,
+							}}
+						/>
+					</li>
+					<li>
+						•{" "}
+						<Trans
+							i18nKey="chat:announcement.feature3"
+							components={{
+								bold: <b />,
+								code: <code />,
+							}}
+						/>
+					</li>
+				</ul>
+
+				<p style={{ margin: "10px 0px 0px" }}>
 					<Trans
-						i18nKey="chat:announcement.feature3"
+						i18nKey="chat:announcement.detailsDiscussLinks"
 						components={{
-							bold: <b />,
-							code: <code />,
+							discordLink: discordLink,
+							redditLink: redditLink,
 						}}
 					/>
-				</li>
-			</ul>
-
-			<p style={{ margin: "10px 0px 0px" }}>
-				<Trans
-					i18nKey="chat:announcement.detailsDiscussLinks"
-					components={{
-						discordLink: discordLink,
-						redditLink: redditLink,
-					}}
-				/>
-			</p>
+				</p>
+			</div>
 		</div>
 	)
 }

+ 80 - 91
webview-ui/src/components/chat/ChatView.tsx

@@ -3,7 +3,6 @@ import debounce from "debounce"
 import { forwardRef, useCallback, useEffect, useImperativeHandle, useMemo, useRef, useState } from "react"
 import { useDeepCompareEffect, useEvent, useMount } from "react-use"
 import { Virtuoso, type VirtuosoHandle } from "react-virtuoso"
-import styled from "styled-components"
 import removeMd from "remove-markdown"
 import { Trans } from "react-i18next"
 
@@ -30,8 +29,8 @@ import { useAppTranslation } from "@src/i18n/TranslationContext"
 
 import TelemetryBanner from "../common/TelemetryBanner"
 import HistoryPreview from "../history/HistoryPreview"
-import RooHero from "../welcome/RooHero"
-
+import RooHero from "@src/components/welcome/RooHero"
+import RooTips from "@src/components/welcome/RooTips"
 import Announcement from "./Announcement"
 import BrowserSessionRow from "./BrowserSessionRow"
 import ChatRow from "./ChatRow"
@@ -39,12 +38,12 @@ import ChatTextArea from "./ChatTextArea"
 import TaskHeader from "./TaskHeader"
 import AutoApproveMenu from "./AutoApproveMenu"
 import SystemPromptWarning from "./SystemPromptWarning"
+import { useTaskSearch } from "../history/useTaskSearch"
 
 export interface ChatViewProps {
 	isHidden: boolean
 	showAnnouncement: boolean
 	hideAnnouncement: () => void
-	showHistoryView: () => void
 }
 
 export interface ChatViewRef {
@@ -56,13 +55,12 @@ export const MAX_IMAGES_PER_MESSAGE = 20 // Anthropic limits to 20 images
 const isMac = navigator.platform.toUpperCase().indexOf("MAC") >= 0
 
 const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewProps> = (
-	{ isHidden, showAnnouncement, hideAnnouncement, showHistoryView },
+	{ isHidden, showAnnouncement, hideAnnouncement },
 	ref,
 ) => {
 	const { t } = useAppTranslation()
 	const modeShortcutText = `${isMac ? "⌘" : "Ctrl"} + . ${t("chat:forNextMode")}`
 	const {
-		version,
 		clineMessages: messages,
 		taskHistory,
 		apiConfiguration,
@@ -84,8 +82,23 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 		customModes,
 		telemetrySetting,
 		hasSystemPromptOverride,
+		historyPreviewCollapsed, // Added historyPreviewCollapsed
 	} = useExtensionState()
 
+	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])
+
 	//const task = messages.length > 0 ? (messages[0].say === "task" ? messages[0] : undefined) : undefined) : undefined
 	const task = useMemo(() => messages.at(0), [messages]) // 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)
 	const modifiedMessages = useMemo(() => combineApiRequests(combineCommandSequences(messages.slice(1))), [messages])
@@ -1197,17 +1210,8 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 	}))
 
 	return (
-		<div
-			style={{
-				position: "fixed",
-				top: 0,
-				left: 0,
-				right: 0,
-				bottom: 0,
-				display: isHidden ? "none" : "flex",
-				flexDirection: "column",
-				overflow: "hidden",
-			}}>
+		<div className={isHidden ? "hidden" : "fixed top-0 left-0 right-0 bottom-0 flex flex-col overflow-hidden"}>
+			{showAnnouncement && <Announcement hideAnnouncement={hideAnnouncement} />}
 			{task ? (
 				<>
 					<TaskHeader
@@ -1237,20 +1241,43 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 					)}
 				</>
 			) : (
-				<div
-					style={{
-						flex: "1 1 0", // flex-grow: 1, flex-shrink: 1, flex-basis: 0
-						minHeight: 0,
-						overflowY: "auto",
-						display: "flex",
-						flexDirection: "column",
-						paddingBottom: "10px",
-					}}>
-					{telemetrySetting === "unset" && <TelemetryBanner />}
-					{showAnnouncement && <Announcement version={version} hideAnnouncement={hideAnnouncement} />}
-
-					<RooHero />
-					{taskHistory.length > 0 && <HistoryPreview showHistoryView={showHistoryView} />}
+				<div className="flex-1 min-h-0 overflow-y-auto flex flex-col gap-4">
+					{/* 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" : ""} p-10 pt-5`}>
+						<RooHero />
+						{telemetrySetting === "unset" && <TelemetryBanner />}
+						{/* Show the task history preview if expanded and tasks exist */}
+						{taskHistory.length > 0 && isExpanded && <HistoryPreview />}
+						<p className="ext-vscode-editor-foreground leading-tight font-vscode text-center">
+							<Trans
+								i18nKey="chat:about"
+								components={{
+									DocsLink: (
+										<a
+											href="https://docs.roocode.com/getting-started/your-first-task"
+											target="_blank"
+											rel="noopener noreferrer">
+											the docs
+										</a>
+									),
+								}}
+							/>
+						</p>
+						<RooTips cycle={false} />
+					</div>
 				</div>
 			)}
 
@@ -1270,28 +1297,20 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 			//    but becomes scrollable when the viewport is too small
 			*/}
 			{!task && (
-				<AutoApproveMenu
-					style={{
-						marginBottom: -2,
-						flex: "0 1 auto", // flex-grow: 0, flex-shrink: 1, flex-basis: auto
-						minHeight: 0,
-					}}
-				/>
+				<div className="mb-[-2px] flex-initial min-h-0">
+					<AutoApproveMenu />
+				</div>
 			)}
 
 			{task && (
 				<>
-					<div style={{ flexGrow: 1, display: "flex" }} ref={scrollContainerRef}>
+					<div className="grow flex" ref={scrollContainerRef}>
 						<Virtuoso
 							ref={virtuosoRef}
 							key={task.ts} // trick to make sure virtuoso re-renders when task changes, and we use initialTopMostItemIndex to start at the bottom
-							className="scrollable"
-							style={{
-								flexGrow: 1,
-								overflowY: "scroll", // always show scrollbar
-							}}
+							className="scrollable grow overflow-y-scroll"
 							components={{
-								Footer: () => <div style={{ height: 5 }} />, // Add empty padding at the bottom
+								Footer: () => <div className="h-[5px]" />, // Add empty padding at the bottom
 							}}
 							// increasing top by 3_000 to prevent jumping around when user collapses a row
 							increaseViewportBy={{ top: 3_000, bottom: Number.MAX_SAFE_INTEGER }} // hack to make sure the last message is always rendered to get truly perfect scroll to bottom animation when new messages are added (Number.MAX_SAFE_INTEGER is safe for arithmetic operations, which is all virtuoso uses this value for in src/sizeRangeSystem.ts)
@@ -1310,40 +1329,33 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 					</div>
 					<AutoApproveMenu />
 					{showScrollToBottom ? (
-						<div
-							style={{
-								display: "flex",
-								padding: "10px 15px 0px 15px",
-							}}>
-							<ScrollToBottomButton
+						<div className="flex px-[15px] pt-[10px]">
+							<div
+								className="bg-[color-mix(in_srgb,_var(--vscode-toolbar-hoverBackground)_55%,_transparent)] rounded-[3px] overflow-hidden cursor-pointer flex justify-center items-center flex-1 h-[25px] hover:bg-[color-mix(in_srgb,_var(--vscode-toolbar-hoverBackground)_90%,_transparent)] active:bg-[color-mix(in_srgb,_var(--vscode-toolbar-hoverBackground)_70%,_transparent)]"
 								onClick={() => {
 									scrollToBottomSmooth()
 									disableAutoScrollRef.current = false
 								}}
 								title={t("chat:scrollToBottom")}>
-								<span className="codicon codicon-chevron-down" style={{ fontSize: "18px" }}></span>
-							</ScrollToBottomButton>
+								<span className="codicon codicon-chevron-down text-[18px]"></span>
+							</div>
 						</div>
 					) : (
 						<div
-							style={{
-								opacity:
-									primaryButtonText || secondaryButtonText || isStreaming
-										? enableButtons || (isStreaming && !didClickCancel)
-											? 1
-											: 0.5
-										: 0,
-								display: "flex",
-								padding: `${primaryButtonText || secondaryButtonText || isStreaming ? "10" : "0"}px 15px 0px 15px`,
-							}}>
+							className={`flex ${
+								primaryButtonText || secondaryButtonText || isStreaming ? "px-[15px] pt-[10px]" : "p-0"
+							} ${
+								primaryButtonText || secondaryButtonText || isStreaming
+									? enableButtons || (isStreaming && !didClickCancel)
+										? "opacity-100"
+										: "opacity-50"
+									: "opacity-0"
+							}`}>
 							{primaryButtonText && !isStreaming && (
 								<VSCodeButton
 									appearance="primary"
 									disabled={!enableButtons}
-									style={{
-										flex: secondaryButtonText ? 1 : 2,
-										marginRight: secondaryButtonText ? "6px" : "0",
-									}}
+									className={secondaryButtonText ? "flex-1 mr-[6px]" : "flex-[2] mr-0"}
 									title={
 										primaryButtonText === t("chat:retry.title")
 											? t("chat:retry.tooltip")
@@ -1372,10 +1384,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 								<VSCodeButton
 									appearance="secondary"
 									disabled={!enableButtons && !(isStreaming && !didClickCancel)}
-									style={{
-										flex: isStreaming ? 2 : 1,
-										marginLeft: isStreaming ? 0 : "6px",
-									}}
+									className={isStreaming ? "flex-[2] ml-0" : "flex-1 ml-[6px]"}
 									title={
 										isStreaming
 											? t("chat:cancel.tooltip")
@@ -1425,24 +1434,4 @@ const ChatViewComponent: React.ForwardRefRenderFunction<ChatViewRef, ChatViewPro
 
 const ChatView = forwardRef(ChatViewComponent)
 
-const ScrollToBottomButton = styled.div`
-	background-color: color-mix(in srgb, var(--vscode-toolbar-hoverBackground) 55%, transparent);
-	border-radius: 3px;
-	overflow: hidden;
-	cursor: pointer;
-	display: flex;
-	justify-content: center;
-	align-items: center;
-	flex: 1;
-	height: 25px;
-
-	&:hover {
-		background-color: color-mix(in srgb, var(--vscode-toolbar-hoverBackground) 90%, transparent);
-	}
-
-	&:active {
-		background-color: color-mix(in srgb, var(--vscode-toolbar-hoverBackground) 70%, transparent);
-	}
-`
-
 export default ChatView

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

@@ -19,8 +19,8 @@ interface ContextMenuProps {
 	selectedType: ContextMenuOptionType | null
 	queryItems: ContextMenuQueryItem[]
 	modes?: ModeConfig[]
-	loading?: boolean // New loading prop
-	dynamicSearchResults?: SearchResult[] // New dynamic search results prop
+	loading?: boolean
+	dynamicSearchResults?: SearchResult[]
 }
 
 const ContextMenu: React.FC<ContextMenuProps> = ({

+ 0 - 1
webview-ui/src/components/chat/__tests__/ChatView.auto-approve.test.tsx

@@ -95,7 +95,6 @@ const defaultProps: ChatViewProps = {
 	isHidden: false,
 	showAnnouncement: false,
 	hideAnnouncement: () => {},
-	showHistoryView: () => {},
 }
 
 const renderChatView = (props: Partial<ChatViewProps> = {}) => {

+ 0 - 1
webview-ui/src/components/chat/__tests__/ChatView.test.tsx

@@ -153,7 +153,6 @@ const defaultProps: ChatViewProps = {
 	isHidden: false,
 	showAnnouncement: false,
 	hideAnnouncement: () => {},
-	showHistoryView: () => {},
 }
 
 const queryClient = new QueryClient()

+ 45 - 96
webview-ui/src/components/history/HistoryPreview.tsx

@@ -2,115 +2,64 @@ import { memo } from "react"
 
 import { vscode } from "@/utils/vscode"
 import { formatLargeNumber, formatDate } from "@/utils/format"
-import { Button } from "@/components/ui"
 
-import { useAppTranslation } from "@src/i18n/TranslationContext"
 import { CopyButton } from "./CopyButton"
 import { useTaskSearch } from "./useTaskSearch"
 
-import { Trans } from "react-i18next"
+import { Coins } from "lucide-react"
 
-type HistoryPreviewProps = {
-	showHistoryView: () => void
-}
-const HistoryPreview = ({ showHistoryView }: HistoryPreviewProps) => {
+const HistoryPreview = () => {
 	const { tasks, showAllWorkspaces } = useTaskSearch()
-	const { t } = useAppTranslation()
 
 	return (
 		<>
-			<div className="flex flex-col gap-3 shrink-0 mx-5">
-				{!!tasks.length && (
-					<div className="flex items-center justify-between text-vscode-descriptionForeground">
-						<div className="flex items-center gap-1">
-							<span className="codicon codicon-comment-discussion scale-90 mr-1" />
-							<span className="font-medium text-xs uppercase">{t("history:recentTasks")}</span>
-						</div>
-						<Button variant="ghost" size="sm" onClick={() => showHistoryView()} className="uppercase">
-							{t("history:viewAll")}
-						</Button>
-					</div>
-				)}
-				{tasks.length === 0 && (
+			<div className="flex flex-col gap-3">
+				{tasks.length !== 0 && (
 					<>
-						<p className="outline rounded p-4">
-							<Trans
-								i18nKey="chat:onboarding"
-								components={{
-									DocsLink: (
-										<a
-											href="https://docs.roocode.com/getting-started/your-first-task"
-											target="_blank"
-											rel="noopener noreferrer">
-											the docs
-										</a>
-									),
-								}}
-							/>
-						</p>
-
-						<Button size="sm" onClick={() => showHistoryView()} className="mx-auto">
-							{t("history:viewAll")}
-						</Button>
-					</>
-				)}
-				{tasks.slice(0, 3).map((item) => (
-					<div
-						key={item.id}
-						className="bg-vscode-toolbar-hoverBackground/50 hover:bg-vscode-toolbar-hoverBackground/75 rounded-xs relative overflow-hidden opacity-90 hover:opacity-100 cursor-pointer"
-						onClick={() => vscode.postMessage({ type: "showTaskWithId", text: item.id })}>
-						<div className="flex flex-col gap-2 p-3 pt-1">
-							<div className="flex justify-between items-center">
-								<span className="text-xs font-medium text-vscode-descriptionForeground uppercase">
-									{formatDate(item.ts)}
-								</span>
-								<CopyButton itemTask={item.task} />
-							</div>
+						{tasks.slice(0, 3).map((item) => (
 							<div
-								className="text-vscode-descriptionForeground overflow-hidden whitespace-pre-wrap"
-								style={{
-									display: "-webkit-box",
-									WebkitLineClamp: 3,
-									WebkitBoxOrient: "vertical",
-									wordBreak: "break-word",
-									overflowWrap: "anywhere",
-								}}>
-								{item.task}
-							</div>
-							<div className="text-xs text-vscode-descriptionForeground">
-								<span>
-									{t("history:tokens", {
-										in: formatLargeNumber(item.tokensIn || 0),
-										out: formatLargeNumber(item.tokensOut || 0),
-									})}
-								</span>
-								{!!item.cacheWrites && (
-									<>
-										{" • "}
-										<span>
-											{t("history:cache", {
-												writes: formatLargeNumber(item.cacheWrites || 0),
-												reads: formatLargeNumber(item.cacheReads || 0),
-											})}
+								key={item.id}
+								className="bg-vscode-editor-background rounded relative overflow-hidden cursor-pointer border border-vscode-toolbar-hoverBackground/30 hover:border-vscode-toolbar-hoverBackground/60"
+								onClick={() => vscode.postMessage({ type: "showTaskWithId", text: item.id })}>
+								<div className="flex flex-col gap-2 p-3 pt-1">
+									<div className="flex justify-between items-center">
+										<span className="text-xs font-medium text-vscode-descriptionForeground uppercase">
+											{formatDate(item.ts)}
 										</span>
-									</>
-								)}
-								{!!item.totalCost && (
-									<>
-										{" • "}
-										<span>{t("history:apiCost", { cost: item.totalCost?.toFixed(4) })}</span>
-									</>
-								)}
-							</div>
-							{showAllWorkspaces && item.workspace && (
-								<div className="flex flex-row gap-1 text-vscode-descriptionForeground text-xs mt-1">
-									<span className="codicon codicon-folder scale-80" />
-									<span>{item.workspace}</span>
+										<CopyButton itemTask={item.task} />
+									</div>
+									<div
+										className="text-vscode-foreground overflow-hidden whitespace-pre-wrap"
+										style={{
+											display: "-webkit-box",
+											WebkitLineClamp: 2,
+											WebkitBoxOrient: "vertical",
+											wordBreak: "break-word",
+											overflowWrap: "anywhere",
+										}}>
+										{item.task}
+									</div>
+									<div className="flex flex-row gap-2 text-xs text-vscode-descriptionForeground">
+										<span>↑ {formatLargeNumber(item.tokensIn || 0)}</span>
+										<span>↓ {formatLargeNumber(item.tokensOut || 0)}</span>
+										{!!item.totalCost && (
+											<span>
+												<Coins className="inline-block size-[1em]" />{" "}
+												{"$" + item.totalCost?.toFixed(2)}
+											</span>
+										)}
+									</div>
+									{showAllWorkspaces && item.workspace && (
+										<div className="flex flex-row gap-1 text-vscode-descriptionForeground text-xs mt-1">
+											<span className="codicon codicon-folder scale-80" />
+											<span>{item.workspace}</span>
+										</div>
+									)}
 								</div>
-							)}
-						</div>
-					</div>
-				))}
+							</div>
+						))}
+					</>
+				)}
 			</div>
 		</>
 	)

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

@@ -1,16 +1,13 @@
 import { useState } from "react"
-import { useAppTranslation } from "@src/i18n/TranslationContext"
-
-const WelcomeView = () => {
-	const { t } = useAppTranslation()
 
+const RooHero = () => {
 	const [imagesBaseUri] = useState(() => {
 		const w = window as any
 		return w.IMAGES_BASE_URI || ""
 	})
 
 	return (
-		<div style={{ padding: "10px 20px", flexShrink: 0 }} className="flex flex-col items-center mt-8 gap-2">
+		<div className="flex flex-col items-center justify-center pb-4">
 			<div
 				style={{
 					backgroundColor: "var(--vscode-foreground)",
@@ -24,9 +21,8 @@ const WelcomeView = () => {
 				className="mx-auto">
 				<img src={imagesBaseUri + "/roo-logo.svg"} alt="Roo logo" className="h-8 opacity-0" />
 			</div>
-			<h2 className="">{t("chat:greeting")}</h2>
 		</div>
 	)
 }
 
-export default WelcomeView
+export default RooHero

+ 92 - 0
webview-ui/src/components/welcome/RooTips.tsx

@@ -0,0 +1,92 @@
+import { VSCodeLink } from "@vscode/webview-ui-toolkit/react"
+import { useTranslation } from "react-i18next"
+import { useState, useEffect } from "react"
+import clsx from "clsx"
+
+const tips = [
+	{
+		icon: "codicon-list-tree",
+		href: "https://docs.roocode.com/features/boomerang-tasks",
+		titleKey: "rooTips.boomerangTasks.title",
+		descriptionKey: "rooTips.boomerangTasks.description",
+	},
+	{
+		icon: "codicon-pinned",
+		href: "https://docs.roocode.com/basic-usage/using-modes",
+		titleKey: "rooTips.stickyModels.title",
+		descriptionKey: "rooTips.stickyModels.description",
+	},
+	{
+		icon: "codicon-tools",
+		href: "https://docs.roocode.com/basic-usage/how-tools-work",
+		titleKey: "rooTips.tools.title",
+		descriptionKey: "rooTips.tools.description",
+	},
+]
+
+interface RooTipsProps {
+	cycle?: boolean
+}
+
+const RooTips = ({ cycle = false }: RooTipsProps) => {
+	const { t } = useTranslation("chat")
+	const [currentTipIndex, setCurrentTipIndex] = useState(Math.floor(Math.random() * tips.length))
+	const [isFading, setIsFading] = useState(false)
+
+	useEffect(() => {
+		if (!cycle) return
+
+		const intervalId = setInterval(() => {
+			setIsFading(true) // Start fade out
+			setTimeout(() => {
+				setCurrentTipIndex((prevIndex) => (prevIndex + 1) % tips.length)
+				setIsFading(false) // Start fade in
+			}, 1000) // Fade duration
+		}, 11000) // 10s display + 1s fade
+
+		return () => clearInterval(intervalId) // Cleanup on unmount
+	}, [cycle])
+
+	const currentTip = tips[currentTipIndex]
+	const topTwoTips = tips.slice(0, 2)
+
+	return (
+		<div
+			className={clsx(
+				"flex flex-col items-center justify-center px-5 py-2.5 gap-4",
+				cycle && "h-[5em] overflow-visible m-5",
+			)}>
+			{/* If we need real estate, we show a compressed version of the tips. Otherwise, we expand it. */}
+			{cycle ? (
+				<>
+					<div className="opacity-70 pb-1"> Did you know about...</div>
+					<div
+						className={clsx(
+							"flex items-center gap-2 text-vscode-editor-foreground font-vscode max-w-[250px] transition-opacity duration-1000 ease-in-out",
+							isFading ? "opacity-0" : "opacity-70",
+						)}>
+						{" "}
+						<span className={`codicon ${currentTip.icon}`}></span>
+						<span>
+							<VSCodeLink href={currentTip.href}>{t(currentTip.titleKey)}</VSCodeLink>:{" "}
+							{t(currentTip.descriptionKey)}
+						</span>
+					</div>
+				</>
+			) : (
+				topTwoTips.map((tip) => (
+					<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 href={tip.href}>{t(tip.titleKey)}</VSCodeLink>: {t(tip.descriptionKey)}
+						</span>
+					</div>
+				))
+			)}
+		</div>
+	)
+}
+
+export default RooTips

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

@@ -38,6 +38,7 @@ const WelcomeView = () => {
 		<Tab>
 			<TabContent className="flex flex-col gap-5">
 				<RooHero />
+				<h2 className="mx-auto">{t("chat:greeting")}</h2>
 
 				<div className="outline rounded p-4">
 					<Trans i18nKey="welcome:introduction" />

+ 45 - 0
webview-ui/src/components/welcome/__tests__/RooTips.test.tsx

@@ -0,0 +1,45 @@
+import React from "react"
+import { render, screen } from "@testing-library/react"
+import RooTips from "../RooTips"
+
+// Mock the translation hook
+jest.mock("react-i18next", () => ({
+	useTranslation: () => ({
+		t: (key: string) => key, // Simple mock that returns the key
+	}),
+	// Mock Trans component if it were used directly, but it's not here
+}))
+
+// Mock VSCodeLink
+jest.mock("@vscode/webview-ui-toolkit/react", () => ({
+	VSCodeLink: ({ href, children }: { href: string; children: React.ReactNode }) => <a href={href}>{children}</a>,
+}))
+
+// Mock clsx if complex class logic needs specific testing (optional)
+// jest.mock('clsx');
+
+describe("RooTips Component", () => {
+	beforeEach(() => {
+		jest.useFakeTimers()
+		// Reset Math.random mock for consistent starting points if needed
+		// jest.spyOn(global.Math, 'random').mockReturnValue(0); // Example: always start with the first tip
+	})
+
+	afterEach(() => {
+		jest.runOnlyPendingTimers()
+		jest.useRealTimers()
+		// Restore Math.random if mocked
+		// jest.spyOn(global.Math, 'random').mockRestore();
+	})
+
+	describe("when cycle is false (default)", () => {
+		beforeEach(() => {
+			render(<RooTips cycle={false} />)
+		})
+
+		test("renders only the top two tips", () => {
+			// Ensure only two tips are present (check by link role)
+			expect(screen.getAllByRole("link")).toHaveLength(2)
+		})
+	})
+})

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

@@ -13,6 +13,7 @@ import { experimentDefault, ExperimentId } from "@roo/shared/experiments"
 import { TelemetrySetting } from "@roo/shared/TelemetrySetting"
 
 export interface ExtensionStateContextType extends ExtensionState {
+	historyPreviewCollapsed?: boolean // Add the new state property
 	didHydrateState: boolean
 	showWelcome: boolean
 	theme: any
@@ -89,6 +90,7 @@ export interface ExtensionStateContextType extends ExtensionState {
 	togglePinnedApiConfig: (configName: string) => void
 	terminalCompressProgressBar?: boolean
 	setTerminalCompressProgressBar: (value: boolean) => void
+	setHistoryPreviewCollapsed: (value: boolean) => void
 }
 
 export const ExtensionStateContext = createContext<ExtensionStateContextType | undefined>(undefined)
@@ -166,6 +168,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
 		terminalZshP10k: false, // Default Powerlevel10k integration setting
 		terminalZdotdir: false, // Default ZDOTDIR handling setting
 		terminalCompressProgressBar: true, // Default to compress progress bar output
+		historyPreviewCollapsed: false, // Initialize the new state (default to expanded)
 	})
 
 	const [didHydrateState, setDidHydrateState] = useState(false)
@@ -336,6 +339,8 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode
 
 				return { ...prevState, pinnedApiConfigs: newPinned }
 			}),
+		setHistoryPreviewCollapsed: (value) =>
+			setState((prevState) => ({ ...prevState, historyPreviewCollapsed: value })), // Implement the setter
 	}
 
 	return <ExtensionStateContext.Provider value={contextValue}>{children}</ExtensionStateContext.Provider>

+ 17 - 2
webview-ui/src/i18n/locales/ca/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "Cancel·la l'operació actual"
 	},
 	"scrollToBottom": "Desplaça't al final del xat",
+	"about": "Genera, refactoritza i depura codi amb l'ajuda de la IA.<br />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": "Tasques Boomerang",
+			"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."
+		}
+	},
 	"selectMode": "Selecciona el mode d'interacció",
-	"selectApiConfig": "Selecciona la configuració de l'API",
 	"enhancePrompt": "Millora la sol·licitud amb context addicional",
 	"addImages": "Afegeix imatges al missatge",
 	"sendMessage": "Envia el missatge",
@@ -217,5 +231,6 @@
 			"close": "Tancar navegador"
 		}
 	},
-	"systemPromptWarning": "ADVERTÈNCIA: S'ha activat una substitució personalitzada d'instruccions del sistema. Això pot trencar greument la funcionalitat i causar un comportament impredictible."
+	"systemPromptWarning": "ADVERTÈNCIA: S'ha activat una substitució personalitzada d'instruccions del sistema. Això pot trencar greument la funcionalitat i causar un comportament impredictible.",
+	"selectApiConfig": "Seleccioneu la configuració de l'API"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "Tasques recents",
+	"recentTasks": "Tasques",
 	"viewAll": "Veure tot",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "Cau: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/de/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "Aktuelle Operation abbrechen"
 	},
 	"scrollToBottom": "Zum Chat-Ende scrollen",
+	"about": "Generiere, überarbeite und debugge Code mit KI-Unterstützung.<br />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": "Bumerang-Aufgaben",
+			"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."
+		}
+	},
 	"selectMode": "Interaktionsmodus auswählen",
-	"selectApiConfig": "API-Konfiguration auswählen",
 	"enhancePrompt": "Prompt mit zusätzlichem Kontext verbessern",
 	"addImages": "Bilder zur Nachricht hinzufügen",
 	"sendMessage": "Nachricht senden",
@@ -217,5 +231,6 @@
 			"close": "Browser schließen"
 		}
 	},
-	"systemPromptWarning": "WARNUNG: Benutzerdefinierte Systemaufforderung aktiv. Dies kann die Funktionalität erheblich beeinträchtigen und zu unvorhersehbarem Verhalten führen."
+	"systemPromptWarning": "WARNUNG: Benutzerdefinierte Systemaufforderung aktiv. Dies kann die Funktionalität erheblich beeinträchtigen und zu unvorhersehbarem Verhalten führen.",
+	"selectApiConfig": "API-Konfiguration auswählen"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "Jüngste Aufgaben",
+	"recentTasks": "Aufgaben",
 	"viewAll": "Alle anzeigen",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "Cache: +{{writes}} → {{reads}}",

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

@@ -65,7 +65,22 @@
 		"tooltip": "Cancel the current operation"
 	},
 	"scrollToBottom": "Scroll to bottom of chat",
-	"onboarding": "<strong>Your task list in this workspace is empty.</strong> Start by typing in a task below. Not sure how to begin? Read more about what Roo can do for you in <DocsLink>the docs</DocsLink>.",
+	"about": "Generate, refactor, and debug code with AI assistance.<br />Check out our <DocsLink>documentation</DocsLink> to learn more.",
+	"onboarding": "Your task list in this workspace is empty.",
+	"rooTips": {
+		"boomerangTasks": {
+			"title": "Boomerang Tasks",
+			"description": "Split tasks into smaller, manageable parts."
+		},
+		"stickyModels": {
+			"title": "Sticky Modes",
+			"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."
+		}
+	},
 	"selectMode": "Select mode for interaction",
 	"selectApiConfig": "Select API configuration",
 	"enhancePrompt": "Enhance prompt with additional context",

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "Recent Tasks",
+	"recentTasks": "Tasks",
 	"viewAll": "View All Tasks",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "Cache: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/es/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "Cancelar la operación actual"
 	},
 	"scrollToBottom": "Desplazarse al final del chat",
+	"about": "Genera, refactoriza y depura código con asistencia de IA.<br />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": "Tareas Boomerang",
+			"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."
+		}
+	},
 	"selectMode": "Seleccionar modo de interacción",
-	"selectApiConfig": "Seleccionar configuración de API",
 	"enhancePrompt": "Mejorar el mensaje con contexto adicional",
 	"addImages": "Agregar imágenes al mensaje",
 	"sendMessage": "Enviar mensaje",
@@ -217,5 +231,6 @@
 			"close": "Cerrar navegador"
 		}
 	},
-	"systemPromptWarning": "ADVERTENCIA: Anulación de instrucciones del sistema personalizada activa. Esto puede romper gravemente la funcionalidad y causar un comportamiento impredecible."
+	"systemPromptWarning": "ADVERTENCIA: Anulación de instrucciones del sistema personalizada activa. Esto puede romper gravemente la funcionalidad y causar un comportamiento impredecible.",
+	"selectApiConfig": "Seleccionar configuración de API"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "Tareas recientes",
+	"recentTasks": "Tareas",
 	"viewAll": "Ver todas",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "Caché: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/fr/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "Annuler l'opération actuelle"
 	},
 	"scrollToBottom": "Défiler jusqu'au bas du chat",
+	"about": "Générer, refactoriser et déboguer du code avec l'assistance de l'IA.<br />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": "Tâches Boomerang",
+			"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."
+		}
+	},
 	"selectMode": "Sélectionner le mode d'interaction",
-	"selectApiConfig": "Sélectionner la configuration API",
 	"enhancePrompt": "Améliorer la requête avec un contexte supplémentaire",
 	"addImages": "Ajouter des images au message",
 	"sendMessage": "Envoyer le message",
@@ -217,5 +231,6 @@
 			"close": "Fermer le navigateur"
 		}
 	},
-	"systemPromptWarning": "AVERTISSEMENT : Remplacement d'instructions système personnalisées actif. Cela peut gravement perturber la fonctionnalité et provoquer un comportement imprévisible."
+	"systemPromptWarning": "AVERTISSEMENT : Remplacement d'instructions système personnalisées actif. Cela peut gravement perturber la fonctionnalité et provoquer un comportement imprévisible.",
+	"selectApiConfig": "Sélectionner la configuration de l’API"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "Tâches récentes",
+	"recentTasks": "Tâches",
 	"viewAll": "Voir tout",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "Cache: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/hi/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "वर्तमान ऑपरेशन रद्द करें"
 	},
 	"scrollToBottom": "चैट के निचले हिस्से तक स्क्रॉल करें",
+	"about": "एआई सहायता से कोड जेनरेट करें, रिफैक्टर करें और डिबग करें। अधिक जानने के लिए हमारे <DocsLink>दस्तावेज़</DocsLink> देखें।",
 	"onboarding": "एजेंटिक कोडिंग क्षमताओं में नवीनतम प्रगति के कारण, मैं जटिल सॉफ्टवेयर विकास कार्यों को चरण-दर-चरण संभाल सकता हूं। ऐसे उपकरणों के साथ जो मुझे फ़ाइलें बनाने और संपादित करने, जटिल प्रोजेक्ट का अन्वेषण करने, ब्राउज़र का उपयोग करने और टर्मिनल कमांड (आपकी अनुमति के बाद) निष्पादित करने की अनुमति देते हैं, मैं आपकी मदद कोड पूर्णता या तकनीकी समर्थन से परे तरीकों से कर सकता हूं। मैं अपनी क्षमताओं का विस्तार करने और नए उपकरण बनाने के लिए MCP का भी उपयोग कर सकता हूं।",
+	"rooTips": {
+		"boomerangTasks": {
+			"title": "बूमरैंग कार्य",
+			"description": "कार्यों को छोटे, प्रबंधनीय भागों में विभाजित करें।"
+		},
+		"stickyModels": {
+			"title": "स्टिकी मोड",
+			"description": "प्रत्येक मोड आपके अंतिम उपयोग किए गए मॉडल को याद रखता है"
+		},
+		"tools": {
+			"title": "उपकरण",
+			"description": "एआई को वेब ब्राउज़ करके, कमांड चलाकर और अधिक समस्याओं को हल करने की अनुमति दें।"
+		}
+	},
 	"selectMode": "इंटरैक्शन मोड चुनें",
-	"selectApiConfig": "API कॉन्फ़िगरेशन चुनें",
 	"enhancePrompt": "अतिरिक्त संदर्भ के साथ प्रॉम्प्ट बढ़ाएँ",
 	"addImages": "संदेश में चित्र जोड़ें",
 	"sendMessage": "संदेश भेजें",
@@ -217,5 +231,6 @@
 			"close": "ब्राउज़र बंद करें"
 		}
 	},
-	"systemPromptWarning": "चेतावनी: कस्टम सिस्टम प्रॉम्प्ट ओवरराइड सक्रिय है। यह कार्यक्षमता को गंभीर रूप से बाधित कर सकता है और अनियमित व्यवहार का कारण बन सकता है।"
+	"systemPromptWarning": "चेतावनी: कस्टम सिस्टम प्रॉम्प्ट ओवरराइड सक्रिय है। यह कार्यक्षमता को गंभीर रूप से बाधित कर सकता है और अनियमित व्यवहार का कारण बन सकता है.",
+	"selectApiConfig": "एपीआई कॉन्फ़िगरेशन का चयन करें"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "हाल के कार्य",
+	"recentTasks": "कार्य",
 	"viewAll": "सभी देखें",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "कैश: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/it/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "Annulla l'operazione corrente"
 	},
 	"scrollToBottom": "Scorri fino alla fine della chat",
+	"about": "Genera, refactor e debug del codice con l'assistenza dell'IA.<br />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": "Attività Boomerang",
+			"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."
+		}
+	},
 	"selectMode": "Seleziona modalità di interazione",
-	"selectApiConfig": "Seleziona configurazione API",
 	"enhancePrompt": "Migliora prompt con contesto aggiuntivo",
 	"addImages": "Aggiungi immagini al messaggio",
 	"sendMessage": "Invia messaggio",
@@ -217,5 +231,6 @@
 			"close": "Chiudi browser"
 		}
 	},
-	"systemPromptWarning": "ATTENZIONE: Sovrascrittura personalizzata delle istruzioni di sistema attiva. Questo può compromettere gravemente le funzionalità e causare comportamenti imprevedibili."
+	"systemPromptWarning": "ATTENZIONE: Sovrascrittura personalizzata delle istruzioni di sistema attiva. Questo può compromettere gravemente le funzionalità e causare comportamenti imprevedibili.",
+	"selectApiConfig": "Seleziona la configurazione API"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "Compiti recenti",
+	"recentTasks": "Compiti",
 	"viewAll": "Vedi tutto",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "Cache: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/ja/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "現在の操作をキャンセル"
 	},
 	"scrollToBottom": "チャットの最下部にスクロール",
+	"about": "AI支援でコードを生成、リファクタリング、デバッグします。詳細については、<DocsLink>ドキュメント</DocsLink>をご覧ください。",
 	"onboarding": "最新のエージェント型コーディング能力の進歩により、複雑なソフトウェア開発タスクをステップバイステップで処理できます。ファイルの作成や編集、複雑なプロジェクトの探索、ブラウザの使用、ターミナルコマンドの実行(許可後)を可能にするツールにより、コード補完や技術サポート以上の方法であなたをサポートできます。MCPを使用して新しいツールを作成し、自分の能力を拡張することもできます。",
+	"rooTips": {
+		"boomerangTasks": {
+			"title": "ブーメランタスク",
+			"description": "タスクをより小さく、管理しやすい部分に分割します。"
+		},
+		"stickyModels": {
+			"title": "スティッキーモード",
+			"description": "各モードは、最後に使用したモデルを記憶しています"
+		},
+		"tools": {
+			"title": "ツール",
+			"description": "AIがWebの閲覧、コマンドの実行などによって問題を解決できるようにします。"
+		}
+	},
 	"selectMode": "対話モードを選択",
-	"selectApiConfig": "API設定を選択",
 	"enhancePrompt": "追加コンテキストでプロンプトを強化",
 	"addImages": "メッセージに画像を追加",
 	"sendMessage": "メッセージを送信",
@@ -217,5 +231,6 @@
 			"close": "ブラウザを閉じる"
 		}
 	},
-	"systemPromptWarning": "警告:カスタムシステムプロンプトの上書きが有効です。これにより機能が深刻に損なわれ、予測不可能な動作が発生する可能性があります。"
+	"systemPromptWarning": "警告:カスタムシステムプロンプトの上書きが有効です。これにより機能が深刻に損なわれ、予測不可能な動作が発生する可能性があります。",
+	"selectApiConfig": "API構成を選択"
 }

+ 17 - 2
webview-ui/src/i18n/locales/ko/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "현재 작업 취소"
 	},
 	"scrollToBottom": "채팅 하단으로 스크롤",
+	"about": "AI 지원으로 코드를 생성, 리팩터링 및 디버깅합니다. 자세한 내용은 <DocsLink>문서</DocsLink>를 확인하세요.",
 	"onboarding": "<strong>이 작업 공간의 작업 목록이 비어 있습니다.</strong> 아래에 작업을 입력하여 시작하세요. 어떻게 시작해야 할지 모르겠나요? Roo가 무엇을 할 수 있는지 <DocsLink>문서</DocsLink>에서 자세히 알아보세요.",
+	"rooTips": {
+		"boomerangTasks": {
+			"title": "부메랑 작업",
+			"description": "작업을 더 작고 관리하기 쉬운 부분으로 나눕니다."
+		},
+		"stickyModels": {
+			"title": "스티키 모드",
+			"description": "각 모드는 마지막으로 사용한 모델을 기억합니다."
+		},
+		"tools": {
+			"title": "도구",
+			"description": "AI가 웹 탐색, 명령 실행 등으로 문제를 해결하도록 허용합니다."
+		}
+	},
 	"selectMode": "상호작용 모드 선택",
-	"selectApiConfig": "API 구성 선택",
 	"enhancePrompt": "추가 컨텍스트로 프롬프트 향상",
 	"addImages": "메시지에 이미지 추가",
 	"sendMessage": "메시지 보내기",
@@ -217,5 +231,6 @@
 			"close": "브라우저 닫기"
 		}
 	},
-	"systemPromptWarning": "경고: 사용자 정의 시스템 프롬프트 재정의가 활성화되었습니다. 이로 인해 기능이 심각하게 손상되고 예측할 수 없는 동작이 발생할 수 있습니다."
+	"systemPromptWarning": "경고: 사용자 정의 시스템 프롬프트 재정의가 활성화되었습니다. 이로 인해 기능이 심각하게 손상되고 예측할 수 없는 동작이 발생할 수 있습니다.",
+	"selectApiConfig": "API 구성 선택"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "최근 작업",
+	"recentTasks": "작업",
 	"viewAll": "모두 보기",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "캐시: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/pl/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "Anuluj bieżącą operację"
 	},
 	"scrollToBottom": "Przewiń do dołu czatu",
+	"about": "Generuj, refaktoryzuj i debuguj kod z pomocą sztucznej inteligencji.<br />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": "Zadania bumerangowe",
+			"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."
+		}
+	},
 	"selectMode": "Wybierz tryb interakcji",
-	"selectApiConfig": "Wybierz konfigurację API",
 	"enhancePrompt": "Ulepsz podpowiedź dodatkowym kontekstem",
 	"addImages": "Dodaj obrazy do wiadomości",
 	"sendMessage": "Wyślij wiadomość",
@@ -217,5 +231,6 @@
 			"close": "Zamknij przeglądarkę"
 		}
 	},
-	"systemPromptWarning": "OSTRZEŻENIE: Aktywne niestandardowe zastąpienie instrukcji systemowych. Może to poważnie zakłócić funkcjonalność i powodować nieprzewidywalne zachowanie."
+	"systemPromptWarning": "OSTRZEŻENIE: Aktywne niestandardowe zastąpienie instrukcji systemowych. Może to poważnie zakłócić funkcjonalność i powodować nieprzewidywalne zachowanie.",
+	"selectApiConfig": "Wybierz konfigurację API"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "Ostatnie zadania",
+	"recentTasks": "Zadania",
 	"viewAll": "Zobacz wszystkie",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "Pamięć podręczna: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/pt-BR/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "Cancelar a operação atual"
 	},
 	"scrollToBottom": "Rolar para o final do chat",
+	"about": "Gere, refatore e depure código com assistência de IA.<br />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": "Tarefas Bumerangue",
+			"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."
+		}
+	},
 	"selectMode": "Selecionar modo de interação",
-	"selectApiConfig": "Selecionar configuração de API",
 	"enhancePrompt": "Aprimorar prompt com contexto adicional",
 	"addImages": "Adicionar imagens à mensagem",
 	"sendMessage": "Enviar mensagem",
@@ -217,5 +231,6 @@
 			"close": "Fechar navegador"
 		}
 	},
-	"systemPromptWarning": "AVISO: Substituição personalizada de instrução do sistema ativa. Isso pode comprometer gravemente a funcionalidade e causar comportamento imprevisível."
+	"systemPromptWarning": "AVISO: Substituição personalizada de instrução do sistema ativa. Isso pode comprometer gravemente a funcionalidade e causar comportamento imprevisível.",
+	"selectApiConfig": "Selecionar configuração da API"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "Tarefas recentes",
+	"recentTasks": "Tarefas",
 	"viewAll": "Ver todas",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "Cache: +{{writes}} → {{reads}}",

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

@@ -65,6 +65,21 @@
 		"tooltip": "Отменить текущую операцию"
 	},
 	"scrollToBottom": "Прокрутить чат вниз",
+	"about": "Создавайте, рефакторите и отлаживайте код с помощью ИИ.<br />Подробнее см. в нашей <DocsLink>документации</DocsLink>.",
+	"rooTips": {
+		"boomerangTasks": {
+			"title": "Boomerang Tasks",
+			"description": "Orchestrate complex workflows with subtasks"
+		},
+		"stickyModels": {
+			"title": "Липкие режимы",
+			"description": "Каждый режим запоминает вашу последнюю использованную модель"
+		},
+		"tools": {
+			"title": "Инструменты",
+			"description": "Разрешите ИИ решать проблемы, просматривая веб-страницы, выполняя команды и т. д."
+		}
+	},
 	"onboarding": "<strong>Ваш список задач в этом рабочем пространстве пуст.</strong> Начните с ввода задачи ниже. Не знаете, с чего начать? Подробнее о возможностях Roo читайте в <DocsLink>документации</DocsLink>.",
 	"selectMode": "Выберите режим взаимодействия",
 	"selectApiConfig": "Выберите конфигурацию API",

+ 17 - 2
webview-ui/src/i18n/locales/tr/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "Mevcut işlemi iptal et"
 	},
 	"scrollToBottom": "Sohbetin altına kaydır",
+	"about": "AI yardımıyla kod oluşturun, yeniden düzenleyin ve hatalarını ayıklayın.<br />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": {
+		"boomerangTasks": {
+			"title": "Bumerang Görevleri",
+			"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."
+		}
+	},
 	"selectMode": "Etkileşim modunu seçin",
-	"selectApiConfig": "API yapılandırmasını seçin",
 	"enhancePrompt": "Ek bağlamla istemi geliştir",
 	"addImages": "Mesaja resim ekle",
 	"sendMessage": "Mesaj gönder",
@@ -217,5 +231,6 @@
 			"close": "Tarayıcıyı kapat"
 		}
 	},
-	"systemPromptWarning": "UYARI: Özel sistem komut geçersiz kılma aktif. Bu işlevselliği ciddi şekilde bozabilir ve öngörülemeyen davranışlara neden olabilir."
+	"systemPromptWarning": "UYARI: Özel sistem komut geçersiz kılma aktif. Bu işlevselliği ciddi şekilde bozabilir ve öngörülemeyen davranışlara neden olabilir.",
+	"selectApiConfig": "API yapılandırmasını seçin"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "Son Görevler",
+	"recentTasks": "Görevler",
 	"viewAll": "Tümünü Gör",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "Önbellek: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/vi/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "Hủy thao tác hiện tại"
 	},
 	"scrollToBottom": "Cuộn xuống cuối cuộc trò chuyện",
+	"about": "Tạo, tái cấu trúc và gỡ lỗi mã bằng sự hỗ trợ của AI.<br />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": {
+		"boomerangTasks": {
+			"title": "Nhiệm vụ Boomerang",
+			"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."
+		}
+	},
 	"selectMode": "Chọn chế độ tương tác",
-	"selectApiConfig": "Chọn cấu hình API",
 	"enhancePrompt": "Nâng cao yêu cầu với ngữ cảnh bổ sung",
 	"addImages": "Thêm hình ảnh vào tin nhắn",
 	"sendMessage": "Gửi tin nhắn",
@@ -217,5 +231,6 @@
 			"close": "Đóng trình duyệt"
 		}
 	},
-	"systemPromptWarning": "CẢNH BÁO: Đã kích hoạt ghi đè lệnh nhắc hệ thống tùy chỉnh. Điều này có thể phá vỡ nghiêm trọng chức năng và gây ra hành vi không thể dự đoán."
+	"systemPromptWarning": "CẢNH BÁO: Đã kích hoạt ghi đè lệnh nhắc hệ thống tùy chỉnh. Điều này có thể phá vỡ nghiêm trọng chức năng và gây ra hành vi không thể dự đoán.",
+	"selectApiConfig": "Chọn cấu hình API"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "Nhiệm vụ gần đây",
+	"recentTasks": "Nhiệm vụ",
 	"viewAll": "Xem tất cả",
 	"tokens": "Token: ↑{{in}} ↓{{out}}",
 	"cache": "Bộ nhớ đệm: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/zh-CN/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "取消当前操作"
 	},
 	"scrollToBottom": "滚动到聊天底部",
+	"about": "通过 AI 辅助生成、重构和调试代码。<br />查看我们的 <DocsLink>文档</DocsLink> 了解更多信息。",
 	"onboarding": "<strong>此工作区中的任务列表为空。</strong> 请在下方输入任务开始。 不确定如何开始? 在 <DocsLink>文档</DocsLink> 中阅读更多关于 Roo 可以为您做什么的信息。",
+	"rooTips": {
+		"boomerangTasks": {
+			"title": "任务拆分",
+			"description": "将任务拆分为更小、更易于管理的部分。"
+		},
+		"stickyModels": {
+			"title": "粘性模式",
+			"description": "每个模式 都会记住 您上次使用的模型"
+		},
+		"tools": {
+			"title": "工具",
+			"description": "允许 AI 通过浏览网络、运行命令等方式解决问题。"
+		}
+	},
 	"selectMode": "选择交互模式",
-	"selectApiConfig": "选择API配置",
 	"enhancePrompt": "增强提示词",
 	"addImages": "添加图片到消息",
 	"sendMessage": "发送消息",
@@ -217,5 +231,6 @@
 			"close": "关闭浏览器"
 		}
 	},
-	"systemPromptWarning": "警告:自定义系统提示词覆盖已激活。这可能严重破坏功能并导致不可预测的行为。"
+	"systemPromptWarning": "警告:自定义系统提示词覆盖已激活。这可能严重破坏功能并导致不可预测的行为。",
+	"selectApiConfig": "选择 API 配置"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "最近任务",
+	"recentTasks": "任务",
 	"viewAll": "查看全部",
 	"tokens": "Token用量: ↑{{in}} ↓{{out}}",
 	"cache": "缓存操作: +{{writes}} → {{reads}}",

+ 17 - 2
webview-ui/src/i18n/locales/zh-TW/chat.json

@@ -65,9 +65,23 @@
 		"tooltip": "取消目前操作"
 	},
 	"scrollToBottom": "捲動至對話框底部",
+	"about": "透過 AI 輔助產生、重構和偵錯程式碼。<br />查看我們的 <DocsLink>說明文件</DocsLink> 以瞭解更多資訊。",
 	"onboarding": "<strong>您在此工作區中的工作清單是空的。</strong> 請在下方輸入工作以開始。 不確定如何開始? 在 <DocsLink>說明文件</DocsLink> 中閱讀更多關於 Roo 能為您做什麼的資訊。",
+	"rooTips": {
+		"boomerangTasks": {
+			"title": "任務拆分",
+			"description": "將任務拆分為更小、更易於管理的部分。"
+		},
+		"stickyModels": {
+			"title": "黏性模式",
+			"description": "每個模式都會記住您上次使用的模型"
+		},
+		"tools": {
+			"title": "工具",
+			"description": "允許 AI 透過瀏覽網路、執行命令等方式解決問題。"
+		}
+	},
 	"selectMode": "選擇互動模式",
-	"selectApiConfig": "選擇 API 設定",
 	"enhancePrompt": "使用額外內容增強提示",
 	"addImages": "新增圖片到訊息中",
 	"sendMessage": "傳送訊息",
@@ -217,5 +231,6 @@
 			"close": "關閉瀏覽器"
 		}
 	},
-	"systemPromptWarning": "警告:自訂系統提示詞覆蓋已啟用。這可能嚴重破壞功能並導致不可預測的行為。"
+	"systemPromptWarning": "警告:自訂系統提示詞覆蓋已啟用。這可能嚴重破壞功能並導致不可預測的行為。",
+	"selectApiConfig": "選取 API 設定"
 }

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

@@ -1,5 +1,5 @@
 {
-	"recentTasks": "最近的工作",
+	"recentTasks": "工作",
 	"viewAll": "檢視全部",
 	"tokens": "Tokens: ↑{{in}} ↓{{out}}",
 	"cache": "快取:+{{writes}} → {{reads}}",