Skip to content

Commit a0cd623

Browse files
authored
Merge pull request #83 from trypear/feat/creator-mode-rebased
Creator mode
2 parents 361edc5 + 6aee669 commit a0cd623

File tree

98 files changed

+1440
-577
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

98 files changed

+1440
-577
lines changed

.vscodeignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,9 @@ jest.*
2929
.roomodes
3030
.rooignore
3131
.roo/**
32+
.pearai-agent/**
33+
.pearai-agent-ignore
34+
.pearai-agent-modes
3235
benchmark/**
3336
cline_docs/**
3437
e2e/**

package-lock.json

Lines changed: 93 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -384,6 +384,7 @@
384384
"@google/genai": "^0.9.0",
385385
"@mistralai/mistralai": "^1.3.6",
386386
"@modelcontextprotocol/sdk": "^1.7.0",
387+
"@pearai/core": "file:./../pearai-submodule/core",
387388
"@types/clone-deep": "^4.0.4",
388389
"@types/pdf-parse": "^1.1.4",
389390
"@types/tmp": "^0.2.6",

src/activate/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@ export { handleUri } from "./handleUri"
22
export { registerCommands } from "./registerCommands"
33
export { registerCodeActions } from "./registerCodeActions"
44
export { registerTerminalActions } from "./registerTerminalActions"
5+
export { registerPearListener } from "./registerPearListener"
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
import * as vscode from "vscode"
2+
import { ClineProvider } from "../core/webview/ClineProvider"
3+
import { assert } from "../utils/util"
4+
import { PEARAI_CREATOR_MODE_WEBAPP_MANAGER_SLUG } from "../shared/modes"
5+
6+
export const getPearaiExtension = async () => {
7+
const pearAiExtension = vscode.extensions.getExtension("pearai.pearai")
8+
9+
assert(!!pearAiExtension, "PearAI extension not found")
10+
11+
if (!pearAiExtension.isActive) {
12+
await pearAiExtension.activate()
13+
}
14+
15+
return pearAiExtension
16+
}
17+
18+
// TODO: TYPES
19+
export const getpearAIExports = async () => {
20+
const pearAiExtension = await getPearaiExtension()
21+
22+
assert(!!pearAiExtension.exports, "⚠️⚠️ Error, no PearAI Exports could be found :( ⚠️⚠️");
23+
24+
return pearAiExtension.exports;
25+
}
26+
27+
// TODO: SHOULD HAVE TYPE SYNCED WITH THE PEARAI SUBMODULE!
28+
type CreatorModeState = "OVERLAY_CLOSED" | "OVERLAY_OPEN" | "OVERLAY_CLOSED_CREATOR_ACTIVE"
29+
30+
export const registerPearListener = async (provider: ClineProvider) => {
31+
// Getting the pear ai extension instance
32+
const exports = await getpearAIExports()
33+
34+
exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg: any) => {
35+
console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`)
36+
37+
let canContinue = false;
38+
39+
while(!canContinue) {
40+
await new Promise((resolve) => setTimeout(resolve, 10));
41+
canContinue = provider.viewLaunched && provider.isViewLaunched;
42+
}
43+
44+
45+
// Get the sidebar provider
46+
// Focus the sidebar first
47+
await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus")
48+
49+
// Wait for the view to be ready using a helper function
50+
await ensureViewIsReady(provider)
51+
// Wait a brief moment for UI to update
52+
await new Promise((resolve) => setTimeout(resolve, 3000))
53+
54+
// * This does actually work but the UI update does not happen. This method calls this.postStateToWebview() so not sure what is going on - James
55+
if(msg.newProjectType === "WEBAPP") {
56+
// Only switch to the creator manager if we're creating a new project
57+
// TODO: later when we need to make a different type of project, we need to change this
58+
await provider.handleModeSwitch(PEARAI_CREATOR_MODE_WEBAPP_MANAGER_SLUG);
59+
}
60+
61+
// Clicl the chat btn
62+
await provider.postMessageToWebview({ type: "action", action: "chatButtonClicked" })
63+
64+
const creatorModeConfig = {
65+
creatorMode: true,
66+
newProjectType: msg.newProjectType,
67+
newProjectPath: msg.newProjectPath,
68+
}
69+
70+
71+
// Initialize with task
72+
await provider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig);
73+
});
74+
// If there's a creator event in the cache after the extensions were refreshed, we need to get it!
75+
exports.pearAPI.creatorMode.triggerCachedCreatorEvent(true);
76+
77+
exports.pearAPI.creatorMode.onDidChangeCreatorModeState(async (state: CreatorModeState) => {
78+
// Get the sidebar provider
79+
const sidebarProvider = ClineProvider.getVisibleInstance();
80+
81+
if (sidebarProvider) {
82+
// Send a message to the webview that will trigger a window event
83+
sidebarProvider.postMessageToWebview({
84+
type: "creatorModeUpdate",
85+
text: state,
86+
});
87+
}
88+
});
89+
90+
}
91+
92+
// TODO: decide if this is needed
93+
// Helper function to ensure the webview is ready
94+
async function ensureViewIsReady(provider: ClineProvider): Promise<void> {
95+
// If the view is already launched, we're good to go
96+
if (provider.viewLaunched) {
97+
return
98+
}
99+
100+
// Otherwise, we need to wait for it to initialize
101+
return new Promise<void>((resolve) => {
102+
// Set up a one-time listener for when the view is ready
103+
const disposable = provider.on("clineCreated", () => {
104+
// Clean up the listener
105+
disposable.dispose()
106+
resolve()
107+
})
108+
109+
// Set a timeout just in case
110+
setTimeout(() => {
111+
disposable.dispose()
112+
resolve()
113+
}, 5000)
114+
})
115+
}

src/api/providers/anthropic.ts

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -105,9 +105,18 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa
105105
case "claude-3-opus-20240229":
106106
case "claude-3-haiku-20240307":
107107
betas.push("prompt-caching-2024-07-31")
108+
// Include prompt_key if newProjectType is set
108109
return {
109-
headers: { "anthropic-beta": betas.join(",") },
110-
authorization: `Bearer ${this.options.apiKey}`,
110+
headers: {
111+
"anthropic-beta": betas.join(","),
112+
prompt_key: this.options.creatorModeConfig?.newProjectType
113+
? String(this.options.creatorModeConfig.newProjectType)
114+
: undefined,
115+
project_path: this.options.creatorModeConfig?.newProjectPath
116+
? String(this.options.creatorModeConfig.newProjectPath)
117+
: undefined,
118+
authorization: `Bearer ${this.options.apiKey}`,
119+
},
111120
}
112121
default:
113122
return undefined

src/api/providers/pearai/pearai.ts

Lines changed: 23 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -116,28 +116,33 @@ export class PearAIHandler extends BaseProvider implements SingleCompletionHandl
116116
}
117117

118118
async *createMessage(systemPrompt: string, messages: any[]): AsyncGenerator<any> {
119-
const generator = this.handler.createMessage(systemPrompt, messages)
120-
let warningMsg = ""
119+
try {
120+
const generator = this.handler.createMessage(systemPrompt, messages)
121+
let warningMsg = ""
121122

122-
for await (const chunk of generator) {
123-
console.dir(chunk)
124-
if (chunk.type === "text" && chunk.metadata?.ui_only) {
125-
warningMsg += chunk.metadata?.content
126-
continue
123+
for await (const chunk of generator) {
124+
console.dir(chunk)
125+
if (chunk.type === "text" && chunk.metadata?.ui_only) {
126+
warningMsg += chunk.metadata?.content ?? ""
127+
continue
128+
}
129+
yield chunk
127130
}
128-
yield chunk
129-
}
130131

131-
if (warningMsg) {
132-
if (warningMsg.includes("pay-as-you-go")) {
133-
vscode.window.showInformationMessage(warningMsg, "View Pay-As-You-Go").then((selection) => {
134-
if (selection === "View Pay-As-You-Go") {
135-
vscode.env.openExternal(vscode.Uri.parse("https://trypear.ai/pay-as-you-go"))
136-
}
137-
})
138-
} else {
139-
vscode.window.showInformationMessage(warningMsg)
132+
if (warningMsg) {
133+
if (warningMsg.includes("pay-as-you-go")) {
134+
vscode.window.showInformationMessage(warningMsg, "View Pay-As-You-Go").then((selection) => {
135+
if (selection === "View Pay-As-You-Go") {
136+
vscode.env.openExternal(vscode.Uri.parse("https://trypear.ai/pay-as-you-go"))
137+
}
138+
})
139+
} else {
140+
vscode.window.showInformationMessage(warningMsg)
141+
}
140142
}
143+
} catch (e) {
144+
const errorMessage = e instanceof Error ? e.message : String(e)
145+
vscode.window.showWarningMessage(`Notice: ${errorMessage}`)
141146
}
142147
}
143148

0 commit comments

Comments
 (0)