Skip to content

Feat: Pear Creator View #29

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 11 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/api/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import { RequestyHandler } from "./providers/requesty"
import { PearAiHandler } from "./providers/pearai"

export interface SingleCompletionHandler {
completePrompt(prompt: string): Promise<string>
completePrompt(prompt: string, useCreatorMode?: boolean): Promise<string>
}

export interface ApiHandler {
Expand Down
100 changes: 99 additions & 1 deletion src/core/webview/ClineProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ import { Cline } from "../Cline"
import { openMention } from "../mentions"
import { getNonce } from "./getNonce"
import { getUri } from "./getUri"
import { PearAiHandler } from "../../api/providers/pearai"

/*
https://github.com/microsoft/vscode-webview-ui-toolkit-samples/blob/main/default/weather-webview/src/providers/WeatherViewProvider.ts
Expand All @@ -73,10 +74,12 @@ export class ClineProvider implements vscode.WebviewViewProvider {
private latestAnnouncementId = "jan-21-2025-custom-modes" // update to some unique identifier when we add a new announcement
configManager: ConfigManager
customModesManager: CustomModesManager
private proprietaryContext: string[] = []

constructor(
readonly context: vscode.ExtensionContext,
private readonly outputChannel: vscode.OutputChannel,
public viewType: "pearai.roo.agentChat" | "pearai.roo.creatorOverlayView" = "pearai.roo.agentChat",
) {
this.outputChannel.appendLine("ClineProvider instantiated")
ClineProvider.activeInstances.add(this)
Expand All @@ -86,6 +89,8 @@ export class ClineProvider implements vscode.WebviewViewProvider {
await this.postStateToWebview()
})

this.listenForPearAiMessages()

// Initialize MCP Hub through the singleton manager
McpServerManager.getInstance(this.context, this)
.then((hub) => {
Expand Down Expand Up @@ -127,6 +132,30 @@ export class ClineProvider implements vscode.WebviewViewProvider {
McpServerManager.unregisterProvider(this)
}

private async listenForPearAiMessages() {
// Getting the pear ai extension instance
const pearaiExtension = vscode.extensions.getExtension("pearai.pearai")

if (!pearaiExtension) {
console.log("PearAI Extension not found")
return
}

if (!pearaiExtension.isActive) {
await pearaiExtension.activate()
}

// Access the API directly from exports
if (pearaiExtension.exports) {
// TODO: SETUP TYPES FOR THE PEAR AI EXPORT
pearaiExtension.exports.pearAPI.creatorMode.onDidRequestExecutePlan((msg: any) => {
console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`)
})
} else {
console.log("PearAI API not available in exports")
}
}

public static getVisibleInstance(): ClineProvider | undefined {
return findLast(Array.from(this.activeInstances), (instance) => instance.view?.visible === true)
}
Expand Down Expand Up @@ -317,7 +346,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
this.outputChannel.appendLine("Webview view resolved")
}

public async initClineWithTask(task?: string, images?: string[]) {
public async initClineWithTask(task?: string, images?: string[], proprietaryContext?: ("CreatorMode" | string)[]) {
this.proprietaryContext = proprietaryContext ?? []
// TODO - MUST DO BEFORE MERGE - WE NEED TO HANDLE THE PROPRIETARY CONTEXT
await this.clearTask()
const {
apiConfiguration,
Expand Down Expand Up @@ -414,6 +445,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
window.$RefreshReg$ = () => {}
window.$RefreshSig$ = () => (type) => type
window.__vite_plugin_react_preamble_installed__ = true
window.viewType = "${this.viewType}";
</script>
`

Expand Down Expand Up @@ -510,6 +542,9 @@ export class ClineProvider implements vscode.WebviewViewProvider {
<meta http-equiv="Content-Security-Policy" content="default-src 'none'; font-src ${webview.cspSource}; style-src ${webview.cspSource} 'unsafe-inline'; img-src ${webview.cspSource} data:; script-src 'nonce-${nonce}'; connect-src ${webview.cspSource} https://stingray-app-gb2an.ondigitalocean.app;">
<link rel="stylesheet" type="text/css" href="${stylesUri}">
<link href="${codiconsUri}" rel="stylesheet" />
<script nonce="${nonce}" type="module">
window.viewType = "${this.viewType}";
</script>
<title>Roo Code</title>
</head>
<body>
Expand Down Expand Up @@ -735,6 +770,68 @@ export class ClineProvider implements vscode.WebviewViewProvider {
// initializing new instance of Cline will make sure that any agentically running promises in old instance don't affect our new task. this essentially creates a fresh slate for the new task
await this.initClineWithTask(message.text, message.images)
break
case "newCreatorModeTask":
// TODO: Get back the plan from the AI model
// Return the plan to the UI to be edited
const { apiConfiguration } = await this.getState()
// apiConfiguration.apiModelId
// const pearAiModels = usePearAiModels(apiConfiguration)
// const pearAI = vscode.extensions.getExtension("pearai.pearai");
// if(!pearAI) {
// console.warn("COULDN'T FIND PEAR AI SUBMODULE");
// }
// pearAI?.exports
// console.log("PEAR AI EXPORTS", pearAI?.exports);
const systemPrompt = `
Best practices:
For any webapp project, ALWAYS adhere to these rules, unless otherwise specified:
React with TypeScript for the frontend
Tailwind CSS for styling
Shadcn/UI components (via Radix UI)
Supabase for backend/database
React Query for data management
React Router for navigation
Recharts for data visualization
React Hook Form for form handling`
const pearAIClass = new PearAiHandler(apiConfiguration)
let responseText = ""
const messageGenerator = pearAIClass.createMessage(systemPrompt, [
{
role: "user",
content: message.text,
},
])

for await (const chunk of messageGenerator) {
if (chunk.type === "text") {
responseText += chunk.text
}

await this.postMessageToWebview({
type: "planCreationStream",
text: responseText,
})
}
await this.postMessageToWebview({
type: "planCreationSuccess",
text: responseText,
})

break
case "creatorModePlannedTaskSubmit":
// TODO: Trigger the "newTask" flow flow, initialising cline with a task
// Go into the planned mode shizz
// vscode.commands.executeCommand("workbench.action.enterCreatorMode")
await this.postMessageToWebview({
type: "invoke",
invoke: "setChatBoxMessage",
text: message.text,
})
await this.postMessageToWebview({ type: "invoke", invoke: "primaryButtonClick" })

await this.initClineWithTask(message.text, message.images)
await this.postStateToWebview()
break
case "apiConfiguration":
if (message.apiConfiguration) {
await this.updateApiConfiguration(message.apiConfiguration)
Expand Down Expand Up @@ -1338,6 +1435,7 @@ export class ClineProvider implements vscode.WebviewViewProvider {
try {
await this.configManager.saveConfig(message.text, message.apiConfiguration)
const listApiConfig = await this.configManager.listConfig()

await this.updateGlobalState("listApiConfigMeta", listApiConfig)
} catch (error) {
this.outputChannel.appendLine(
Expand Down
10 changes: 8 additions & 2 deletions src/extension.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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, "pearai.roo.agentChat")

context.subscriptions.push(
vscode.window.registerWebviewViewProvider(ClineProvider.sideBarId, sidebarProvider, {
Expand Down Expand Up @@ -79,6 +79,12 @@ export function activate(context: vscode.ExtensionContext) {
}),
)

const creatorOverlay = new ClineProvider(context, outputChannel, "pearai.roo.creatorOverlayView")

context.subscriptions.push(
vscode.window.registerWebviewViewProvider("pearai.roo.creatorOverlayView", creatorOverlay),
)

// context.subscriptions.push(
// vscode.commands.registerCommand("roo-cline.mcpButtonClicked", () => {
// sidebarProvider.postMessageToWebview({ type: "action", action: "mcpButtonClicked" })
Expand All @@ -95,7 +101,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, "pearai.roo.agentChat")
//const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined
const lastCol = Math.max(...vscode.window.visibleTextEditors.map((editor) => editor.viewColumn || 0))

Expand Down
4 changes: 4 additions & 0 deletions src/shared/ExtensionMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ export interface ExtensionMessage {
| "updateCustomMode"
| "deleteCustomMode"
| "currentCheckpointUpdated"
| "planCreationStream"
| "planCreationSuccess"
text?: string
action?:
| "chatButtonClicked"
Expand Down Expand Up @@ -194,6 +196,8 @@ export interface ClineSayTool {
| "searchFiles"
| "switchMode"
| "newTask"
| "newCreatorModeTask"
| "creatorModePlannedTaskSubmit"
path?: string
diff?: string
content?: string
Expand Down
4 changes: 4 additions & 0 deletions src/shared/WebviewMessage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export interface WebviewMessage {
| "alwaysAllowExecute"
| "webviewDidLaunch"
| "newTask"
| "newCreatorModeTask"
| "creatorModePlannedTaskSubmit"
| "askResponse"
| "clearTask"
| "didShowAnnouncement"
Expand Down Expand Up @@ -95,6 +97,8 @@ export interface WebviewMessage {
| "openPearAiAuth"
| "deleteMcpServer"
| "maxOpenTabsContext"
| "pearAiHideCreatorLoadingOverlay"
| "pearAiCloseCreatorInterface"
text?: string
disabled?: boolean
askResponse?: ClineAskResponse
Expand Down
68 changes: 68 additions & 0 deletions webview-ui/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions webview-ui/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,15 @@
"build-storybook": "storybook build"
},
"dependencies": {
"@headlessui/react": "^2.2.0",
"@radix-ui/react-alert-dialog": "^1.1.6",
"@radix-ui/react-collapsible": "^1.1.3",
"@radix-ui/react-dialog": "^1.1.6",
"@radix-ui/react-dropdown-menu": "^2.1.5",
"@radix-ui/react-icons": "^1.3.2",
"@radix-ui/react-popover": "^1.1.6",
"@headlessui/react": "^2.2.0",
"@radix-ui/react-select": "^2.1.5",
"@radix-ui/react-progress": "^1.1.2",
"@radix-ui/react-select": "^2.1.5",
"@radix-ui/react-separator": "^1.1.2",
"@radix-ui/react-slider": "^1.2.3",
"@radix-ui/react-slot": "^1.1.2",
Expand All @@ -41,6 +41,7 @@
"react-dom": "^18.3.1",
"react-markdown": "^9.0.3",
"react-remark": "^2.1.0",
"react-router-dom": "^7.3.0",
"react-textarea-autosize": "^8.5.3",
"react-use": "^17.5.1",
"react-virtuoso": "^4.7.13",
Expand Down
Loading