diff --git a/creatormodetask.md b/creatormodetask.md new file mode 100644 index 00000000000..9f24671fc6e --- /dev/null +++ b/creatormodetask.md @@ -0,0 +1,52 @@ +# Creator Mode Task Description + +## Overview + +This project is an **agentic AI extension** for VSCode, forked from **RooCode**, which itself is a fork of **Cline**. Our fork is called **PearAI-Roo-Code**. + +## Goal + +We are implementing a **new view called Creator Mode** into this extension. The objective is to introduce a **separate GUI file structure** to minimize merge conflicts when pulling upstream. However, separation is not a strict requirement—if it makes more sense to integrate changes within the existing structure, we will do so. + +## Guidelines + +- **Maintain Separation:** GUI files should be kept separate to minimize merge conflicts when pulling upstream. +- **Flexible Code Organization:** While separation is preferred, prioritize maintainability and efficiency over strict separation. +- **Keep This Document Updated:** Ensure this file always reflects the latest task status for continuity. +- **Clear and Concise Development:** No unnecessary complexity—keep solutions to the point and functional. +- no bs. +- dont hallucinate. + +## Creator Mode Details + +- Creator Mode will feature a **text input box** at the center, allowing users to enter prompts. +- The design will differ from the existing **ChatView** (`chatview.tsx`), but function similarly in terms of input handling. +- When the user enters a prompt, it will be sent to the **selected AI model**. +- The response will generate a **new file containing an action plan**, which the user can edit directly. +- A new **mode identifier** (`Creator Mode`) will be introduced, similar to the existing **Ask Mode** and **Architect Mode**. + +## Development Plan (Step-by-Step) + +[COMPLETED] - add completed tasks here + +[NEXT STEPS] + +1. **Initial Input Box Implementation** + + - Create a simple input box that sends user input to the selected model. + - Ensure basic communication between the UI and backend. + - Validate that the model receives and processes input correctly. + +2. **Introduce Creator Mode** + + - Understand how existing "ask" mode and "architect" mode are implemented. + - Add `Creator Mode` to the list of available modes. + - Ensure the UI adapts accordingly when this mode is selected. + +3. **Implement File Edit Functionality** + - Modify the response handling to generate an editable file. + - Provide a smooth user experience for modifying action plans. + +- Proceed step-by-step, ensuring each milestone is functional before progressing, so begin with step **1: Implementing the input box** and verifying AI model communication, once stable, move on to **step 2: introducing Creator Mode**. + +This file should be regularly updated to reflect the project's current state and objectives. diff --git a/src/activate/registerCommands.ts b/src/activate/registerCommands.ts index 69e257e7a51..f93558caf4d 100644 --- a/src/activate/registerCommands.ts +++ b/src/activate/registerCommands.ts @@ -51,7 +51,7 @@ const openClineInNewTab = async ({ context, outputChannel }: Omit editor.viewColumn || 0)) @@ -82,5 +82,5 @@ const openClineInNewTab = async ({ context, outputChannel }: Omit {} window.$RefreshSig$ = () => (type) => type window.__vite_plugin_react_preamble_installed__ = true + window.isCreator="${this.isCreator}"; ` @@ -426,6 +433,8 @@ export class ClineProvider implements vscode.WebviewViewProvider { `connect-src https://* ws://${localServerUrl} ws://0.0.0.0:${localPort} http://${localServerUrl} http://0.0.0.0:${localPort} http://localhost:8000 http://0.0.0.0:8000 https://stingray-app-gb2an.ondigitalocean.app`, ] + console.dir("CREATORRRRRR") + console.dir(this.isCreator) return /*html*/ ` diff --git a/src/extension.ts b/src/extension.ts index 5dcfd3169e5..7ec50ee92f3 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -35,7 +35,7 @@ export function activate(context: vscode.ExtensionContext) { context.globalState.update("allowedCommands", defaultCommands) } - const sidebarProvider = new ClineProvider(context, outputChannel) + const sidebarProvider = new ClineProvider(context, outputChannel, false) context.subscriptions.push( vscode.window.registerWebviewViewProvider(ClineProvider.sideBarId, sidebarProvider, { @@ -111,7 +111,7 @@ export function activate(context: vscode.ExtensionContext) { outputChannel.appendLine("Opening Roo Code in new tab") // (this example uses webviewProvider activation event which is necessary to deserialize cached webview, but since we use retainContextWhenHidden, we don't need to use that event) // https://github.com/microsoft/vscode-extension-samples/blob/main/webview-sample/src/extension.ts - const tabProvider = new ClineProvider(context, outputChannel) + const tabProvider = new ClineProvider(context, outputChannel, true) //const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined const lastCol = Math.max(...vscode.window.visibleTextEditors.map((editor) => editor.viewColumn || 0)) @@ -137,7 +137,7 @@ export function activate(context: vscode.ExtensionContext) { // Lock the editor group so clicking on files doesn't open them over the panel await delay(100) - await vscode.commands.executeCommand("workbench.action.lockEditorGroup") + // await vscode.commands.executeCommand("workbench.action.lockEditorGroup") } // context.subscriptions.push(vscode.commands.registerCommand("roo-cline.popoutButtonClicked", openClineInNewTab)) diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index e87edffed16..d5a421b4ff3 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -45,6 +45,7 @@ export interface ExtensionMessage { | "updateCustomMode" | "deleteCustomMode" | "currentCheckpointUpdated" + | "creator" text?: string action?: | "chatButtonClicked" @@ -53,6 +54,7 @@ export interface ExtensionMessage { | "historyButtonClicked" | "promptsButtonClicked" | "didBecomeVisible" + | "generateActionPlan" invoke?: "sendMessage" | "primaryButtonClick" | "secondaryButtonClick" | "setChatBoxMessage" state?: ExtensionState images?: string[] diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index 6f24415b624..4bed49afa41 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -95,6 +95,8 @@ export interface WebviewMessage { | "openPearAiAuth" | "deleteMcpServer" | "maxOpenTabsContext" + | "creator" + | "generateActionPlan" text?: string disabled?: boolean askResponse?: ClineAskResponse diff --git a/src/shared/modes.ts b/src/shared/modes.ts index f7d3a3be3b7..14f2176aa21 100644 --- a/src/shared/modes.ts +++ b/src/shared/modes.ts @@ -74,6 +74,15 @@ export function getToolsForMode(groups: readonly GroupEntry[]): string[] { // Main modes configuration as an ordered array export const modes: readonly ModeConfig[] = [ + { + slug: "creator", + name: "Creator", + roleDefinition: + "You are PearAI Agent (Powered by Roo Code / Cline), a creative and systematic software architect focused on turning high-level ideas into actionable plans. Your primary goal is to help users transform their ideas into structured action plans.", + groups: ["read", ["edit", { fileRegex: "\\.md$", description: "Markdown files only" }], "browser", "mcp"], + customInstructions: + "Your role is to help users transform their ideas into concrete action plans. When a user provides a prompt, analyze it carefully and create a detailed, step-by-step plan that outlines how to implement their idea. Focus on breaking down complex tasks into manageable steps, considering technical requirements, potential challenges, and best practices. The plan should be clear enough that it can be directly implemented by switching to Code mode afterward.", + }, { slug: "code", name: "Code", diff --git a/webview-ui/src/App.tsx b/webview-ui/src/App.tsx index 740ceb11acc..70fa2efb4d1 100644 --- a/webview-ui/src/App.tsx +++ b/webview-ui/src/App.tsx @@ -12,6 +12,7 @@ import WelcomeView from "./components/welcome/WelcomeView" import McpView from "./components/mcp/McpView" import PromptsView from "./components/prompts/PromptsView" import { Inspector } from "react-dev-inspector" +import Creator from "./creator/creator" type Tab = "settings" | "history" | "mcp" | "prompts" | "chat" @@ -83,10 +84,10 @@ const App = () => { ) } +const tempIsCreator: boolean = true + const AppWithProviders = () => ( - - - + {window.isCreator === "true" ? : } ) export default AppWithProviders diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index cd2773d0808..ccd98738e35 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1022,7 +1022,7 @@ const ChatView = ({ isHidden, showAnnouncement, hideAnnouncement, showHistoryVie ...
-
PearAI Coding Agent
+
PearAI Casdfoding Agent
Powered by Roo Code / Cline
diff --git a/webview-ui/src/creator/creator.tsx b/webview-ui/src/creator/creator.tsx new file mode 100644 index 00000000000..2d427c7ce6b --- /dev/null +++ b/webview-ui/src/creator/creator.tsx @@ -0,0 +1,189 @@ +import { useState, useCallback, useEffect, useRef } from "react" +import { vscode } from "../utils/vscode" +import { WebviewMessage } from "../../../src/shared/WebviewMessage" +import { ExtensionMessage, ClineMessage } from "../../../src/shared/ExtensionMessage" +import { Markdown } from "../components/ui/markdown" + +interface Message { + role: "user" | "assistant" + content: string + timestamp: number +} + +const Creator = () => { + const [prompt, setPrompt] = useState("") + const [isProcessing, setIsProcessing] = useState(false) + const [response, setResponse] = useState(null) + const [messages, setMessages] = useState([]) + const [isLoading, setIsLoading] = useState(false) + const [inputValue, setInputValue] = useState("") + const messagesEndRef = useRef(null) + + const handleSubmit = async (e: React.FormEvent) => { + e.preventDefault() + if (!prompt.trim() || isProcessing) return + + setIsProcessing(true) + try { + const message: WebviewMessage = { + type: "creator", + text: prompt.trim(), + } + await vscode.postMessage(message) + setPrompt("") + } finally { + setIsProcessing(false) + } + } + + const handleMessage = useCallback((e: MessageEvent) => { + const message = e.data + if (message.type === "partialMessage" && message.partialMessage) { + setResponse(message.partialMessage) + } + }, []) + + const scrollToBottom = () => { + messagesEndRef.current?.scrollIntoView({ behavior: "smooth" }) + } + + useEffect(() => { + scrollToBottom() + }, [messages]) + + const handleSendMessage = useCallback((text: string) => { + if (!text.trim()) return + + // Add user message to chat + setMessages((prev) => [ + ...prev, + { + role: "user", + content: text.trim(), + timestamp: Date.now(), + }, + ]) + + setIsLoading(true) + + // Send message to extension + vscode.postMessage({ + type: "newTask", + text: text.trim(), + }) + }, []) + + // Add message event listener + useEffect(() => { + const handleMessage = (event: MessageEvent) => { + const message = event.data + + if (message.type === "partialMessage" && message.partialMessage) { + // Handle streaming response + setMessages((prev) => { + const lastMessage = prev[prev.length - 1] + if (lastMessage?.role === "assistant") { + // Update existing assistant message + return [ + ...prev.slice(0, -1), + { + ...lastMessage, + content: lastMessage.content + message.partialMessage.text, + }, + ] + } else { + // Add new assistant message + return [ + ...prev, + { + role: "assistant", + content: message.partialMessage.text || "", + timestamp: Date.now(), + }, + ] + } + }) + setIsLoading(false) + } + } + + window.addEventListener("message", handleMessage) + return () => window.removeEventListener("message", handleMessage) + }, []) + + return ( +
+ {/* Messages container with scrolling */} +
+ {messages.map((msg, i) => ( +
+ {/* Use Markdown component for messages */} + +
+ ))} + + {isLoading && ( +
+
+
+
+
+
+
+ )} + + {/* Scroll anchor */} +
+
+ + {/* Input container */} +
+
+