diff --git a/.changeset/polite-games-arrive.md b/.changeset/polite-games-arrive.md new file mode 100644 index 00000000000..03c192fc55a --- /dev/null +++ b/.changeset/polite-games-arrive.md @@ -0,0 +1,59 @@ +--- +"kilo-code": patch +--- + +Include changes from Roo Code v3.36.6 + +- Add tool alias support for model-specific tool customization, allowing users to configure how tools are presented to different AI models (PR #9989 by @daniel-lxs) +- Sanitize MCP server and tool names for API compatibility, ensuring special characters don't cause issues with API calls (PR #10054 by @daniel-lxs) +- Improve auto-approve timer visibility in follow-up suggestions for better user awareness of pending actions (PR #10048 by @brunobergher) +- Fix: Cancel auto-approval timeout when user starts typing, preventing accidental auto-approvals during user interaction (PR #9937 by @roomote) +- Add WorkspaceTaskVisibility type for organization cloud settings to support team visibility controls (PR #10020 by @roomote) +- Fix: Extract raw error message from OpenRouter metadata for clearer error reporting (PR #10039 by @daniel-lxs) +- Fix: Show tool protocol dropdown for LiteLLM provider, restoring missing configuration option (PR #10053 by @daniel-lxs) +- Add: GPT-5.2 model to openai-native provider (PR #10024 by @hannesrudolph) +- Fix: Handle empty Gemini responses and reasoning loops to prevent infinite retries (PR #10007 by @hannesrudolph) +- Fix: Add missing tool_result blocks to prevent API errors when tool results are expected (PR #10015 by @daniel-lxs) +- Fix: Filter orphaned tool_results when more results than tool_uses to prevent message validation errors (PR #10027 by @daniel-lxs) +- Fix: Add general API endpoints for Z.ai provider (#9879 by @richtong, PR #9894 by @roomote) +- Remove: Deprecated list_code_definition_names tool (PR #10005 by @hannesrudolph) +- Add error details modal with on-demand display for improved error visibility when debugging issues (PR #9985 by @roomote) +- Fix: Prevent premature rawChunkTracker clearing for MCP tools, improving reliability of MCP tool streaming (PR #9993 by @daniel-lxs) +- Fix: Filter out 429 rate limit errors from API error telemetry for cleaner metrics (PR #9987 by @daniel-lxs) +- Fix: Correct TODO list display order in chat view to show items in proper sequence (PR #9991 by @roomote) +- Refactor: Unified context-management architecture with improved UX for better context control (PR #9795 by @hannesrudolph) +- Add new `search_replace` native tool for single-replacement operations with improved editing precision (PR #9918 by @hannesrudolph) +- Streaming tool stats and token usage throttling for better real-time feedback during generation (PR #9926 by @hannesrudolph) +- Add versioned settings support with minPluginVersion gating for Roo provider (PR #9934 by @hannesrudolph) +- Make Architect mode save plans to `/plans` directory and gitignore it (PR #9944 by @brunobergher) +- Add ability to save screenshots from the browser tool (PR #9963 by @mrubens) +- Refactor: Decouple tools from system prompt for cleaner architecture (PR #9784 by @daniel-lxs) +- Update DeepSeek models to V3.2 with new pricing (PR #9962 by @hannesrudolph) +- Add minimal and medium reasoning effort levels for Gemini models (PR #9973 by @hannesrudolph) +- Update xAI models catalog with latest model options (PR #9872 by @hannesrudolph) +- Add DeepSeek V3-2 support for Baseten provider (PR #9861 by @AlexKer) +- Tweaks to Baseten model definitions for better defaults (PR #9866 by @mrubens) +- Fix: Add xhigh reasoning effort support for gpt-5.1-codex-max (#9891 by @andrewginns, PR #9900 by @andrewginns) +- Fix: Add Kimi, MiniMax, and Qwen model configurations for Bedrock (#9902 by @jbearak, PR #9905 by @app/roomote) +- Configure tool preferences for xAI models (PR #9923 by @hannesrudolph) +- Default to using native tools when supported on OpenRouter (PR #9878 by @mrubens) +- Fix: Exclude apply_diff from native tools when diffEnabled is false (#9919 by @denis-kudelin, PR #9920 by @app/roomote) +- Fix: Always show tool protocol selector for openai-compatible provider (#9965 by @bozoweed, PR #9966 by @hannesrudolph) +- Fix: Respect explicit supportsReasoningEffort array values for proper model configuration (PR #9970 by @hannesrudolph) +- Add timeout configuration to OpenAI Compatible Provider Client (PR #9898 by @dcbartlett) +- Revert default tool protocol change from xml to native for stability (PR #9956 by @mrubens) +- Improve OpenAI error messages to be more useful for debugging (PR #9639 by @mrubens) +- Better error logs for parseToolCall exceptions (PR #9857 by @cte) +- Improve cloud job error logging for RCC provider errors (PR #9924 by @cte) +- Fix: Display actual API error message instead of generic text on retry (PR #9954 by @hannesrudolph) +- Add API error telemetry to OpenRouter provider for better diagnostics (PR #9953 by @daniel-lxs) +- Fix: Sanitize removed/invalid API providers to prevent infinite loop (PR #9869 by @hannesrudolph) +- Fix: Use foreground color for context-management icons (PR #9912 by @hannesrudolph) +- Fix: Suppress 'ask promise was ignored' error in handleError (PR #9914 by @daniel-lxs) +- Fix: Process finish_reason to emit tool_call_end events properly (PR #9927 by @daniel-lxs) +- Fix: Add finish_reason processing to xai.ts provider (PR #9929 by @daniel-lxs) +- Fix: Validate and fix tool_result IDs before API requests (PR #9952 by @daniel-lxs) +- Fix: Return undefined instead of 0 for disabled API timeout (PR #9960 by @hannesrudolph) +- Stop making unnecessary count_tokens requests for better performance (PR #9884 by @mrubens) +- Refactor: Consolidate ThinkingBudget components and fix disable handling (PR #9930 by @hannesrudolph) +- Forbid time estimates in architect mode for more focused planning (PR #9931 by @app/roomote diff --git a/.gitignore b/.gitignore index 0832924917f..b5ff9bb4d01 100644 --- a/.gitignore +++ b/.gitignore @@ -68,4 +68,6 @@ qdrant_storage/ *.code-workspace # Act Secret Files -.secrets \ No newline at end of file +.secrets +# Architect plans +plans/ diff --git a/.roo/rules-translate/AGENTS.md b/.roo/rules-translate/AGENTS.md index add4a837b8d..0ef1f2cf80e 100644 --- a/.roo/rules-translate/AGENTS.md +++ b/.roo/rules-translate/AGENTS.md @@ -316,31 +316,36 @@ For each language that is missing translations: "dragFiles": "按住shift拖动文件" ======= "dragFiles": "Shift+拖拽文件" ->>>>>>> AFTER + +> > > > > > > AFTER <<<<<<< BEFORE "description": "启用后,Kilo Code 将能够与 MCP 服务器交互以获取高级功能。" ======= "description": "启用后 Kilo Code 可与 MCP 服务交互获取高级功能。" ->>>>>>> AFTER + +> > > > > > > AFTER <<<<<<< BEFORE "cannotUndo": "此操作无法撤消。" ======= "cannotUndo": "此操作不可逆。" ->>>>>>> AFTER + +> > > > > > > AFTER <<<<<<< BEFORE "hold shift to drag in files" → "按住shift拖动文件" ======= "hold shift to drag in files" → "Shift+拖拽文件" ->>>>>>> AFTER + +> > > > > > > AFTER <<<<<<< BEFORE "Double click to edit" → "双击进行编辑" ======= "Double click to edit" → "双击编辑" ->>>>>>> AFTER + +> > > > > > > AFTER ``` ### Common Pitfalls diff --git a/apps/kilocode-docs/docs/advanced-usage/appbuilder.md b/apps/kilocode-docs/docs/advanced-usage/appbuilder.md index 6a27123644e..51c4e50daaf 100644 --- a/apps/kilocode-docs/docs/advanced-usage/appbuilder.md +++ b/apps/kilocode-docs/docs/advanced-usage/appbuilder.md @@ -39,14 +39,14 @@ Before using App Builder: 1. Navigate to **[App Builder](https://app.kilo.ai/app-builder)** from your Kilo dashboard. 2. Choose an **AI Model** for development (e.g., Grok Code Fast 1, Claude Sonnet 4.5, GPT-5.2). 3. Describe your application in plain language: - - What it should do - - Key features and functionality - - Design preferences or constraints + - What it should do + - Key features and functionality + - Design preferences or constraints 4. Watch the **live preview** update as the AI generates your app. 5. Provide feedback to refine: - - "Make the header sticky" - - "Add a dark mode toggle" - - "Connect this form to a database" + - "Make the header sticky" + - "Add a dark mode toggle" + - "Connect this form to a database" 6. When satisfied, click **Deploy** to push your app live. --- @@ -54,11 +54,12 @@ Before using App Builder: ## How App Builder Works - When you describe your application: - 1. The AI model interprets your requirements and generates an initial implementation. - 2. Code is rendered in real-time in the live preview panel. - 3. You can interact with the preview as if it were the deployed app. - 4. Each refinement request triggers targeted updates to the codebase. - 5. The AI maintains context across your entire conversation for coherent iteration. + + 1. The AI model interprets your requirements and generates an initial implementation. + 2. Code is rendered in real-time in the live preview panel. + 3. You can interact with the preview as if it were the deployed app. + 4. Each refinement request triggers targeted updates to the codebase. + 5. The AI maintains context across your entire conversation for coherent iteration. - Deployment packages your application and provisions hosting automatically. diff --git a/apps/web-evals/src/app/runs/[id]/run.tsx b/apps/web-evals/src/app/runs/[id]/run.tsx index a4b39100245..41581a21c41 100644 --- a/apps/web-evals/src/app/runs/[id]/run.tsx +++ b/apps/web-evals/src/app/runs/[id]/run.tsx @@ -242,7 +242,7 @@ function formatLogContent(log: string): React.ReactNode[] { export function Run({ run }: { run: Run }) { const runStatus = useRunStatus(run) - const { tasks, tokenUsage, usageUpdatedAt, heartbeat, runners } = runStatus + const { tasks, tokenUsage, toolUsage, usageUpdatedAt, heartbeat, runners } = runStatus const [selectedTask, setSelectedTask] = useState(null) const [taskLog, setTaskLog] = useState(null) @@ -336,37 +336,70 @@ export function Run({ run }: { run: Run }) { ) const taskMetrics: Record = useMemo(() => { + // Reference usageUpdatedAt to trigger recomputation when Map contents change + void usageUpdatedAt const metrics: Record = {} tasks?.forEach((task) => { - const usage = tokenUsage.get(task.id) - - if (task.finishedAt && task.taskMetrics) { - metrics[task.id] = task.taskMetrics - } else if (usage) { + const streamingUsage = tokenUsage.get(task.id) + const dbMetrics = task.taskMetrics + + // For finished tasks, prefer DB values but fall back to streaming values + // This handles race conditions during timeout where DB might not have latest data + if (task.finishedAt) { + // Check if DB metrics have meaningful values (not just default/empty) + const dbHasData = dbMetrics && (dbMetrics.tokensIn > 0 || dbMetrics.tokensOut > 0 || dbMetrics.cost > 0) + if (dbHasData) { + metrics[task.id] = dbMetrics + } else if (streamingUsage) { + // Fall back to streaming values if DB is empty/stale + metrics[task.id] = { + tokensIn: streamingUsage.totalTokensIn, + tokensOut: streamingUsage.totalTokensOut, + tokensContext: streamingUsage.contextTokens, + duration: streamingUsage.duration ?? 0, + cost: streamingUsage.totalCost, + } + } + } else if (streamingUsage) { + // For running tasks, use streaming values metrics[task.id] = { - tokensIn: usage.totalTokensIn, - tokensOut: usage.totalTokensOut, - tokensContext: usage.contextTokens, - duration: usage.duration ?? 0, - cost: usage.totalCost, + tokensIn: streamingUsage.totalTokensIn, + tokensOut: streamingUsage.totalTokensOut, + tokensContext: streamingUsage.contextTokens, + duration: streamingUsage.duration ?? 0, + cost: streamingUsage.totalCost, } } }) return metrics - // eslint-disable-next-line react-hooks/exhaustive-deps }, [tasks, tokenUsage, usageUpdatedAt]) // Collect all unique tool names from all tasks and sort by total attempts const toolColumns = useMemo(() => { + // Reference usageUpdatedAt to trigger recomputation when Map contents change + void usageUpdatedAt if (!tasks) return [] const toolTotals = new Map() for (const task of tasks) { - if (task.taskMetrics?.toolUsage) { - for (const [toolName, usage] of Object.entries(task.taskMetrics.toolUsage)) { + // Get both DB and streaming values + const dbToolUsage = task.taskMetrics?.toolUsage + const streamingToolUsage = toolUsage.get(task.id) + + // For finished tasks, prefer DB values but fall back to streaming values + // For running tasks, use streaming values + // This handles race conditions during timeout where DB might not have latest data + const taskToolUsage = task.finishedAt + ? dbToolUsage && Object.keys(dbToolUsage).length > 0 + ? dbToolUsage + : streamingToolUsage + : streamingToolUsage + + if (taskToolUsage) { + for (const [toolName, usage] of Object.entries(taskToolUsage)) { const tool = toolName as ToolName const current = toolTotals.get(tool) ?? 0 toolTotals.set(tool, current + usage.attempts) @@ -378,10 +411,13 @@ export function Run({ run }: { run: Run }) { return Array.from(toolTotals.entries()) .sort((a, b) => b[1] - a[1]) .map(([name]): ToolName => name) - }, [tasks]) + // toolUsage ref is stable; usageUpdatedAt triggers recomputation when Map contents change + }, [tasks, toolUsage, usageUpdatedAt]) // Compute aggregate stats const stats = useMemo(() => { + // Reference usageUpdatedAt to trigger recomputation when Map contents change + void usageUpdatedAt if (!tasks) return null const passed = tasks.filter((t) => t.passed === true).length @@ -393,8 +429,8 @@ export function Run({ run }: { run: Run }) { let totalCost = 0 let totalDuration = 0 - // Aggregate tool usage from completed tasks - const toolUsage: ToolUsage = {} + // Aggregate tool usage from all tasks (both finished and running) + const toolUsageAggregate: ToolUsage = {} for (const task of tasks) { const metrics = taskMetrics[task.id] @@ -405,15 +441,24 @@ export function Run({ run }: { run: Run }) { totalDuration += metrics.duration } - // Aggregate tool usage from finished tasks with taskMetrics - if (task.finishedAt && task.taskMetrics?.toolUsage) { - for (const [key, usage] of Object.entries(task.taskMetrics.toolUsage)) { + // Aggregate tool usage: prefer DB values for finished tasks, fall back to streaming values + // This handles race conditions during timeout where DB might not have latest data + const dbToolUsage = task.taskMetrics?.toolUsage + const streamingToolUsage = toolUsage.get(task.id) + const taskToolUsage = task.finishedAt + ? dbToolUsage && Object.keys(dbToolUsage).length > 0 + ? dbToolUsage + : streamingToolUsage + : streamingToolUsage + + if (taskToolUsage) { + for (const [key, usage] of Object.entries(taskToolUsage)) { const tool = key as keyof ToolUsage - if (!toolUsage[tool]) { - toolUsage[tool] = { attempts: 0, failures: 0 } + if (!toolUsageAggregate[tool]) { + toolUsageAggregate[tool] = { attempts: 0, failures: 0 } } - toolUsage[tool].attempts += usage.attempts - toolUsage[tool].failures += usage.failures + toolUsageAggregate[tool].attempts += usage.attempts + toolUsageAggregate[tool].failures += usage.failures } } } @@ -427,13 +472,15 @@ export function Run({ run }: { run: Run }) { totalTokensOut, totalCost, totalDuration, - toolUsage, + toolUsage: toolUsageAggregate, } - // eslint-disable-next-line react-hooks/exhaustive-deps - }, [tasks, taskMetrics, tokenUsage, usageUpdatedAt]) + // Map refs are stable; usageUpdatedAt triggers recomputation when Map contents change + }, [tasks, taskMetrics, toolUsage, usageUpdatedAt]) // Calculate elapsed time (wall-clock time from run creation to completion or now) const elapsedTime = useMemo(() => { + // Reference usageUpdatedAt to trigger recomputation for live elapsed time updates + void usageUpdatedAt if (!tasks || tasks.length === 0) return null const startTime = new Date(run.createdAt).getTime() @@ -452,7 +499,6 @@ export function Run({ run }: { run: Run }) { // If still running, use current time return Date.now() - startTime - // eslint-disable-next-line react-hooks/exhaustive-deps }, [tasks, run.createdAt, run.taskMetricsId, usageUpdatedAt]) return ( @@ -655,7 +701,14 @@ export function Run({ run }: { run: Run }) { {formatTokens(taskMetrics[task.id]!.tokensContext)} {toolColumns.map((toolName) => { - const usage = task.taskMetrics?.toolUsage?.[toolName] + // Use DB values for finished tasks, but fall back to streaming values + // if DB values are missing (handles race condition during timeout) + const dbUsage = task.taskMetrics?.toolUsage?.[toolName] + const streamingUsage = toolUsage.get(task.id)?.[toolName] + const usage = task.finishedAt + ? (dbUsage ?? streamingUsage) + : streamingUsage + const successRate = usage && usage.attempts > 0 ? ((usage.attempts - usage.failures) / usage.attempts) * 100 diff --git a/apps/web-evals/src/hooks/use-run-status.ts b/apps/web-evals/src/hooks/use-run-status.ts index 5ad9e19ff36..cc7bc8f56b7 100644 --- a/apps/web-evals/src/hooks/use-run-status.ts +++ b/apps/web-evals/src/hooks/use-run-status.ts @@ -1,7 +1,7 @@ import { useState, useCallback, useRef } from "react" import { useQuery, keepPreviousData } from "@tanstack/react-query" -import { type TokenUsage, RooCodeEventName, taskEventSchema } from "@roo-code/types" +import { type TokenUsage, type ToolUsage, RooCodeEventName, taskEventSchema } from "@roo-code/types" import type { Run, Task, TaskMetrics } from "@roo-code/evals" import { getHeartbeat } from "@/actions/heartbeat" @@ -15,6 +15,7 @@ export type RunStatus = { runners: string[] | undefined tasks: (Task & { taskMetrics: TaskMetrics | null })[] | undefined tokenUsage: Map + toolUsage: Map usageUpdatedAt: number | undefined } @@ -23,6 +24,7 @@ export const useRunStatus = (run: Run): RunStatus => { const [usageUpdatedAt, setUsageUpdatedAt] = useState() const tokenUsage = useRef>(new Map()) + const toolUsage = useRef>(new Map()) const startTimes = useRef>(new Map()) const { data: heartbeat } = useQuery({ @@ -78,6 +80,12 @@ export const useRunStatus = (run: Run): RunStatus => { const startTime = startTimes.current.get(taskId) const duration = startTime ? Date.now() - startTime : undefined tokenUsage.current.set(taskId, { ...payload[1], duration }) + + // Track tool usage from streaming updates + if (payload[2]) { + toolUsage.current.set(taskId, payload[2]) + } + setUsageUpdatedAt(Date.now()) break } @@ -96,6 +104,7 @@ export const useRunStatus = (run: Run): RunStatus => { runners, tasks, tokenUsage: tokenUsage.current, + toolUsage: toolUsage.current, usageUpdatedAt, } } diff --git a/apps/web-roo-code/next.config.ts b/apps/web-roo-code/next.config.ts index ec827646071..a2591c1a30f 100644 --- a/apps/web-roo-code/next.config.ts +++ b/apps/web-roo-code/next.config.ts @@ -27,6 +27,11 @@ const nextConfig: NextConfig = { destination: "https://roo-code.notion.site/238fd1401b0a8087b858e1ad431507cf?pvs=105", permanent: false, }, + { + source: "/provider/pricing", + destination: "/provider", + permanent: true, + }, ] }, } diff --git a/apps/web-roo-code/public/heroes/cloud-screen.png b/apps/web-roo-code/public/heroes/cloud-screen.png index 1c6ba660529..2ed2af3f0eb 100644 Binary files a/apps/web-roo-code/public/heroes/cloud-screen.png and b/apps/web-roo-code/public/heroes/cloud-screen.png differ diff --git a/apps/web-roo-code/src/app/cloud/page.tsx b/apps/web-roo-code/src/app/cloud/page.tsx index 7f70f95ffd5..cab1ebd9487 100644 --- a/apps/web-roo-code/src/app/cloud/page.tsx +++ b/apps/web-roo-code/src/app/cloud/page.tsx @@ -1,29 +1,33 @@ import { ArrowRight, + Bot, + Brain, ChartLine, - Cloud, - Lock, + Github, + History, LucideIcon, - Megaphone, - MessageCircleQuestionMark, - ReplaceAll, + Pencil, Router, Share2, + Slack, Users, + Users2, } from "lucide-react" import type { Metadata } from "next" +// import Image from "next/image" import { Button } from "@/components/ui" -import { AnimatedBackground } from "@/components/homepage" +import { AnimatedBackground, UseExamplesSection } from "@/components/homepage" import { SEO } from "@/lib/seo" import { ogImageUrl } from "@/lib/og" import { EXTERNAL_LINKS } from "@/lib/constants" -import Image from "next/image" +// Workaround for next/image choking on these for some reason +// import screenshotDark from "/public/heroes/cloud-screen.png" const TITLE = "Roo Code Cloud" const DESCRIPTION = - "Roo Code Cloud gives you and your team the tools to take AI-coding to the next level with cloud agents, remote control, and more." -const OG_DESCRIPTION = "Go way beyond the IDE" + "Your AI Software Engineering Team in the Cloud. Delegate tasks to autonomous agents, review PRs, and collaborate with your team." +const OG_DESCRIPTION = "Your AI Team in the Cloud" const PATH = "/cloud" export const metadata: Metadata = { @@ -54,161 +58,162 @@ export const metadata: Metadata = { description: DESCRIPTION, images: [ogImageUrl(TITLE, OG_DESCRIPTION)], }, - keywords: [...SEO.keywords, "cloud", "subscription", "cloud agents", "AI cloud development"], + keywords: [...SEO.keywords, "cloud", "subscription", "cloud agents", "AI cloud development", "autonomous agents"], } +const howItWorks = [ + { + title: "1. Connect your GitHub account", + description: + "Pick which repos the agents can work with in their isolated containers and choose what model you want to power each of them. You're in control.", + icon: Github, + }, + { + title: "2. Set up your agent team", + description: + "Choose the roles you want filled, like Explainer, Planner, Coder, PR Reviewer and PR Fixer. They know how to act in each situation and stay on-task with no deviations.", + icon: Users2, + }, + { + title: "3. Start giving them tasks", + description: + "Describe what you want them to do from the web UI, get the Reviewer automatically reviewing PRs, get the Coder building features from Slack threads and much more. They're now part of your team.", + icon: Pencil, + }, +] + interface Feature { icon: LucideIcon title: string description: string - logos?: string[] } -const cloudFeatures: Feature[] = [ - { - icon: Router, - title: "Roomote Control", - description: "Control your IDE from anywhere and keep coding away from your computer.", - }, +const features: Feature[] = [ { - icon: Cloud, - title: "Cloud Agents", + icon: Bot, + title: "Autonomous Cloud Agents", description: - "Specialized agents running in the Cloud to get stuff done while you sleep, with a credit-based system that doesn't lock you in or dumb your models down.", + "Delegate work to specialized agents like the Planner, Coder, Explainer, Reviewer, and Fixer that run 24/7.", }, { - icon: ReplaceAll, - title: "Still Model-agnostic", - description: "Bring your own provider key — no markup, lock-in, no restrictions.", - logos: ["Anthropic", "OpenAI", "Gemini", "Grok", "Qwen", "Kimi", "Mistral", "Ollama"], + icon: Brain, + title: "Model Agnostic", + description: + "Bring your own keys or use the Roo Code Cloud Provider with access to all top models with no markup.", }, { - icon: ChartLine, - title: "Usage Analytics", - description: "Detailed token analytics to help you optimize your costs and usage.", + icon: Github, + title: "GitHub PR Reviews", + description: + "Agents can automatically review Pull Requests, provide feedback, and even push fixes directly to your repository.", }, { - icon: Megaphone, - title: "Early Model Access", - description: "Get early, free access to new, stealth coding models as they become available.", + icon: Slack, + title: "Slack Integration", + description: "Start tasks, get updates, and collaborate with agents directly from your team's Slack channels.", }, { - icon: Share2, - title: "Task Sharing", - description: "Share tasks with friends and co-workers and let them follow your work.", + icon: Router, + title: "Roomote Control", + description: + "Connect to your local VS Code instance and control the extension remotely from the browser or Slack.", }, { icon: Users, - title: "Team Management", + title: "Team Collaboration", description: - "Manage your team and their access to tasks and resources, with centralized billing, analytics and configuration.", + "Manage your team and their access to tasks and resources, with centralized billing and configuration.", }, { - icon: Lock, - title: "Secure and Private", - description: - "Your data is never used for training, and we're SOC2 Type 2 and GDPR compliant, following state-of-the-art security practices, with deep respect for your IP.", + icon: ChartLine, + title: "Usage Analytics", + description: "Detailed token analytics to help you optimize your costs and usage across your team.", }, { - icon: MessageCircleQuestionMark, - title: "Priority support", - description: "Get quick help from the people who know Roo best.", + icon: History, + title: "Task History", + description: "Access from anywhere all of your tasks, from the cloud and the extension", + }, + { + icon: Share2, + title: "Task Sharing", + description: "Share tasks with friends and co-workers and let them follow your work in real-time.", }, ] -// Workaround for next/image choking on these for some reason -// import screenshotDark from "/public/heroes/cloud-screen.png" - export default function CloudPage() { return ( <> -
+ {/* Hero Section */} +
-
-
-
-
-

- Go way beyond the IDE -

-

- Roo Code Cloud gives you (and your team) the tools to take AI-coding to the next - level -

-
- -
-
-
-
- Screenshot of Roo Code Cloud -
-
+
+
+

+ Your AI Team in the Cloud +

+

+ Create your agent team in the Cloud, give them access to GitHub, and start delegating tasks + from Web and Slack. +

+
+ + {/* Screenshot */} +
+ {/* How It Works Section */}
-
+
+
+
+ +
-

Power and Flexibility

-

- Code in the cloud, access free models, get usage analytics and more +

How it works

+

+ It only takes 2 minutes to expand your team by 10x.

-
    - {cloudFeatures.map((feature, index) => { - const Icon = feature.icon +
      + {howItWorks.map((step, index) => { + const Icon = step.icon return (
    • - + className="relative h-full border border-border rounded-2xl bg-background p-8 transition-all duration-300 hover:shadow-lg"> + {Icon && }

      - {feature.title} + {step.title}

      -

      - {feature.description} -

      - {feature.logos && ( -
      - {feature.logos.map((logo) => ( - {`${logo} - ))} -
      - )} +
      + {step.description} +
    • ) })} @@ -217,25 +222,61 @@ export default function CloudPage() {
-
+ {/* Use Cases Section */} + + + {/* Features Grid */} +
+
+
+
+
+
+

+ Powering the next generation of software development +

+

+ Everything you need to scale your development capacity with AI. +

+
+
+ {features.map((feature, index) => { + const Icon = feature.icon + return ( +
+
+ +
+

{feature.title}

+

{feature.description}

+
+ ) + })} +
+
+
{/* CTA Section */} -
+
-
-

Try Roo Code Cloud now

-

Code from anywhere.

+
+

+ Try a completely new way of working. +

+

Start for free today.

diff --git a/apps/web-roo-code/src/app/extension/page.tsx b/apps/web-roo-code/src/app/extension/page.tsx new file mode 100644 index 00000000000..56219a34519 --- /dev/null +++ b/apps/web-roo-code/src/app/extension/page.tsx @@ -0,0 +1,84 @@ +/* eslint-disable react/jsx-no-target-blank */ + +import { getVSCodeDownloads } from "@/lib/stats" + +import { Button } from "@/components/ui" +import { + AnimatedBackground, + CodeExample, + CompanyLogos, + FAQSection, + Features, + InstallSection, + Testimonials, +} from "@/components/homepage" +import { EXTERNAL_LINKS } from "@/lib/constants" +import { ArrowRight } from "lucide-react" +import { StructuredData } from "@/components/structured-data" + +// Invalidate cache when a request comes in, at most once every hour. +export const revalidate = 3600 + +export default async function ExtensionPage() { + const downloads = await getVSCodeDownloads() + + return ( + <> + +
+ +
+
+
+
+

+ The Open Source AI Coding Assistant for serious work. +

+

+ Specialized modes stay on task and ship great code. +
+ Fully model-agnostic so you can use the best (or most cost-effective) model for + each task. +

+

+ Stop chasing this week's hot new model or CLI tool and go deep with Roo Code. +

+
+ +
+ +
+
+
+
+ +
+
+
+
+
+
+ +
+
+ +
+
+ +
+ + + ) +} diff --git a/apps/web-roo-code/src/app/pricing/page.tsx b/apps/web-roo-code/src/app/pricing/page.tsx index 361bc3f7882..9029b9fde8b 100644 --- a/apps/web-roo-code/src/app/pricing/page.tsx +++ b/apps/web-roo-code/src/app/pricing/page.tsx @@ -194,8 +194,8 @@ export default function PricingPage() { )} Inference:{" "} - - Roo Provider + + Roo Provider pricing {" "} credits or{" "} diff --git a/apps/web-roo-code/src/app/provider/pricing/page.tsx b/apps/web-roo-code/src/app/provider/page.tsx similarity index 83% rename from apps/web-roo-code/src/app/provider/pricing/page.tsx rename to apps/web-roo-code/src/app/provider/page.tsx index 4558355d2c6..7bcebae2463 100644 --- a/apps/web-roo-code/src/app/provider/pricing/page.tsx +++ b/apps/web-roo-code/src/app/provider/page.tsx @@ -1,10 +1,10 @@ "use client" import { useEffect, useMemo, useState } from "react" -import { ModelCard } from "./components/model-card" +import { ModelCard } from "./pricing/components/model-card" import { Model, ModelWithTotalPrice, ModelsResponse, SortOption } from "@/lib/types/models" import Link from "next/link" -import { ChevronDown, CircleX, Loader, LoaderCircle, Search } from "lucide-react" +import { ChevronDown, CircleX, Cloud, Loader, LoaderCircle, Puzzle, Search } from "lucide-react" const API_URL = "https://api.roocode.com/proxy/v1/models?include_paid=true" @@ -13,28 +13,29 @@ const faqs = [ question: "What are AI model providers?", answer: "AI model providers offer various language models with different capabilities and pricing.", }, - { - question: "How is pricing calculated?", - answer: "Pricing is based on token usage for input and output, measured per million tokens, like pretty much any other provider out there.", - }, { question: "What is the Roo Code Cloud Provider?", answer: ( <>

This is our very own model provider, optimized to work seamlessly with Roo Code Cloud.

-

- It offers a selection of state-of-the-art LLMs (both closed and open weight) we know work well with - Roo for you to choose, with no markup. -

-

- We also often feature 100% free models which labs share with us for the community to use and provide - feedback. -

+

You don't have to use it to use Roo Code, but it's the easiest way to do it.

), }, { - question: "But how much does the Roo Code Cloud service cost?", + question: "Do I have to use the Roo Code Cloud Provider to use the Roo Code products?", + answer: "Not at all! You can bring your own provider key, no problem. This is just meant to make it easier.", + }, + { + question: "How is pricing calculated?", + answer: "Pricing is based on token usage for input and output, measured per million tokens, like pretty much any other provider out there.", + }, + { + question: "How is my data treated?", + answer: "The Roo Code Cloud provider doesn't keep any of your data, the service only aims to make it easier to use Roo Code. Each model vendor has their own privacy policy though, and usually free models use your data for training, so keep that in mind.", + }, + { + question: "How much does the Roo Code Cloud service cost?", answer: ( <> Our{" "} @@ -57,7 +58,7 @@ function enrichModelWithTotalPrice(model: Model): ModelWithTotalPrice { } } -export default function ProviderPricingPage() { +export default function ProviderPage() { const [models, setModels] = useState([]) const [loading, setLoading] = useState(true) const [error, setError] = useState(null) @@ -133,13 +134,22 @@ export default function ProviderPricingPage() {
-

- Roo Code Cloud Provider Pricing -

-

- See pricing and features for all models we offer in our selection. -
- You can always bring your own key ( +

The Roo Code Cloud Provider

+

+ The easiest way to use Roo Code (in the{" "} + + + Cloud + {" "} + or the{" "} + + + Extension + + ) with the best free and paid models – no separate accounts, no messing with API keys. +

+

+ And you can always bring your own key ( FAQ @@ -240,7 +250,7 @@ export default function ProviderPricingPage() {

{faqs.map((faq, index) => ( -
+

{faq.question}

{faq.answer}

diff --git a/apps/web-roo-code/src/components/chromes/nav-bar.tsx b/apps/web-roo-code/src/components/chromes/nav-bar.tsx index 2442e3b759e..fa51f081cec 100644 --- a/apps/web-roo-code/src/components/chromes/nav-bar.tsx +++ b/apps/web-roo-code/src/components/chromes/nav-bar.tsx @@ -13,7 +13,7 @@ import { EXTERNAL_LINKS } from "@/lib/constants" import { useLogoSrc } from "@/lib/hooks/use-logo-src" import { ScrollButton } from "@/components/ui" import ThemeToggle from "@/components/chromes/theme-toggle" -import { ChevronDown, X } from "lucide-react" +import { Brain, ChevronDown, Cloud, Puzzle, X } from "lucide-react" interface NavBarProps { stars: string | null @@ -25,7 +25,7 @@ export function NavBar({ stars, downloads }: NavBarProps) { const logoSrc = useLogoSrc() return ( -
+
@@ -34,72 +34,89 @@ export function NavBar({ stars, downloads }: NavBarProps) {
{/* Desktop Navigation */} -