From 4dcf9f18668889c275598b2abd8c26a4d912ad5b Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 11:21:49 +0100 Subject: [PATCH 01/80] WIP: creator mode shizz --- package-lock.json | 1 - src/activate/index.ts | 1 + src/extension.ts | 9 ++++++++- src/shared/creatorMode.ts | 10 ++++++++++ src/shared/modes.ts | 10 +++++++++- 5 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 src/shared/creatorMode.ts diff --git a/package-lock.json b/package-lock.json index 5e9bd85604e..e543fbb3c36 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17040,7 +17040,6 @@ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "chalk": "^2.4.1", diff --git a/src/activate/index.ts b/src/activate/index.ts index 658bf467f7a..2fff46a5f04 100644 --- a/src/activate/index.ts +++ b/src/activate/index.ts @@ -2,3 +2,4 @@ export { handleUri } from "./handleUri" export { registerCommands } from "./registerCommands" export { registerCodeActions } from "./registerCodeActions" export { registerTerminalActions } from "./registerTerminalActions" +export { registerPearListener } from "./registerPearListener" diff --git a/src/extension.ts b/src/extension.ts index c391aaf0cd2..d4dfe7e7fcc 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -26,7 +26,13 @@ import { TerminalRegistry } from "./integrations/terminal/TerminalRegistry" import { API } from "./exports/api" import { migrateSettings } from "./utils/migrateSettings" -import { handleUri, registerCommands, registerCodeActions, registerTerminalActions } from "./activate" +import { + handleUri, + registerCommands, + registerCodeActions, + registerTerminalActions, + registerPearListener, +} from "./activate" import { formatLanguage } from "./shared/language" /** @@ -202,6 +208,7 @@ export async function activate(context: vscode.ExtensionContext) { registerCodeActions(context) registerTerminalActions(context) + registerPearListener() context.subscriptions.push( vscode.commands.registerCommand("roo-cline.focus", async (...args: any[]) => { diff --git a/src/shared/creatorMode.ts b/src/shared/creatorMode.ts new file mode 100644 index 00000000000..350deea3f39 --- /dev/null +++ b/src/shared/creatorMode.ts @@ -0,0 +1,10 @@ +export const CREATOR_MODE_PLANNING_PROMPT = ` +Depending on the user's request, you may need to do some information gathering (for example using read_file or search_files) to get more context about the task. +You may also ask the user clarifying questions to get a better understanding of the task. +Once you've gained more context about the user's request, you should create a detailed plan for how to accomplish the task. +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. +(Directly write the plan to a markdown file instead of showing it as normal response.)\n\n +Once you create and write the plan, you mark the task as completed. +You only make plans and you should not ask or switch to any other mode. +Keep the plan brief, mainly feature based (include a feature list), and no steps, a product outline.` diff --git a/src/shared/modes.ts b/src/shared/modes.ts index b1a0038fd83..8468d073f2e 100644 --- a/src/shared/modes.ts +++ b/src/shared/modes.ts @@ -1,9 +1,9 @@ import * as vscode from "vscode" - import { GroupOptions, GroupEntry, ModeConfig, PromptComponent, CustomModePrompts, ExperimentId } from "../schemas" import { TOOL_GROUPS, ToolGroup, ALWAYS_AVAILABLE_TOOLS } from "./tools" import { addCustomInstructions } from "../core/prompts/sections/custom-instructions" import { EXPERIMENT_IDS } from "./experiments" +import { CREATOR_MODE_PLANNING_PROMPT } from "./creatorMode" export type Mode = string export type { GroupOptions, GroupEntry, ModeConfig, PromptComponent, CustomModePrompts } @@ -52,6 +52,14 @@ 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: CREATOR_MODE_PLANNING_PROMPT, + }, { slug: "code", name: "💻 Code", From f10215ee5e958241453eea956edfd82394fe46d8 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 11:24:06 +0100 Subject: [PATCH 02/80] WIP: registering pear listener for messages from submodule --- src/activate/registerPearListener.ts | 78 ++++++++++++++++++++++++++++ src/core/webview/ClineProvider.ts | 19 ++++++- src/utils/util.ts | 19 +++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/activate/registerPearListener.ts create mode 100644 src/utils/util.ts diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts new file mode 100644 index 00000000000..4a5e5a66bd3 --- /dev/null +++ b/src/activate/registerPearListener.ts @@ -0,0 +1,78 @@ +import * as vscode from "vscode" +import { ClineProvider } from "../core/webview/ClineProvider" +import { assert } from "../utils/util" + +export const getPearaiExtension = async () => { + const pearAiExtension = vscode.extensions.getExtension("pearai.pearai") + + assert(!!pearAiExtension, "PearAI extension not found") + + if (!pearAiExtension.isActive) { + await pearAiExtension.activate() + } + + return pearAiExtension +} + +export const registerPearListener = async () => { + // Getting the pear ai extension instance + const pearAiExtension = await getPearaiExtension() + + // Access the API directly from exports + if (pearAiExtension.exports) { + pearAiExtension.exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg: any) => { + console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`) + + // Get the sidebar provider + const sidebarProvider = ClineProvider.getSidebarInstance() + + if (sidebarProvider) { + // Focus the sidebar first + await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") + + // Wait for the view to be ready using a helper function + await ensureViewIsReady(sidebarProvider) + + // Switch to creator mode + await sidebarProvider.handleModeSwitch("creator") + await sidebarProvider.postStateToWebview() + + // Navigate to chat view + await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) + + // Wait a brief moment for UI to update + await new Promise((resolve) => setTimeout(resolve, 300)) + + // Initialize with task + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, true) + } + }) + } else { + console.error("⚠️⚠️ PearAI API not available in exports ⚠️⚠️") + } +} + +// TODO: decide if this is needed +// Helper function to ensure the webview is ready +async function ensureViewIsReady(provider: ClineProvider): Promise { + // If the view is already launched, we're good to go + if (provider.viewLaunched) { + return + } + + // Otherwise, we need to wait for it to initialize + return new Promise((resolve) => { + // Set up a one-time listener for when the view is ready + const disposable = provider.on("clineAdded", () => { + // Clean up the listener + disposable.dispose() + resolve() + }) + + // Set a timeout just in case + setTimeout(() => { + disposable.dispose() + resolve() + }, 5000) + }) +} diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 268b7050f8f..17651316a81 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -86,6 +86,7 @@ export class ClineProvider extends EventEmitter implements private readonly outputChannel: vscode.OutputChannel, private readonly renderContext: "sidebar" | "editor" = "sidebar", public readonly contextProxy: ContextProxy, + private readonly isCreatorView: boolean = false, ) { super() @@ -115,6 +116,16 @@ export class ClineProvider extends EventEmitter implements }) } + public static getSidebarInstance(): ClineProvider | undefined { + const sidebar = Array.from(this.activeInstances).find((instance) => !instance.isCreatorView) + + if (!sidebar?.view?.visible) { + vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") + } + + return sidebar + } + // Adds a new Cline instance to clineStack, marking the start of a new task. // The instance is pushed to the top of the stack (LIFO order). // When the task is completed, the top instance is removed, reactivating the previous task. @@ -474,6 +485,7 @@ export class ClineProvider extends EventEmitter implements | "experiments" > > = {}, + creatorMode?: boolean ) { const { apiConfiguration, @@ -493,7 +505,12 @@ export class ClineProvider extends EventEmitter implements const cline = new Cline({ provider: this, - apiConfiguration: { ...apiConfiguration, pearaiAgentModels: pearaiAgentModels }, + apiConfiguration: { + ...apiConfiguration, + ...apiConfiguration, + pearaiAgentModels: pearaiAgentModels + creatorMode, + }, customInstructions: effectiveInstructions, enableDiff, enableCheckpoints, diff --git a/src/utils/util.ts b/src/utils/util.ts new file mode 100644 index 00000000000..54e5cbc8f04 --- /dev/null +++ b/src/utils/util.ts @@ -0,0 +1,19 @@ +class AssertionError extends Error { + constructor(message: string) { + super(message) + // Adding the stack info to error. + // Inspired by: https://blog.dennisokeeffe.com/blog/2020-08-07-error-tracing-with-sentry-and-es6-classes + if (Error.captureStackTrace) { + Error.captureStackTrace(this, AssertionError) + } else { + this.stack = new Error(message).stack + } + this.name = "AssertionError" + } +} + +export function assert(condition: boolean, message: string): asserts condition { + if (!condition) { + throw new AssertionError(message) + } +} From a5101313b2c3e0012319f09fd0ee33b40f4642df Mon Sep 17 00:00:00 2001 From: James Arnott Date: Thu, 17 Apr 2025 13:50:40 +0100 Subject: [PATCH 03/80] fix: sending roo code when we're in creator mode --- src/core/Cline.ts | 5 +++++ src/core/webview/ClineProvider.ts | 33 +++++++++++++++++++++++++++---- src/schemas/index.ts | 2 ++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/core/Cline.ts b/src/core/Cline.ts index d32581be9fa..669c1b93f3e 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -127,6 +127,7 @@ export type ClineOptions = { taskNumber?: number onCreated?: (cline: Cline) => void pearaiModels?: Record + creatorMode?: boolean } export class Cline extends EventEmitter { @@ -142,6 +143,7 @@ export class Cline extends EventEmitter { pausedModeSlug: string = defaultModeSlug private pauseInterval: NodeJS.Timeout | undefined + public creatorMode: boolean readonly apiConfiguration: ApiConfiguration api: ApiHandler private promptCacheKey: string @@ -220,6 +222,7 @@ export class Cline extends EventEmitter { parentTask, taskNumber = -1, onCreated, + creatorMode, }: ClineOptions) { super() @@ -257,6 +260,8 @@ export class Cline extends EventEmitter { this.diffViewProvider = new DiffViewProvider(this.cwd) this.enableCheckpoints = enableCheckpoints + this.creatorMode = creatorMode ?? false + this.rootTask = rootTask this.parentTask = parentTask this.taskNumber = taskNumber diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 17651316a81..bce62f8b8f9 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -498,6 +498,15 @@ export class ClineProvider extends EventEmitter implements experiments, } = await this.getState() + // Update API configuration with creator mode + await this.updateApiConfiguration({ + ...apiConfiguration, + creatorMode, + }) + + // Post updated state to webview immediately + await this.postStateToWebview() + const modePrompt = customModePrompts?.[mode] as PromptComponent const effectiveInstructions = [globalInstructions, modePrompt?.customInstructions].filter(Boolean).join("\n\n") @@ -508,7 +517,7 @@ export class ClineProvider extends EventEmitter implements apiConfiguration: { ...apiConfiguration, ...apiConfiguration, - pearaiAgentModels: pearaiAgentModels + pearaiAgentModels: pearaiAgentModels, creatorMode, }, customInstructions: effectiveInstructions, @@ -523,6 +532,7 @@ export class ClineProvider extends EventEmitter implements taskNumber: this.clineStack.length + 1, onCreated: (cline) => this.emit("clineCreated", cline), ...options, + creatorMode, }) await this.addClineToStack(cline) @@ -841,6 +851,13 @@ export class ClineProvider extends EventEmitter implements async updateApiConfiguration(providerSettings: ProviderSettings) { // Update mode's default config. const { mode } = await this.getState() + const currentCline = this.getCurrentCline() + + // Preserve creator mode when updating configuration + const updatedConfig = { + ...providerSettings, + creatorMode: currentCline?.creatorMode, + } satisfies ProviderSettings; if (mode) { const currentApiConfigName = this.getGlobalState("currentApiConfigName") @@ -852,10 +869,10 @@ export class ClineProvider extends EventEmitter implements } } - await this.contextProxy.setProviderSettings(providerSettings) + await this.contextProxy.setProviderSettings(updatedConfig) if (this.getCurrentCline()) { - this.getCurrentCline()!.api = buildApiHandler(providerSettings) + this.getCurrentCline()!.api = buildApiHandler(updatedConfig) } } @@ -1167,8 +1184,10 @@ export class ClineProvider extends EventEmitter implements } async getStateToPostToWebview() { + const currentCline = this.getCurrentCline() + // Get base state const { - apiConfiguration, + apiConfiguration: baseApiConfiguration, lastShownAnnouncementId, customInstructions, alwaysAllowReadOnly, @@ -1227,6 +1246,12 @@ export class ClineProvider extends EventEmitter implements historyPreviewCollapsed, } = await this.getState() + // Construct API configuration with creator mode + const apiConfiguration = { + ...baseApiConfiguration, + creatorMode: currentCline?.creatorMode, + } + const telemetryKey = process.env.POSTHOG_API_KEY const machineId = vscode.env.machineId const allowedCommands = vscode.workspace.getConfiguration("roo-cline").get("allowedCommands") || [] diff --git a/src/schemas/index.ts b/src/schemas/index.ts index db61b52a2e2..159cfcb7bf7 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -449,6 +449,7 @@ export const providerSettingsSchema = z.object({ defaultModelId: z.string().optional(), }) .optional(), + creatorMode: z.boolean().optional(), }) export type ProviderSettings = z.infer @@ -546,6 +547,7 @@ const providerSettingsRecord: ProviderSettingsRecord = { pearaiApiKey: undefined, pearaiModelInfo: undefined, pearaiAgentModels: undefined, + creatorMode: undefined, // X.AI (Grok) xaiApiKey: undefined, } From 9700c59d92e3ddc4a24f840ea96ae0b67846b430 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Thu, 17 Apr 2025 14:39:49 +0100 Subject: [PATCH 04/80] feat: added creator mode bar --- webview-ui/src/components/chat/ChatView.tsx | 4 + .../src/components/chat/CreatorModeBar.tsx | 64 ++++++++++ .../src/components/chat/button/index.tsx | 116 ++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 webview-ui/src/components/chat/CreatorModeBar.tsx create mode 100644 webview-ui/src/components/chat/button/index.tsx diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 33eb1916aa3..2bc0fb98f14 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -49,6 +49,7 @@ import { vscInputBorder, vscSidebarBorder, } from "../ui" +import { CreatorModeBar } from "./CreatorModeBar" import SystemPromptWarning from "./SystemPromptWarning" import { usePearAIModels } from "@/hooks/usePearAIModels" @@ -1237,6 +1238,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction + {apiConfiguration?.creatorMode === true && ( + + )} {task ? ( <> void + nextCallback?: () => void + className?: string +} +// from: https://vscode.dev/github/trypear/pearai-submodule/blob/acorn/253-submodule-api-fixed/gui/src/pages/creator/ui/planningBar.tsx#L15-L50 +// TODO: UI LIBRARY COMPONENT SHARING SHIZZ HERE! + +export const CreatorModeBar: FC = ({ + isGenerating, + requestedPlan, + playCallback, + nextCallback, + className, +}) => { + return ( +
+ {isGenerating &&
} +
+
+
+
+
Planning
+
+
{requestedPlan}
+
+
+ +
+
+ + + +
+ + {/* */} +
+
+ ) +} diff --git a/webview-ui/src/components/chat/button/index.tsx b/webview-ui/src/components/chat/button/index.tsx new file mode 100644 index 00000000000..a5e043aa6e8 --- /dev/null +++ b/webview-ui/src/components/chat/button/index.tsx @@ -0,0 +1,116 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +// FROM: https://vscode.dev/github/trypear/pearai-submodule/blob/acorn/253-submodule-api-fixed/gui/src/pages/creator/ui/button/index.tsx#L1-L121 +// TODO: UI LIBRARY COMPONENT SHARING SHIZZ HERE! +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 border-none whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[#a1a1aa] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-[#18181b] text-[#fafafa] shadow hover:bg-[#27272a]", + destructive: "bg-[#ef4444] text-[#fafafa] shadow-sm hover:bg-[#dc2626]", + outline: "border border-[#e4e4e7] bg-[#ffffff] shadow-sm hover:bg-[#f4f4f5] hover:text-[#18181b]", + secondary: "bg-[#f4f4f5] text-[#18181b] hover:bg-[#e4e4e7]", + ghost: "hover:bg-[#f4f4f5] hover:text-[#18181b]", + link: "text-[#18181b] underline-offset-4 hover:underline", + }, + size: { + // default: "h-9 px-4 py-2", + default: "h-7 rounded-md px-2 text-md", + sm: "h-6 rounded-md px-2 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + toggled: { + true: "", + }, + }, + compoundVariants: [ + { + variant: "default", + toggled: true, + className: " bg-[#3030ad] text-[#0B84FF] hover:bg-[#3a3ad2]", // bg-[#27272a] text-[#fafafa] + }, + { + variant: "destructive", + toggled: true, + className: "bg-[#dc2626] text-[#fafafa]", + }, + { + variant: "outline", + toggled: true, + className: "bg-[#f4f4f5] text-[#18181b] border-[#a1a1aa]", + }, + { + variant: "secondary", + toggled: true, + // className: "bg-[#e4e4e7] text-[#18181b]" + className: "bg-[#E3EFFF] text-[#4388F8] hover:bg-[#D1E3FF]", + }, + { + variant: "ghost", + toggled: true, + className: "bg-[#f4f4f5] text-[#18181b]", + }, + { + variant: "link", + toggled: true, + className: "text-[#18181b] underline", + }, + ], + defaultVariants: { + variant: "default", + size: "default", + toggled: false, + }, + }, +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean + onToggle?: (toggled: boolean) => void +} + +const Button = React.forwardRef( + ( + { className, variant, size, toggled: initialToggled = false, asChild = false, onToggle, onClick, ...props }, + ref, + ) => { + const Comp = asChild ? Slot : "button" + const [toggled, setToggled] = React.useState(initialToggled) + + const handleClick = (event: React.MouseEvent) => { + if (onToggle) { + const newToggled = !toggled + setToggled(newToggled) + onToggle(newToggled) + } + + onClick?.(event) + } + + return ( + + ) + }, +) +Button.displayName = "Button" + +export { Button, buttonVariants } From c0170291833d5abd2425fccb8096ee04f3d98fd3 Mon Sep 17 00:00:00 2001 From: nang-dev Date: Sat, 19 Apr 2025 17:05:33 -0400 Subject: [PATCH 05/80] Added newProject filtering --- src/activate/registerPearListener.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 4a5e5a66bd3..198276dae94 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -33,10 +33,11 @@ export const registerPearListener = async () => { // Wait for the view to be ready using a helper function await ensureViewIsReady(sidebarProvider) - // Switch to creator mode - await sidebarProvider.handleModeSwitch("creator") - await sidebarProvider.postStateToWebview() - + if (msg.newProject) { + // Switch to creator mode + await sidebarProvider.handleModeSwitch("creator") + await sidebarProvider.postStateToWebview() + } // Navigate to chat view await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) @@ -44,7 +45,7 @@ export const registerPearListener = async () => { await new Promise((resolve) => setTimeout(resolve, 300)) // Initialize with task - await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, true) + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, msg.newProject) } }) } else { From 2f2e1c14a9c4df9d8c41b031e2010eeff9bcc3b8 Mon Sep 17 00:00:00 2001 From: nang-dev Date: Wed, 23 Apr 2025 21:42:53 -0400 Subject: [PATCH 06/80] Progress --- src/activate/registerPearListener.ts | 10 ++++++++-- src/api/providers/anthropic.ts | 9 ++++++++- src/core/Cline.ts | 4 ++++ src/core/webview/ClineProvider.ts | 17 +++++++++-------- src/exports/roo-code.d.ts | 2 ++ src/exports/types.ts | 2 ++ src/schemas/index.ts | 2 ++ src/shared/creatorMode.ts | 10 ---------- src/shared/modes.ts | 4 ++-- src/shared/pearaiApi.ts | 4 ++-- 10 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 198276dae94..d557dd197d8 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -33,7 +33,7 @@ export const registerPearListener = async () => { // Wait for the view to be ready using a helper function await ensureViewIsReady(sidebarProvider) - if (msg.newProject) { + if (msg.creatorMode) { // Switch to creator mode await sidebarProvider.handleModeSwitch("creator") await sidebarProvider.postStateToWebview() @@ -45,7 +45,13 @@ export const registerPearListener = async () => { await new Promise((resolve) => setTimeout(resolve, 300)) // Initialize with task - await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, msg.newProject) + await sidebarProvider.initClineWithTask( + msg.plan, + undefined, + undefined, + msg.creatorMode, + msg.newProjectType, + ) } }) } else { diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index f80fde03439..e39b3b1d67d 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -105,8 +105,15 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa case "claude-3-opus-20240229": case "claude-3-haiku-20240307": betas.push("prompt-caching-2024-07-31") + + // Include prompt_key if newProjectType is set return { - headers: { "anthropic-beta": betas.join(",") }, + headers: { + "anthropic-beta": betas.join(","), + ...(String(this.options.newProjectType) + ? { prompt_key: String(this.options.newProjectType) } + : {}), + }, authorization: `Bearer ${this.options.apiKey}`, } default: diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 669c1b93f3e..c76ecebccb6 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -128,6 +128,7 @@ export type ClineOptions = { onCreated?: (cline: Cline) => void pearaiModels?: Record creatorMode?: boolean + newProjectType?: string } export class Cline extends EventEmitter { @@ -144,6 +145,7 @@ export class Cline extends EventEmitter { private pauseInterval: NodeJS.Timeout | undefined public creatorMode: boolean + public newProjectType: string readonly apiConfiguration: ApiConfiguration api: ApiHandler private promptCacheKey: string @@ -223,6 +225,7 @@ export class Cline extends EventEmitter { taskNumber = -1, onCreated, creatorMode, + newProjectType, }: ClineOptions) { super() @@ -261,6 +264,7 @@ export class Cline extends EventEmitter { this.enableCheckpoints = enableCheckpoints this.creatorMode = creatorMode ?? false + this.newProjectType = newProjectType ?? "" this.rootTask = rootTask this.parentTask = parentTask diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index bce62f8b8f9..9391a9ba9fa 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -464,12 +464,9 @@ export class ClineProvider extends EventEmitter implements return this.initClineWithTask(task, images, parent) } - // When initializing a new task, (not from history but from a tool command - // new_task) there is no need to remove the previouse task since the new - // task is a subtask of the previous one, and when it finishes it is removed - // from the stack and the caller is resumed in this way we can have a chain - // of tasks, each one being a sub task of the previous one until the main - // task is finished. + // when initializing a new task, (not from history but from a tool command new_task) there is no need to remove the previouse task + // since the new task is a sub task of the previous one, and when it finishes it is removed from the stack and the caller is resumed + // in this way we can have a chain of tasks, each one being a sub task of the previous one until the main task is finished public async initClineWithTask( task?: string, images?: string[], @@ -485,7 +482,8 @@ export class ClineProvider extends EventEmitter implements | "experiments" > > = {}, - creatorMode?: boolean + creatorMode?: boolean, + newProjectType?: string, ) { const { apiConfiguration, @@ -502,6 +500,7 @@ export class ClineProvider extends EventEmitter implements await this.updateApiConfiguration({ ...apiConfiguration, creatorMode, + newProjectType, }) // Post updated state to webview immediately @@ -516,7 +515,6 @@ export class ClineProvider extends EventEmitter implements provider: this, apiConfiguration: { ...apiConfiguration, - ...apiConfiguration, pearaiAgentModels: pearaiAgentModels, creatorMode, }, @@ -533,6 +531,7 @@ export class ClineProvider extends EventEmitter implements onCreated: (cline) => this.emit("clineCreated", cline), ...options, creatorMode, + newProjectType, }) await this.addClineToStack(cline) @@ -857,6 +856,7 @@ export class ClineProvider extends EventEmitter implements const updatedConfig = { ...providerSettings, creatorMode: currentCline?.creatorMode, + newProjectType: currentCline?.newProjectType, } satisfies ProviderSettings; if (mode) { @@ -1250,6 +1250,7 @@ export class ClineProvider extends EventEmitter implements const apiConfiguration = { ...baseApiConfiguration, creatorMode: currentCline?.creatorMode, + newProjectType: currentCline?.newProjectType, } const telemetryKey = process.env.POSTHOG_API_KEY diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index 4eef2426dab..7978f5a3850 100644 --- a/src/exports/roo-code.d.ts +++ b/src/exports/roo-code.d.ts @@ -202,6 +202,8 @@ type ProviderSettings = { defaultModelId?: string | undefined } | undefined + creatorMode?: boolean | undefined + newProjectType?: string | undefined } type GlobalSettings = { diff --git a/src/exports/types.ts b/src/exports/types.ts index 0b557dd0baf..69b1f9f4d79 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -203,6 +203,8 @@ type ProviderSettings = { defaultModelId?: string | undefined } | undefined + creatorMode?: boolean | undefined + newProjectType?: string | undefined } export type { ProviderSettings } diff --git a/src/schemas/index.ts b/src/schemas/index.ts index 159cfcb7bf7..edfdb2d32a1 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -450,6 +450,7 @@ export const providerSettingsSchema = z.object({ }) .optional(), creatorMode: z.boolean().optional(), + newProjectType: z.string().optional(), }) export type ProviderSettings = z.infer @@ -548,6 +549,7 @@ const providerSettingsRecord: ProviderSettingsRecord = { pearaiModelInfo: undefined, pearaiAgentModels: undefined, creatorMode: undefined, + newProjectType: undefined, // X.AI (Grok) xaiApiKey: undefined, } diff --git a/src/shared/creatorMode.ts b/src/shared/creatorMode.ts index 350deea3f39..e69de29bb2d 100644 --- a/src/shared/creatorMode.ts +++ b/src/shared/creatorMode.ts @@ -1,10 +0,0 @@ -export const CREATOR_MODE_PLANNING_PROMPT = ` -Depending on the user's request, you may need to do some information gathering (for example using read_file or search_files) to get more context about the task. -You may also ask the user clarifying questions to get a better understanding of the task. -Once you've gained more context about the user's request, you should create a detailed plan for how to accomplish the task. -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. -(Directly write the plan to a markdown file instead of showing it as normal response.)\n\n -Once you create and write the plan, you mark the task as completed. -You only make plans and you should not ask or switch to any other mode. -Keep the plan brief, mainly feature based (include a feature list), and no steps, a product outline.` diff --git a/src/shared/modes.ts b/src/shared/modes.ts index 8468d073f2e..23940d87941 100644 --- a/src/shared/modes.ts +++ b/src/shared/modes.ts @@ -3,7 +3,8 @@ import { GroupOptions, GroupEntry, ModeConfig, PromptComponent, CustomModePrompt import { TOOL_GROUPS, ToolGroup, ALWAYS_AVAILABLE_TOOLS } from "./tools" import { addCustomInstructions } from "../core/prompts/sections/custom-instructions" import { EXPERIMENT_IDS } from "./experiments" -import { CREATOR_MODE_PLANNING_PROMPT } from "./creatorMode" + +// Mode types export type Mode = string export type { GroupOptions, GroupEntry, ModeConfig, PromptComponent, CustomModePrompts } @@ -58,7 +59,6 @@ export const modes: readonly ModeConfig[] = [ 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: CREATOR_MODE_PLANNING_PROMPT, }, { slug: "code", diff --git a/src/shared/pearaiApi.ts b/src/shared/pearaiApi.ts index 0d110218aa3..c0a5e4d3656 100644 --- a/src/shared/pearaiApi.ts +++ b/src/shared/pearaiApi.ts @@ -1,8 +1,8 @@ // CHANGE AS NEEDED FOR DEVELOPMENT // PROD: -export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" +// export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" // DEV: -// export const PEARAI_URL = "http://localhost:8000/integrations/cline" +export const PEARAI_URL = "http://localhost:8000/integrations/cline" import { anthropicModels, From 9ab8d868f3846e5bc624e2774b8ab315e4bc6173 Mon Sep 17 00:00:00 2001 From: nang-dev Date: Wed, 23 Apr 2025 23:09:49 -0400 Subject: [PATCH 07/80] Added creatorModeConfig --- src/activate/registerPearListener.ts | 22 +++++++++++--------- src/api/providers/anthropic.ts | 12 ++++++----- src/core/Cline.ts | 14 +++++-------- src/core/webview/ClineProvider.ts | 23 ++++++++------------- src/exports/roo-code.d.ts | 9 ++++++-- src/exports/types.ts | 9 ++++++-- src/schemas/index.ts | 14 +++++++++---- src/shared/pearaiApi.ts | 4 ++-- webview-ui/src/components/chat/ChatView.tsx | 2 +- 9 files changed, 60 insertions(+), 49 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index d557dd197d8..0120332522a 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -1,6 +1,8 @@ import * as vscode from "vscode" import { ClineProvider } from "../core/webview/ClineProvider" import { assert } from "../utils/util" +import { CreatorModeConfig } from "../schemas" + export const getPearaiExtension = async () => { const pearAiExtension = vscode.extensions.getExtension("pearai.pearai") @@ -33,7 +35,7 @@ export const registerPearListener = async () => { // Wait for the view to be ready using a helper function await ensureViewIsReady(sidebarProvider) - if (msg.creatorMode) { + if (msg.creatorModeConfig?.creatorMode) { // Switch to creator mode await sidebarProvider.handleModeSwitch("creator") await sidebarProvider.postStateToWebview() @@ -44,14 +46,14 @@ export const registerPearListener = async () => { // Wait a brief moment for UI to update await new Promise((resolve) => setTimeout(resolve, 300)) + let creatorModeConifig = { + creatorMode: msg.creatorMode, + newProjectType: msg.newProjectType, + newProjectPath: msg.newProjectPath, + } satisfies CreatorModeConfig; + // Initialize with task - await sidebarProvider.initClineWithTask( - msg.plan, - undefined, - undefined, - msg.creatorMode, - msg.newProjectType, - ) + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConifig) } }) } else { @@ -68,9 +70,9 @@ async function ensureViewIsReady(provider: ClineProvider): Promise { } // Otherwise, we need to wait for it to initialize - return new Promise((resolve) => { + return new Promise((resolve) => { // Set up a one-time listener for when the view is ready - const disposable = provider.on("clineAdded", () => { + const disposable = provider.on("clineCreated", () => { // Clean up the listener disposable.dispose() resolve() diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index e39b3b1d67d..b65e89e0bb3 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -105,16 +105,18 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa case "claude-3-opus-20240229": case "claude-3-haiku-20240307": betas.push("prompt-caching-2024-07-31") - // Include prompt_key if newProjectType is set return { headers: { "anthropic-beta": betas.join(","), - ...(String(this.options.newProjectType) - ? { prompt_key: String(this.options.newProjectType) } - : {}), + prompt_key: this.options.creatorModeConfig?.newProjectType + ? String(this.options.creatorModeConfig.newProjectType) + : undefined, + project_path: this.options.creatorModeConfig?.newProjectPath + ? String(this.options.creatorModeConfig.newProjectPath) + : undefined, + authorization: `Bearer ${this.options.apiKey}`, }, - authorization: `Bearer ${this.options.apiKey}`, } default: return undefined diff --git a/src/core/Cline.ts b/src/core/Cline.ts index c76ecebccb6..4b627a27262 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -11,7 +11,7 @@ import { serializeError } from "serialize-error" import * as vscode from "vscode" // schemas -import { TokenUsage, ToolUsage, ToolName, ModelInfo } from "../schemas" +import { TokenUsage, ToolUsage, ToolName, ModelInfo, CreatorModeConfig } from "../schemas" // api import { ApiHandler, buildApiHandler } from "../api" @@ -127,8 +127,7 @@ export type ClineOptions = { taskNumber?: number onCreated?: (cline: Cline) => void pearaiModels?: Record - creatorMode?: boolean - newProjectType?: string + creatorModeConfig?: CreatorModeConfig } export class Cline extends EventEmitter { @@ -144,8 +143,7 @@ export class Cline extends EventEmitter { pausedModeSlug: string = defaultModeSlug private pauseInterval: NodeJS.Timeout | undefined - public creatorMode: boolean - public newProjectType: string + public creatorModeConfig: CreatorModeConfig readonly apiConfiguration: ApiConfiguration api: ApiHandler private promptCacheKey: string @@ -224,8 +222,7 @@ export class Cline extends EventEmitter { parentTask, taskNumber = -1, onCreated, - creatorMode, - newProjectType, + creatorModeConfig, }: ClineOptions) { super() @@ -263,8 +260,7 @@ export class Cline extends EventEmitter { this.diffViewProvider = new DiffViewProvider(this.cwd) this.enableCheckpoints = enableCheckpoints - this.creatorMode = creatorMode ?? false - this.newProjectType = newProjectType ?? "" + this.creatorModeConfig = creatorModeConfig ?? { creatorMode: false } this.rootTask = rootTask this.parentTask = parentTask diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 9391a9ba9fa..1ed59ea90bd 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -9,7 +9,7 @@ import axios from "axios" import pWaitFor from "p-wait-for" import * as vscode from "vscode" -import { GlobalState, ProviderSettings, RooCodeSettings } from "../../schemas" +import { CreatorModeConfig, GlobalState, ProviderSettings, RooCodeSettings } from "../../schemas" import { t } from "../../i18n" import { setPanel } from "../../activate/registerCommands" import { @@ -482,8 +482,7 @@ export class ClineProvider extends EventEmitter implements | "experiments" > > = {}, - creatorMode?: boolean, - newProjectType?: string, + creatorModeConfig?: CreatorModeConfig, ) { const { apiConfiguration, @@ -499,8 +498,7 @@ export class ClineProvider extends EventEmitter implements // Update API configuration with creator mode await this.updateApiConfiguration({ ...apiConfiguration, - creatorMode, - newProjectType, + creatorModeConfig, }) // Post updated state to webview immediately @@ -515,9 +513,10 @@ export class ClineProvider extends EventEmitter implements provider: this, apiConfiguration: { ...apiConfiguration, - pearaiAgentModels: pearaiAgentModels, - creatorMode, + creatorModeConfig, + pearaiAgentModels, }, + creatorModeConfig, customInstructions: effectiveInstructions, enableDiff, enableCheckpoints, @@ -530,8 +529,6 @@ export class ClineProvider extends EventEmitter implements taskNumber: this.clineStack.length + 1, onCreated: (cline) => this.emit("clineCreated", cline), ...options, - creatorMode, - newProjectType, }) await this.addClineToStack(cline) @@ -855,9 +852,8 @@ export class ClineProvider extends EventEmitter implements // Preserve creator mode when updating configuration const updatedConfig = { ...providerSettings, - creatorMode: currentCline?.creatorMode, - newProjectType: currentCline?.newProjectType, - } satisfies ProviderSettings; + creatorModeConfig: currentCline?.creatorModeConfig, + } if (mode) { const currentApiConfigName = this.getGlobalState("currentApiConfigName") @@ -1249,8 +1245,7 @@ export class ClineProvider extends EventEmitter implements // Construct API configuration with creator mode const apiConfiguration = { ...baseApiConfiguration, - creatorMode: currentCline?.creatorMode, - newProjectType: currentCline?.newProjectType, + creatorModeConfig: currentCline?.creatorModeConfig, } const telemetryKey = process.env.POSTHOG_API_KEY diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index 7978f5a3850..c6069a5d225 100644 --- a/src/exports/roo-code.d.ts +++ b/src/exports/roo-code.d.ts @@ -202,8 +202,13 @@ type ProviderSettings = { defaultModelId?: string | undefined } | undefined - creatorMode?: boolean | undefined - newProjectType?: string | undefined + creatorModeConfig?: + | { + creatorMode?: boolean | undefined + newProjectType?: string | undefined + newProjectPath?: string | undefined + } + | undefined } type GlobalSettings = { diff --git a/src/exports/types.ts b/src/exports/types.ts index 69b1f9f4d79..2795442a125 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -203,8 +203,13 @@ type ProviderSettings = { defaultModelId?: string | undefined } | undefined - creatorMode?: boolean | undefined - newProjectType?: string | undefined + creatorModeConfig?: + | { + creatorMode?: boolean | undefined + newProjectType?: string | undefined + newProjectPath?: string | undefined + } + | undefined } export type { ProviderSettings } diff --git a/src/schemas/index.ts b/src/schemas/index.ts index edfdb2d32a1..6aa954e1c58 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -339,6 +339,14 @@ export type Experiments = z.infer type _AssertExperiments = AssertEqual>> +export const creatorModeConfigSchema = z.object({ + creatorMode: z.boolean().optional(), + newProjectType: z.string().optional(), + newProjectPath: z.string().optional(), +}); + +export type CreatorModeConfig = z.infer + /** * ProviderSettings */ @@ -449,8 +457,7 @@ export const providerSettingsSchema = z.object({ defaultModelId: z.string().optional(), }) .optional(), - creatorMode: z.boolean().optional(), - newProjectType: z.string().optional(), + creatorModeConfig: creatorModeConfigSchema.optional(), }) export type ProviderSettings = z.infer @@ -548,8 +555,7 @@ const providerSettingsRecord: ProviderSettingsRecord = { pearaiApiKey: undefined, pearaiModelInfo: undefined, pearaiAgentModels: undefined, - creatorMode: undefined, - newProjectType: undefined, + creatorModeConfig: undefined, // X.AI (Grok) xaiApiKey: undefined, } diff --git a/src/shared/pearaiApi.ts b/src/shared/pearaiApi.ts index c0a5e4d3656..0d110218aa3 100644 --- a/src/shared/pearaiApi.ts +++ b/src/shared/pearaiApi.ts @@ -1,8 +1,8 @@ // CHANGE AS NEEDED FOR DEVELOPMENT // PROD: -// export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" +export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" // DEV: -export const PEARAI_URL = "http://localhost:8000/integrations/cline" +// export const PEARAI_URL = "http://localhost:8000/integrations/cline" import { anthropicModels, diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 2bc0fb98f14..69795636d48 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1238,7 +1238,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction - {apiConfiguration?.creatorMode === true && ( + {apiConfiguration?.creatorModeConfig?.creatorMode === true && ( )} {task ? ( From 03d7d7425d6155f4a909856a8ae948aa16882c52 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Tue, 6 May 2025 19:28:02 +0100 Subject: [PATCH 08/80] fix:build --- package-lock.json | 1 + src/core/webview/ClineProvider.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index e543fbb3c36..5e9bd85604e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17040,6 +17040,7 @@ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "chalk": "^2.4.1", diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 1ed59ea90bd..85485f0e9f2 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -850,10 +850,11 @@ export class ClineProvider extends EventEmitter implements const currentCline = this.getCurrentCline() // Preserve creator mode when updating configuration - const updatedConfig = { + const updatedConfig: ProviderSettings = { ...providerSettings, creatorModeConfig: currentCline?.creatorModeConfig, } + if (mode) { const currentApiConfigName = this.getGlobalState("currentApiConfigName") From edd80be981b18146608d4e89ab8ef242421df250 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Thu, 8 May 2025 18:11:20 +0100 Subject: [PATCH 09/80] chore: spelling + types --- src/activate/registerPearListener.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 0120332522a..7a51f905627 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -46,14 +46,14 @@ export const registerPearListener = async () => { // Wait a brief moment for UI to update await new Promise((resolve) => setTimeout(resolve, 300)) - let creatorModeConifig = { + let creatorModeConfig = { creatorMode: msg.creatorMode, newProjectType: msg.newProjectType, newProjectPath: msg.newProjectPath, } satisfies CreatorModeConfig; // Initialize with task - await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConifig) + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig) } }) } else { From 35739ec5adf73d6462194d361063a7e8f60fd1c7 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 11:02:07 +0100 Subject: [PATCH 10/80] fix: not using deep compare effect --- webview-ui/src/components/chat/ChatView.tsx | 352 ++++++++++---------- 1 file changed, 176 insertions(+), 176 deletions(-) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 69795636d48..f2272f52d11 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -160,182 +160,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction { - // if last message is an ask, show user ask UI - // if user finished a task, then start a new task with a new conversation history since in this moment that the extension is waiting for user response, the user could close the extension and the conversation history would be lost. - // basically as long as a task is active, the conversation history will be persisted - if (lastMessage) { - switch (lastMessage.type) { - case "ask": - const isPartial = lastMessage.partial === true - switch (lastMessage.ask) { - case "api_req_failed": - playSound("progress_loop") - setTextAreaDisabled(true) - setClineAsk("api_req_failed") - setEnableButtons(true) - setPrimaryButtonText(t("chat:retry.title")) - setSecondaryButtonText(t("chat:startNewTask.title")) - break - case "mistake_limit_reached": - playSound("progress_loop") - setTextAreaDisabled(false) - setClineAsk("mistake_limit_reached") - setEnableButtons(true) - setPrimaryButtonText(t("chat:proceedAnyways.title")) - setSecondaryButtonText(t("chat:startNewTask.title")) - break - case "followup": - if (!isPartial) { - playSound("notification") - } - setTextAreaDisabled(isPartial) - setClineAsk("followup") - // setting enable buttons to `false` would trigger a focus grab when - // the text area is enabled which is undesirable. - // We have no buttons for this tool, so no problem having them "enabled" - // to workaround this issue. See #1358. - setEnableButtons(true) - setPrimaryButtonText(undefined) - setSecondaryButtonText(undefined) - break - case "tool": - if (!isAutoApproved(lastMessage) && !isPartial) { - playSound("notification") - } - setTextAreaDisabled(isPartial) - setClineAsk("tool") - setEnableButtons(!isPartial) - const tool = JSON.parse(lastMessage.text || "{}") as ClineSayTool - switch (tool.tool) { - case "editedExistingFile": - case "appliedDiff": - case "newFileCreated": - case "insertContent": - setPrimaryButtonText(t("chat:save.title")) - setSecondaryButtonText(t("chat:reject.title")) - break - case "finishTask": - setPrimaryButtonText(t("chat:completeSubtaskAndReturn")) - setSecondaryButtonText(undefined) - break - default: - setPrimaryButtonText(t("chat:approve.title")) - setSecondaryButtonText(t("chat:reject.title")) - break - } - break - case "browser_action_launch": - if (!isAutoApproved(lastMessage) && !isPartial) { - playSound("notification") - } - setTextAreaDisabled(isPartial) - setClineAsk("browser_action_launch") - setEnableButtons(!isPartial) - setPrimaryButtonText(t("chat:approve.title")) - setSecondaryButtonText(t("chat:reject.title")) - break - case "command": - if (!isAutoApproved(lastMessage) && !isPartial) { - playSound("notification") - } - setTextAreaDisabled(isPartial) - setClineAsk("command") - setEnableButtons(!isPartial) - setPrimaryButtonText(t("chat:runCommand.title")) - setSecondaryButtonText(t("chat:reject.title")) - break - case "command_output": - setTextAreaDisabled(false) - setClineAsk("command_output") - setEnableButtons(true) - setPrimaryButtonText(t("chat:proceedWhileRunning.title")) - setSecondaryButtonText(t("chat:killCommand.title")) - break - case "use_mcp_server": - if (!isAutoApproved(lastMessage) && !isPartial) { - playSound("notification") - } - setTextAreaDisabled(isPartial) - setClineAsk("use_mcp_server") - setEnableButtons(!isPartial) - setPrimaryButtonText(t("chat:approve.title")) - setSecondaryButtonText(t("chat:reject.title")) - break - case "completion_result": - // extension waiting for feedback. but we can just present a new task button - if (!isPartial) { - playSound("celebration") - } - setTextAreaDisabled(isPartial) - setClineAsk("completion_result") - setEnableButtons(!isPartial) - setPrimaryButtonText(t("chat:startNewTask.title")) - setSecondaryButtonText(undefined) - break - case "resume_task": - if (!isAutoApproved(lastMessage) && !isPartial) { - playSound("notification") - } - setTextAreaDisabled(false) - setClineAsk("resume_task") - setEnableButtons(true) - setPrimaryButtonText(t("chat:resumeTask.title")) - setSecondaryButtonText(t("chat:terminate.title")) - setDidClickCancel(false) // special case where we reset the cancel button state - break - case "resume_completed_task": - if (!isPartial) { - playSound("celebration") - } - setTextAreaDisabled(false) - setClineAsk("resume_completed_task") - setEnableButtons(true) - setPrimaryButtonText(t("chat:startNewTask.title")) - setSecondaryButtonText(undefined) - setDidClickCancel(false) - break - } - break - case "say": - // Don't want to reset since there could be a "say" after - // an "ask" while ask is waiting for response. - switch (lastMessage.say) { - case "api_req_retry_delayed": - setTextAreaDisabled(true) - break - case "api_req_started": - if (secondLastMessage?.ask === "command_output") { - // If the last ask is a command_output, and we - // receive an api_req_started, then that means - // the command has finished and we don't need - // input from the user anymore (in every other - // case, the user has to interact with input - // field or buttons to continue, which does the - // following automatically). - setInputValue("") - setTextAreaDisabled(true) - setSelectedImages([]) - setClineAsk(undefined) - setEnableButtons(false) - } - break - case "api_req_finished": - case "error": - case "text": - case "browser_action": - case "browser_action_result": - case "command_output": - case "mcp_server_request_started": - case "mcp_server_response": - case "completion_result": - break - } - break - } - } - }, [lastMessage, secondLastMessage]) - useEffect(() => { if (messages.length === 0) { setTextAreaDisabled(false) @@ -850,6 +674,182 @@ const ChatViewComponent: React.ForwardRefRenderFunction { + // if last message is an ask, show user ask UI + // if user finished a task, then start a new task with a new conversation history since in this moment that the extension is waiting for user response, the user could close the extension and the conversation history would be lost. + // basically as long as a task is active, the conversation history will be persisted + if (lastMessage) { + switch (lastMessage.type) { + case "ask": + const isPartial = lastMessage.partial === true + switch (lastMessage.ask) { + case "api_req_failed": + playSound("progress_loop") + setTextAreaDisabled(true) + setClineAsk("api_req_failed") + setEnableButtons(true) + setPrimaryButtonText(t("chat:retry.title")) + setSecondaryButtonText(t("chat:startNewTask.title")) + break + case "mistake_limit_reached": + playSound("progress_loop") + setTextAreaDisabled(false) + setClineAsk("mistake_limit_reached") + setEnableButtons(true) + setPrimaryButtonText(t("chat:proceedAnyways.title")) + setSecondaryButtonText(t("chat:startNewTask.title")) + break + case "followup": + if (!isPartial) { + playSound("notification") + } + setTextAreaDisabled(isPartial) + setClineAsk("followup") + // setting enable buttons to `false` would trigger a focus grab when + // the text area is enabled which is undesirable. + // We have no buttons for this tool, so no problem having them "enabled" + // to workaround this issue. See #1358. + setEnableButtons(true) + setPrimaryButtonText(undefined) + setSecondaryButtonText(undefined) + break + case "tool": + if (!isAutoApproved(lastMessage) && !isPartial) { + playSound("notification") + } + setTextAreaDisabled(isPartial) + setClineAsk("tool") + setEnableButtons(!isPartial) + const tool = JSON.parse(lastMessage.text || "{}") as ClineSayTool + switch (tool.tool) { + case "editedExistingFile": + case "appliedDiff": + case "newFileCreated": + case "insertContent": + setPrimaryButtonText(t("chat:save.title")) + setSecondaryButtonText(t("chat:reject.title")) + break + case "finishTask": + setPrimaryButtonText(t("chat:completeSubtaskAndReturn")) + setSecondaryButtonText(undefined) + break + default: + setPrimaryButtonText(t("chat:approve.title")) + setSecondaryButtonText(t("chat:reject.title")) + break + } + break + case "browser_action_launch": + if (!isAutoApproved(lastMessage) && !isPartial) { + playSound("notification") + } + setTextAreaDisabled(isPartial) + setClineAsk("browser_action_launch") + setEnableButtons(!isPartial) + setPrimaryButtonText(t("chat:approve.title")) + setSecondaryButtonText(t("chat:reject.title")) + break + case "command": + if (!isAutoApproved(lastMessage) && !isPartial) { + playSound("notification") + } + setTextAreaDisabled(isPartial) + setClineAsk("command") + setEnableButtons(!isPartial) + setPrimaryButtonText(t("chat:runCommand.title")) + setSecondaryButtonText(t("chat:reject.title")) + break + case "command_output": + setTextAreaDisabled(false) + setClineAsk("command_output") + setEnableButtons(true) + setPrimaryButtonText(t("chat:proceedWhileRunning.title")) + setSecondaryButtonText(t("chat:killCommand.title")) + break + case "use_mcp_server": + if (!isAutoApproved(lastMessage) && !isPartial) { + playSound("notification") + } + setTextAreaDisabled(isPartial) + setClineAsk("use_mcp_server") + setEnableButtons(!isPartial) + setPrimaryButtonText(t("chat:approve.title")) + setSecondaryButtonText(t("chat:reject.title")) + break + case "completion_result": + // extension waiting for feedback. but we can just present a new task button + if (!isPartial) { + playSound("celebration") + } + setTextAreaDisabled(isPartial) + setClineAsk("completion_result") + setEnableButtons(!isPartial) + setPrimaryButtonText(t("chat:startNewTask.title")) + setSecondaryButtonText(undefined) + break + case "resume_task": + if (!isAutoApproved(lastMessage) && !isPartial) { + playSound("notification") + } + setTextAreaDisabled(false) + setClineAsk("resume_task") + setEnableButtons(true) + setPrimaryButtonText(t("chat:resumeTask.title")) + setSecondaryButtonText(t("chat:terminate.title")) + setDidClickCancel(false) // special case where we reset the cancel button state + break + case "resume_completed_task": + if (!isPartial) { + playSound("celebration") + } + setTextAreaDisabled(false) + setClineAsk("resume_completed_task") + setEnableButtons(true) + setPrimaryButtonText(t("chat:startNewTask.title")) + setSecondaryButtonText(undefined) + setDidClickCancel(false) + break + } + break + case "say": + // Don't want to reset since there could be a "say" after + // an "ask" while ask is waiting for response. + switch (lastMessage.say) { + case "api_req_retry_delayed": + setTextAreaDisabled(true) + break + case "api_req_started": + if (secondLastMessage?.ask === "command_output") { + // If the last ask is a command_output, and we + // receive an api_req_started, then that means + // the command has finished and we don't need + // input from the user anymore (in every other + // case, the user has to interact with input + // field or buttons to continue, which does the + // following automatically). + setInputValue("") + setTextAreaDisabled(true) + setSelectedImages([]) + setClineAsk(undefined) + setEnableButtons(false) + } + break + case "api_req_finished": + case "error": + case "text": + case "browser_action": + case "browser_action_result": + case "command_output": + case "mcp_server_request_started": + case "mcp_server_response": + case "completion_result": + break + } + break + } + } + }, [lastMessage, secondLastMessage, isAutoApproved, t]) + useEffect(() => { // This ensures the first message is not read, future user messages are // labeled as `user_feedback`. From 228f26081865d2d3ac254547e938d63560abaca5 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 12:20:31 +0100 Subject: [PATCH 11/80] fix: creator shizz --- src/activate/registerPearListener.ts | 68 ++++++++++++++++------------ 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 7a51f905627..9d0d62ba6e3 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -24,38 +24,46 @@ export const registerPearListener = async () => { if (pearAiExtension.exports) { pearAiExtension.exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg: any) => { console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`) - // Get the sidebar provider - const sidebarProvider = ClineProvider.getSidebarInstance() - - if (sidebarProvider) { - // Focus the sidebar first - await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") - - // Wait for the view to be ready using a helper function - await ensureViewIsReady(sidebarProvider) - - if (msg.creatorModeConfig?.creatorMode) { - // Switch to creator mode - await sidebarProvider.handleModeSwitch("creator") - await sidebarProvider.postStateToWebview() - } - // Navigate to chat view - await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) - - // Wait a brief moment for UI to update - await new Promise((resolve) => setTimeout(resolve, 300)) - - let creatorModeConfig = { - creatorMode: msg.creatorMode, - newProjectType: msg.newProjectType, - newProjectPath: msg.newProjectPath, - } satisfies CreatorModeConfig; - - // Initialize with task - await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig) + let sidebarProvider = ClineProvider.getVisibleInstance() + + // TODO: LOOK INTO THIS - THIS IS A JANKY FIX AND IT FEELS LIKE THIS IS TEMPERAMENTAL + while (!sidebarProvider) { + await new Promise((resolve) => setTimeout(resolve, 500)) + sidebarProvider = ClineProvider.getVisibleInstance() } - }) + + // Focus the sidebar first + await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") + + // Wait for the view to be ready using a helper function + await ensureViewIsReady(sidebarProvider) + + if (msg.creatorModeConfig?.creatorMode) { + // Switch to creator mode + await sidebarProvider.handleModeSwitch("creator") + await sidebarProvider.postStateToWebview() + } + // Navigate to chat view + await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) + + // Wait a brief moment for UI to update + await new Promise((resolve) => setTimeout(resolve, 300)) + + let creatorModeConfig = { + creatorMode: true, + newProjectType: msg.newProjectType, + newProjectPath: msg.newProjectPath, + } + + console.log('Called init with taskk', msg.plan, undefined, undefined, undefined, creatorModeConfig); + + // Initialize with task + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig); + }); + // If there's a creator event in the cache after the extensions were refreshed, we need to get it! + pearAiExtension.exports.pearAPI.creatorMode.triggerCachedCreatorEvent(true); + console.log("triggerCachedCreatorEvent CALLED!") } else { console.error("⚠️⚠️ PearAI API not available in exports ⚠️⚠️") } From 562f9986ed20eacc7c400242b4e00fa11fe87a80 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 16:46:55 +0100 Subject: [PATCH 12/80] fix: creator mode style --- webview-ui/src/components/chat/ChatView.tsx | 4 +- .../src/components/chat/CreatorModeBar.tsx | 64 ------------------ .../src/components/chat/PlanningBar.tsx | 65 +++++++++++++++++++ webview-ui/src/index.css | 55 ++++++++++++++++ 4 files changed, 122 insertions(+), 66 deletions(-) delete mode 100644 webview-ui/src/components/chat/CreatorModeBar.tsx create mode 100644 webview-ui/src/components/chat/PlanningBar.tsx diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index f2272f52d11..04a3df32d7e 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -49,7 +49,7 @@ import { vscInputBorder, vscSidebarBorder, } from "../ui" -import { CreatorModeBar } from "./CreatorModeBar" +import { PlanningBar } from "./PlanningBar" import SystemPromptWarning from "./SystemPromptWarning" import { usePearAIModels } from "@/hooks/usePearAIModels" @@ -1239,7 +1239,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction {apiConfiguration?.creatorModeConfig?.creatorMode === true && ( - + )} {task ? ( <> diff --git a/webview-ui/src/components/chat/CreatorModeBar.tsx b/webview-ui/src/components/chat/CreatorModeBar.tsx deleted file mode 100644 index c9007cec2ed..00000000000 --- a/webview-ui/src/components/chat/CreatorModeBar.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { CodeBracketIcon, PlayIcon, DocumentTextIcon as OutlineDocumentTextIcon } from "@heroicons/react/24/outline" -import { Button } from "./button" -import { DocumentTextIcon as SolidDocumentTextIcon } from "@heroicons/react/24/solid" -import { FC } from "react" -import { cn } from "@/lib/utils" - -export type PlanningBarProps = { - isGenerating?: boolean - requestedPlan: string - playCallback?: () => void - nextCallback?: () => void - className?: string -} -// from: https://vscode.dev/github/trypear/pearai-submodule/blob/acorn/253-submodule-api-fixed/gui/src/pages/creator/ui/planningBar.tsx#L15-L50 -// TODO: UI LIBRARY COMPONENT SHARING SHIZZ HERE! - -export const CreatorModeBar: FC = ({ - isGenerating, - requestedPlan, - playCallback, - nextCallback, - className, -}) => { - return ( -
- {isGenerating &&
} -
-
-
-
-
Planning
-
-
{requestedPlan}
-
-
- -
-
- - - -
- - {/* */} -
-
- ) -} diff --git a/webview-ui/src/components/chat/PlanningBar.tsx b/webview-ui/src/components/chat/PlanningBar.tsx new file mode 100644 index 00000000000..937022d1841 --- /dev/null +++ b/webview-ui/src/components/chat/PlanningBar.tsx @@ -0,0 +1,65 @@ +import { CodeBracketIcon } from "@heroicons/react/24/outline" +import { Button } from "./button" +import { DocumentTextIcon as SolidDocumentTextIcon } from "@heroicons/react/24/solid" +import { FC } from "react" +import { cn } from "@/lib/utils" + +export type PlanningBarProps = { + isGenerating?: boolean; + requestedPlan: string; + nextCallback?: () => void; + className?: string; +}; + +export const PlanningBar: FC = ({ + isGenerating, + requestedPlan, + nextCallback, + className, +}) => { + return ( +
+ {/* {isGenerating &&
} */} +
+
+
+
+
Planning
+
+
+ {requestedPlan} +
+
+
+ +
+
+ + +
+ + {/* */} +
+
+ ); +}; diff --git a/webview-ui/src/index.css b/webview-ui/src/index.css index f8bf1ab5a64..97f049e3447 100644 --- a/webview-ui/src/index.css +++ b/webview-ui/src/index.css @@ -413,3 +413,58 @@ input[cmdk-input]:focus { .codicon[class*="codicon-"] { text-rendering: geometricPrecision !important; } + + +/* _-_-_-_-_-_-_-_- PEARAI CREATOR STYLES _-_-_-_-_-_-_-_- */ + +.circle { + position: absolute; + left: 50%; + top: 50%; + transform: translateX(-50%) translateY(-50%); + width: 10px; + height: 10px; +} + +/* Static green dot */ +.circle::after { + content: ""; + position: absolute; + left: 0; + top: 0; + display: block; + width: 100%; + height: 100%; + background-color: #75daad; + border-radius: 50px; + z-index: 2; +} + +/* Pulsing outer ring */ +.animated-circle::before { + content: ""; + position: absolute; + left: 0; + top: 0; + display: block; + width: 100%; + height: 100%; + border-radius: 50px; + background-color: #75daad; + opacity: 0.6; + z-index: 1; + animation: pulse-ring 1.5s cubic-bezier(0.215, 0.61, 0.355, 1) infinite; +} + +@keyframes pulse-ring { + 0% { + transform: scale(1); + opacity: 0.6; + } + 100% { + transform: scale(3); + opacity: 0; + } +} + +/* _-_-_-_-_-_-_-_- PEARAI CREATOR STYLES _-_-_-_-_-_-_-_- */ From c0a67cc0ff9558adf87f4b1afe5ddfb461f91eb9 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 17:24:58 +0100 Subject: [PATCH 13/80] fix: task + stop btn --- src/activate/registerPearListener.ts | 2 -- webview-ui/src/components/chat/ChatView.tsx | 6 +++- .../src/components/chat/PlanningBar.tsx | 31 ++++++++++--------- .../src/components/chat/button/index.tsx | 2 +- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 9d0d62ba6e3..c4b87ce3035 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -1,8 +1,6 @@ import * as vscode from "vscode" import { ClineProvider } from "../core/webview/ClineProvider" import { assert } from "../utils/util" -import { CreatorModeConfig } from "../schemas" - export const getPearaiExtension = async () => { const pearAiExtension = vscode.extensions.getExtension("pearai.pearai") diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 04a3df32d7e..76e170c0ae1 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1239,7 +1239,11 @@ const ChatViewComponent: React.ForwardRefRenderFunction {apiConfiguration?.creatorModeConfig?.creatorMode === true && ( - + vscode.postMessage({ type: "cancelTask" })} + /> )} {task ? ( <> diff --git a/webview-ui/src/components/chat/PlanningBar.tsx b/webview-ui/src/components/chat/PlanningBar.tsx index 937022d1841..d6d372a0d90 100644 --- a/webview-ui/src/components/chat/PlanningBar.tsx +++ b/webview-ui/src/components/chat/PlanningBar.tsx @@ -1,26 +1,26 @@ import { CodeBracketIcon } from "@heroicons/react/24/outline" import { Button } from "./button" -import { DocumentTextIcon as SolidDocumentTextIcon } from "@heroicons/react/24/solid" +import { DocumentTextIcon as SolidDocumentTextIcon, StopCircleIcon, StopIcon } from "@heroicons/react/24/solid" import { FC } from "react" import { cn } from "@/lib/utils" export type PlanningBarProps = { isGenerating?: boolean; requestedPlan: string; - nextCallback?: () => void; + stopCallback?: () => void; className?: string; }; export const PlanningBar: FC = ({ isGenerating, requestedPlan, - nextCallback, + stopCallback, className, }) => { return (
@@ -38,26 +38,27 @@ export const PlanningBar: FC = ({
-
+
+
- +
+ + +
- {/* */}
diff --git a/webview-ui/src/components/chat/button/index.tsx b/webview-ui/src/components/chat/button/index.tsx index a5e043aa6e8..82025df2d12 100644 --- a/webview-ui/src/components/chat/button/index.tsx +++ b/webview-ui/src/components/chat/button/index.tsx @@ -6,7 +6,7 @@ import { cn } from "@/lib/utils" // FROM: https://vscode.dev/github/trypear/pearai-submodule/blob/acorn/253-submodule-api-fixed/gui/src/pages/creator/ui/button/index.tsx#L1-L121 // TODO: UI LIBRARY COMPONENT SHARING SHIZZ HERE! const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 border-none whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[#a1a1aa] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + "inline-flex items-center justify-center gap-2 border-none whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[#a1a1aa] disabled:pointer-events-none cursor-pointer disabled:cursor-default disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", { variants: { variant: { From 0a72e5fd35f02a62c484ed870d057ce9ecf0d7e6 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 17:45:16 +0100 Subject: [PATCH 14/80] feat: added message emitter to handle creator mode updates --- src/activate/registerPearListener.ts | 18 +++++++++++++++++- src/shared/ExtensionMessage.ts | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index c4b87ce3035..30c145ce942 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -14,6 +14,9 @@ export const getPearaiExtension = async () => { return pearAiExtension } +// TODO: SHOULD HAVE TYPE SYNCED WITH THE PEARAI SUBMODULE! +type CreatorModeState = "OVERLAY_CLOSED" | "OVERLAY_OPEN" | "OVERLAY_CLOSED_CREATOR_ACTIVE" + export const registerPearListener = async () => { // Getting the pear ai extension instance const pearAiExtension = await getPearaiExtension() @@ -61,7 +64,20 @@ export const registerPearListener = async () => { }); // If there's a creator event in the cache after the extensions were refreshed, we need to get it! pearAiExtension.exports.pearAPI.creatorMode.triggerCachedCreatorEvent(true); - console.log("triggerCachedCreatorEvent CALLED!") + + pearAiExtension.exports.pearAPI.creatorMode.onDidChangeCreatorModeState(async (state: CreatorModeState) => { + // Get the sidebar provider + const sidebarProvider = ClineProvider.getVisibleInstance(); + + if (sidebarProvider) { + // Send a message to the webview that will trigger a window event + sidebarProvider.postMessageToWebview({ + type: "creatorModeUpdate", + text: state, + }); + } + }); + } else { console.error("⚠️⚠️ PearAI API not available in exports ⚠️⚠️") } diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index ec686e5e7e7..5fa819c5cf4 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -68,6 +68,7 @@ export interface ExtensionMessage { | "acceptInput" | "setHistoryPreviewCollapsed" | "commandExecutionStatus" + | "creatorModeUpdate" text?: string action?: | "chatButtonClicked" From 1749a561716b0bad8f9b82dc3025d608415a7b77 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 21:24:46 +0100 Subject: [PATCH 15/80] fix: sizing --- webview-ui/src/components/chat/PlanningBar.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/webview-ui/src/components/chat/PlanningBar.tsx b/webview-ui/src/components/chat/PlanningBar.tsx index d6d372a0d90..b6b9a8006f5 100644 --- a/webview-ui/src/components/chat/PlanningBar.tsx +++ b/webview-ui/src/components/chat/PlanningBar.tsx @@ -25,13 +25,13 @@ export const PlanningBar: FC = ({ )} > {/* {isGenerating &&
} */} -
-
+
+
-
Planning
-
-
+
Planning
+
+
{requestedPlan}
From 23b1c1960f6cf8e86e911b1ec9d7abf80da336cc Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 21:29:50 +0100 Subject: [PATCH 16/80] chore: lil switchup --- src/activate/registerPearListener.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 30c145ce942..bd7c6e7f64a 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -39,25 +39,21 @@ export const registerPearListener = async () => { // Wait for the view to be ready using a helper function await ensureViewIsReady(sidebarProvider) - - if (msg.creatorModeConfig?.creatorMode) { - // Switch to creator mode - await sidebarProvider.handleModeSwitch("creator") - await sidebarProvider.postStateToWebview() - } - // Navigate to chat view - await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) - // Wait a brief moment for UI to update await new Promise((resolve) => setTimeout(resolve, 300)) - let creatorModeConfig = { + // * This does actually work but the UI update does not happen. This method calls this.postStateToWebview() so not sure what is going on - James + await sidebarProvider.handleModeSwitch("Creator") + + // Clicl the chat btn + await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) + + const creatorModeConfig = { creatorMode: true, newProjectType: msg.newProjectType, newProjectPath: msg.newProjectPath, } - console.log('Called init with taskk', msg.plan, undefined, undefined, undefined, creatorModeConfig); // Initialize with task await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig); From 12e5a4ec0a1aa53c9f85ca4fb29c6e4166ddd66d Mon Sep 17 00:00:00 2001 From: James Arnott Date: Sat, 10 May 2025 11:41:30 +0100 Subject: [PATCH 17/80] feat: handling the feedback button --- src/activate/registerPearListener.ts | 118 +++++++++--------- src/core/webview/webviewMessageHandler.ts | 9 ++ src/shared/WebviewMessage.ts | 1 + .../src/components/chat/PlanningBar.tsx | 3 +- 4 files changed, 73 insertions(+), 58 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index bd7c6e7f64a..622f3555f7d 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -14,69 +14,73 @@ export const getPearaiExtension = async () => { return pearAiExtension } +// TODO: TYPES +export const getpearAIExports = async () => { + const pearAiExtension = await getPearaiExtension() + + assert(!!pearAiExtension.exports, "⚠️⚠️ Error, no PearAI Exports could be found :( ⚠️⚠️"); + + return pearAiExtension.exports; +} + // TODO: SHOULD HAVE TYPE SYNCED WITH THE PEARAI SUBMODULE! type CreatorModeState = "OVERLAY_CLOSED" | "OVERLAY_OPEN" | "OVERLAY_CLOSED_CREATOR_ACTIVE" export const registerPearListener = async () => { // Getting the pear ai extension instance - const pearAiExtension = await getPearaiExtension() + const exports = await getpearAIExports() + + exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg: any) => { + console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`) + // Get the sidebar provider + let sidebarProvider = ClineProvider.getVisibleInstance() + + // TODO: LOOK INTO THIS - THIS IS A JANKY FIX AND IT FEELS LIKE THIS IS TEMPERAMENTAL + while (!sidebarProvider) { + await new Promise((resolve) => setTimeout(resolve, 500)) + sidebarProvider = ClineProvider.getVisibleInstance() + } + + // Focus the sidebar first + await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") + + // Wait for the view to be ready using a helper function + await ensureViewIsReady(sidebarProvider) + // Wait a brief moment for UI to update + await new Promise((resolve) => setTimeout(resolve, 300)) + + // * This does actually work but the UI update does not happen. This method calls this.postStateToWebview() so not sure what is going on - James + await sidebarProvider.handleModeSwitch("Creator") + + // Clicl the chat btn + await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) + + const creatorModeConfig = { + creatorMode: true, + newProjectType: msg.newProjectType, + newProjectPath: msg.newProjectPath, + } + + + // Initialize with task + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig); + }); + // If there's a creator event in the cache after the extensions were refreshed, we need to get it! + exports.pearAPI.creatorMode.triggerCachedCreatorEvent(true); + + exports.pearAPI.creatorMode.onDidChangeCreatorModeState(async (state: CreatorModeState) => { + // Get the sidebar provider + const sidebarProvider = ClineProvider.getVisibleInstance(); + + if (sidebarProvider) { + // Send a message to the webview that will trigger a window event + sidebarProvider.postMessageToWebview({ + type: "creatorModeUpdate", + text: state, + }); + } + }); - // Access the API directly from exports - if (pearAiExtension.exports) { - pearAiExtension.exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg: any) => { - console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`) - // Get the sidebar provider - let sidebarProvider = ClineProvider.getVisibleInstance() - - // TODO: LOOK INTO THIS - THIS IS A JANKY FIX AND IT FEELS LIKE THIS IS TEMPERAMENTAL - while (!sidebarProvider) { - await new Promise((resolve) => setTimeout(resolve, 500)) - sidebarProvider = ClineProvider.getVisibleInstance() - } - - // Focus the sidebar first - await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") - - // Wait for the view to be ready using a helper function - await ensureViewIsReady(sidebarProvider) - // Wait a brief moment for UI to update - await new Promise((resolve) => setTimeout(resolve, 300)) - - // * This does actually work but the UI update does not happen. This method calls this.postStateToWebview() so not sure what is going on - James - await sidebarProvider.handleModeSwitch("Creator") - - // Clicl the chat btn - await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) - - const creatorModeConfig = { - creatorMode: true, - newProjectType: msg.newProjectType, - newProjectPath: msg.newProjectPath, - } - - - // Initialize with task - await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig); - }); - // If there's a creator event in the cache after the extensions were refreshed, we need to get it! - pearAiExtension.exports.pearAPI.creatorMode.triggerCachedCreatorEvent(true); - - pearAiExtension.exports.pearAPI.creatorMode.onDidChangeCreatorModeState(async (state: CreatorModeState) => { - // Get the sidebar provider - const sidebarProvider = ClineProvider.getVisibleInstance(); - - if (sidebarProvider) { - // Send a message to the webview that will trigger a window event - sidebarProvider.postMessageToWebview({ - type: "creatorModeUpdate", - text: state, - }); - } - }); - - } else { - console.error("⚠️⚠️ PearAI API not available in exports ⚠️⚠️") - } } // TODO: decide if this is needed diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index ae14b5e1b53..b36d11cc909 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -38,6 +38,7 @@ import { buildApiHandler } from "../../api" import { GlobalState } from "../../schemas" import { MultiSearchReplaceDiffStrategy } from "../diff/strategies/multi-search-replace" import { getModels } from "../../api/providers/fetchers/cache" +import { getpearAIExports } from "../../activate/registerPearListener" export const webviewMessageHandler = async (provider: ClineProvider, message: WebviewMessage) => { // Utility functions provided for concise get/update of global state via contextProxy API. @@ -1269,6 +1270,14 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We ), ) break + case "openPearAICreatorFeedbackOverlay": + const pearAIExports = await getpearAIExports(); + const currentCline = provider.getCurrentCline(); + + + // Open the feedback form with the chat history + pearAIExports.pearAPI.creatorMode.openFeedbackForm(currentCline?.clineMessages || []); + break } } diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index d26a20ee3d9..60bd0a5daa9 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -128,6 +128,7 @@ export interface WebviewMessage { | "toggleApiConfigPin" | "setHistoryPreviewCollapsed" | "openPearAIAuth" + | "openPearAICreatorFeedbackOverlay" text?: string disabled?: boolean askResponse?: ClineAskResponse diff --git a/webview-ui/src/components/chat/PlanningBar.tsx b/webview-ui/src/components/chat/PlanningBar.tsx index b6b9a8006f5..6407b670a15 100644 --- a/webview-ui/src/components/chat/PlanningBar.tsx +++ b/webview-ui/src/components/chat/PlanningBar.tsx @@ -3,6 +3,7 @@ import { Button } from "./button" import { DocumentTextIcon as SolidDocumentTextIcon, StopCircleIcon, StopIcon } from "@heroicons/react/24/solid" import { FC } from "react" import { cn } from "@/lib/utils" +import { vscode } from "@src/utils/vscode" export type PlanningBarProps = { isGenerating?: boolean; @@ -52,7 +53,7 @@ export const PlanningBar: FC = ({
- - -
+
+
+
+ + +
- - -
- {/* */} -
-
- ); -}; + + +
+ {/* */} +
+
+ ) +} diff --git a/webview-ui/src/index.css b/webview-ui/src/index.css index 97f049e3447..50603c6ac58 100644 --- a/webview-ui/src/index.css +++ b/webview-ui/src/index.css @@ -467,4 +467,39 @@ input[cmdk-input]:focus { } } +/* Rainbow border glow effect */ +.rainbow-border-glow { + position: absolute; + inset: -2px; + background: linear-gradient( + 90deg, + rgba(255, 128, 128, 0.7) 0%, + rgba(255, 192, 128, 0.7) 14%, + rgba(255, 255, 128, 0.7) 28%, + rgba(128, 255, 128, 0.7) 42%, + rgba(128, 255, 255, 0.7) 56%, + rgba(128, 128, 255, 0.7) 70%, + rgba(192, 128, 255, 0.7) 84%, + rgba(255, 128, 192, 0.7) 100% + ); + background-size: 200% auto; + filter: blur(5px); + animation: rainbow-flow 3s linear infinite; + z-index: -1; /* Ensure it's behind the button */ + opacity: 0; /* Start invisible */ + transition: opacity 0.5s ease; /* Add transition for smooth opacity changes */ +} + +/* Class to show the element */ +.rainbow-border-glow-visible { + opacity: 0.7; +} + +@keyframes rainbow-flow { + to { + background-position: 200% center; + } +} + + /* _-_-_-_-_-_-_-_- PEARAI CREATOR STYLES _-_-_-_-_-_-_-_- */ From 44bec75cbae395186e5ddcbd08f79daa768cc445 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Mon, 12 May 2025 11:27:33 +0100 Subject: [PATCH 31/80] fix: creator mode new tasks are also in creator mode --- src/core/tools/newTaskTool.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/tools/newTaskTool.ts b/src/core/tools/newTaskTool.ts index dc45c73d3a0..f2e9e178e44 100644 --- a/src/core/tools/newTaskTool.ts +++ b/src/core/tools/newTaskTool.ts @@ -78,7 +78,8 @@ export async function newTaskTool( // Delay to allow mode change to take effect before next tool is executed. await delay(500) - const newCline = await provider.initClineWithTask(message, undefined, cline) + // Pass the creator mode config from the parent task to ensure creator mode is preserved + const newCline = await provider.initClineWithTask(message, undefined, cline, {}, cline.creatorModeConfig) cline.emit("taskSpawned", newCline.taskId) pushToolResult(`Successfully created new task in ${targetMode.name} mode with message: ${message}`) From 44ca22be461907d6420163a81b6d8e83ea19281c Mon Sep 17 00:00:00 2001 From: Himanshu Date: Mon, 12 May 2025 23:15:36 +0530 Subject: [PATCH 32/80] rename roo rules (#80) * rename .roo -> .pearai-agent * pearai-agent-ignore * pearai-agent-modes --- .vscodeignore | 3 + src/core/config/CustomModesManager.ts | 14 +- .../__tests__/CustomModesManager.test.ts | 26 +- src/core/ignore/RooIgnoreController.ts | 28 +- .../RooIgnoreController.security.test.ts | 2 +- .../__tests__/custom-system-prompt.test.ts | 5 +- .../__tests__/responses-rooignore.test.ts | 14 +- src/core/prompts/instructions/create-mode.ts | 7 +- src/core/prompts/responses.ts | 3 +- .../__tests__/custom-instructions.test.ts | 216 +++--- .../__tests__/custom-system-prompt.test.ts | 3 +- .../prompts/sections/custom-instructions.ts | 11 +- .../prompts/sections/custom-system-prompt.ts | 9 +- .../webview/__tests__/ClineProvider.test.ts | 5 +- src/core/webview/webviewMessageHandler.ts | 3 +- src/exports/types.ts | 684 +++++++----------- src/i18n/locales/ca/common.json | 2 +- src/i18n/locales/de/common.json | 2 +- src/i18n/locales/en/common.json | 2 +- src/i18n/locales/es/common.json | 2 +- src/i18n/locales/fr/common.json | 2 +- src/i18n/locales/hi/common.json | 2 +- src/i18n/locales/it/common.json | 2 +- src/i18n/locales/ja/common.json | 2 +- src/i18n/locales/ko/common.json | 2 +- src/i18n/locales/pl/common.json | 2 +- src/i18n/locales/pt-BR/common.json | 2 +- src/i18n/locales/ru/common.json | 2 +- src/i18n/locales/tr/common.json | 2 +- src/i18n/locales/vi/common.json | 2 +- src/i18n/locales/zh-CN/common.json | 2 +- src/i18n/locales/zh-TW/common.json | 2 +- src/services/mcp/McpHub.ts | 3 +- src/shared/ExtensionMessage.ts | 2 +- src/shared/constants.ts | 5 + src/shared/pearaiApi.ts | 4 +- src/utils/path.ts | 1 + .../src/components/prompts/PromptsView.tsx | 9 +- .../settings/ContextManagementSettings.tsx | 4 +- .../ContextManagementSettings.test.tsx | 2 +- .../src/context/ExtensionStateContext.tsx | 2 +- webview-ui/src/i18n/locales/ca/prompts.json | 10 +- webview-ui/src/i18n/locales/ca/settings.json | 6 +- webview-ui/src/i18n/locales/de/prompts.json | 10 +- webview-ui/src/i18n/locales/de/settings.json | 6 +- webview-ui/src/i18n/locales/en/prompts.json | 10 +- webview-ui/src/i18n/locales/en/settings.json | 6 +- webview-ui/src/i18n/locales/es/prompts.json | 10 +- webview-ui/src/i18n/locales/es/settings.json | 6 +- webview-ui/src/i18n/locales/fr/prompts.json | 10 +- webview-ui/src/i18n/locales/fr/settings.json | 6 +- webview-ui/src/i18n/locales/hi/prompts.json | 10 +- webview-ui/src/i18n/locales/hi/settings.json | 6 +- webview-ui/src/i18n/locales/it/prompts.json | 10 +- webview-ui/src/i18n/locales/it/settings.json | 6 +- webview-ui/src/i18n/locales/ja/prompts.json | 10 +- webview-ui/src/i18n/locales/ja/settings.json | 2 +- webview-ui/src/i18n/locales/ko/prompts.json | 10 +- webview-ui/src/i18n/locales/ko/settings.json | 4 +- webview-ui/src/i18n/locales/pl/prompts.json | 10 +- webview-ui/src/i18n/locales/pl/settings.json | 6 +- .../src/i18n/locales/pt-BR/prompts.json | 10 +- .../src/i18n/locales/pt-BR/settings.json | 6 +- webview-ui/src/i18n/locales/ru/prompts.json | 10 +- webview-ui/src/i18n/locales/ru/settings.json | 6 +- webview-ui/src/i18n/locales/tr/prompts.json | 10 +- webview-ui/src/i18n/locales/tr/settings.json | 6 +- webview-ui/src/i18n/locales/vi/prompts.json | 10 +- webview-ui/src/i18n/locales/vi/settings.json | 6 +- .../src/i18n/locales/zh-CN/prompts.json | 10 +- .../src/i18n/locales/zh-CN/settings.json | 6 +- .../src/i18n/locales/zh-TW/prompts.json | 10 +- .../src/i18n/locales/zh-TW/settings.json | 6 +- 73 files changed, 621 insertions(+), 726 deletions(-) create mode 100644 src/shared/constants.ts diff --git a/.vscodeignore b/.vscodeignore index 53fd3798c01..1bc718e577e 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -29,6 +29,9 @@ jest.* .roomodes .rooignore .roo/** +.pearai-agent/** +.pearai-agent-ignore +.pearai-agent-modes benchmark/** cline_docs/** e2e/** diff --git a/src/core/config/CustomModesManager.ts b/src/core/config/CustomModesManager.ts index efa3366aee2..5dd08e0078b 100644 --- a/src/core/config/CustomModesManager.ts +++ b/src/core/config/CustomModesManager.ts @@ -7,9 +7,9 @@ import { fileExistsAtPath } from "../../utils/fs" import { arePathsEqual, getWorkspacePath } from "../../utils/path" import { logger } from "../../utils/logging" import { GlobalFileNames } from "../../shared/globalFileNames" +import { AGENT_MODES_FILE_NAME } from "../../shared/constants" -const ROOMODES_FILENAME = ".roomodes" - +const ROOMODES_FILENAME = AGENT_MODES_FILE_NAME export class CustomModesManager { private disposables: vscode.Disposable[] = [] private isWriting = false @@ -152,11 +152,11 @@ export class CustomModesManager { return } - // Get modes from .roomodes if it exists (takes precedence) + // Get modes from .pearai-agent-modes if it exists (takes precedence) const roomodesPath = await this.getWorkspaceRoomodes() const roomodesModes = roomodesPath ? await this.loadModesFromFile(roomodesPath) : [] - // Merge modes from both sources (.roomodes takes precedence) + // Merge modes from both sources (.pearai-agent-modes takes precedence) const mergedModes = await this.mergeCustomModes(roomodesModes, result.data.customModes) await this.context.globalState.update("customModes", mergedModes) await this.onUpdate() @@ -164,7 +164,7 @@ export class CustomModesManager { }), ) - // Watch .roomodes file if it exists + // Watch .pearai-agent-modes file if it exists const roomodesPath = await this.getWorkspaceRoomodes() if (roomodesPath) { this.disposables.push( @@ -172,7 +172,7 @@ export class CustomModesManager { if (arePathsEqual(document.uri.fsPath, roomodesPath)) { const settingsModes = await this.loadModesFromFile(settingsPath) const roomodesModes = await this.loadModesFromFile(roomodesPath) - // .roomodes takes precedence + // .pearai-agent-modes takes precedence const mergedModes = await this.mergeCustomModes(roomodesModes, settingsModes) await this.context.globalState.update("customModes", mergedModes) await this.onUpdate() @@ -187,7 +187,7 @@ export class CustomModesManager { const settingsPath = await this.getCustomModesFilePath() const settingsModes = await this.loadModesFromFile(settingsPath) - // Get modes from .roomodes if it exists + // Get modes from .pearai-agent-modes if it exists const roomodesPath = await this.getWorkspaceRoomodes() const roomodesModes = roomodesPath ? await this.loadModesFromFile(roomodesPath) : [] diff --git a/src/core/config/__tests__/CustomModesManager.test.ts b/src/core/config/__tests__/CustomModesManager.test.ts index a5de1414835..309b4705ed2 100644 --- a/src/core/config/__tests__/CustomModesManager.test.ts +++ b/src/core/config/__tests__/CustomModesManager.test.ts @@ -23,7 +23,7 @@ describe("CustomModesManager", () => { // Use path.sep to ensure correct path separators for the current platform const mockStoragePath = `${path.sep}mock${path.sep}settings` const mockSettingsPath = path.join(mockStoragePath, "settings", GlobalFileNames.customModes) - const mockRoomodes = `${path.sep}mock${path.sep}workspace${path.sep}.roomodes` + const mockRoomodes = `${path.sep}mock${path.sep}workspace${path.sep}.pearai-agent-ignore` beforeEach(() => { mockOnUpdate = jest.fn() @@ -60,7 +60,7 @@ describe("CustomModesManager", () => { }) describe("getCustomModes", () => { - it("should merge modes with .roomodes taking precedence", async () => { + it("should merge modes with .pearai-agent-ignore taking precedence", async () => { const settingsModes = [ { slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] }, { slug: "mode2", name: "Mode 2", roleDefinition: "Role 2", groups: ["read"] }, @@ -87,13 +87,13 @@ describe("CustomModesManager", () => { expect(modes).toHaveLength(3) expect(modes.map((m) => m.slug)).toEqual(["mode2", "mode3", "mode1"]) - // mode2 should come from .roomodes since it takes precedence + // mode2 should come from .pearai-agent-ignore since it takes precedence const mode2 = modes.find((m) => m.slug === "mode2") expect(mode2?.name).toBe("Mode 2 Override") expect(mode2?.roleDefinition).toBe("Role 2 Override") }) - it("should handle missing .roomodes file", async () => { + it("should handle missing .pearai-agent-ignore file", async () => { const settingsModes = [{ slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] }] ;(fileExistsAtPath as jest.Mock).mockImplementation(async (path: string) => { @@ -112,7 +112,7 @@ describe("CustomModesManager", () => { expect(modes[0].slug).toBe("mode1") }) - it("should handle invalid JSON in .roomodes", async () => { + it("should handle invalid JSON in .pearai-agent-ignore", async () => { const settingsModes = [{ slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] }] ;(fs.readFile as jest.Mock).mockImplementation(async (path: string) => { @@ -127,14 +127,14 @@ describe("CustomModesManager", () => { const modes = await manager.getCustomModes() - // Should fall back to settings modes when .roomodes is invalid + // Should fall back to settings modes when .pearai-agent-ignore is invalid expect(modes).toHaveLength(1) expect(modes[0].slug).toBe("mode1") }) }) describe("updateCustomMode", () => { - it("should update mode in settings file while preserving .roomodes precedence", async () => { + it("should update mode in settings file while preserving .pearai-agent-ignore precedence", async () => { const newMode: ModeConfig = { slug: "mode1", name: "Updated Mode 1", @@ -198,13 +198,13 @@ describe("CustomModesManager", () => { }), ) - // Should update global state with merged modes where .roomodes takes precedence + // Should update global state with merged modes where .pearai-agent-ignore takes precedence expect(mockContext.globalState.update).toHaveBeenCalledWith( "customModes", expect.arrayContaining([ expect.objectContaining({ slug: "mode1", - name: "Roomodes Mode 1", // .roomodes version should take precedence + name: "Roomodes Mode 1", // .pearai-agent-ignore version should take precedence source: "project", }), ]), @@ -214,7 +214,7 @@ describe("CustomModesManager", () => { expect(mockOnUpdate).toHaveBeenCalled() }) - it("creates .roomodes file when adding project-specific mode", async () => { + it("creates .pearai-agent-ignore file when adding project-specific mode", async () => { const projectMode: ModeConfig = { slug: "project-mode", name: "Project Mode", @@ -223,7 +223,7 @@ describe("CustomModesManager", () => { source: "project", } - // Mock .roomodes to not exist initially + // Mock .pearai-agent-ignore to not exist initially let roomodesContent: any = null ;(fileExistsAtPath as jest.Mock).mockImplementation(async (path: string) => { return path === mockSettingsPath @@ -249,7 +249,7 @@ describe("CustomModesManager", () => { await manager.updateCustomMode("project-mode", projectMode) - // Verify .roomodes was created with the project mode + // Verify .pearai-agent-ignore was created with the project mode expect(fs.writeFile).toHaveBeenCalledWith( expect.any(String), // Don't check exact path as it may have different separators on different platforms expect.stringContaining("project-mode"), @@ -260,7 +260,7 @@ describe("CustomModesManager", () => { const writeCall = (fs.writeFile as jest.Mock).mock.calls[0] expect(path.normalize(writeCall[0])).toBe(path.normalize(mockRoomodes)) - // Verify the content written to .roomodes + // Verify the content written to .pearai-agent-ignore expect(roomodesContent).toEqual({ customModes: [ expect.objectContaining({ diff --git a/src/core/ignore/RooIgnoreController.ts b/src/core/ignore/RooIgnoreController.ts index fda6c371757..cd794aa9850 100644 --- a/src/core/ignore/RooIgnoreController.ts +++ b/src/core/ignore/RooIgnoreController.ts @@ -3,13 +3,13 @@ import { fileExistsAtPath } from "../../utils/fs" import fs from "fs/promises" import ignore, { Ignore } from "ignore" import * as vscode from "vscode" +import { AGENT_IGNORE_FILE_NAME } from "../../shared/constants" export const LOCK_TEXT_SYMBOL = "\u{1F512}" - /** * Controls LLM access to files by enforcing ignore patterns. * Designed to be instantiated once in Cline.ts and passed to file manipulation services. - * Uses the 'ignore' library to support standard .gitignore syntax in .rooignore files. + * Uses the 'ignore' library to support standard .gitignore syntax in .pearai-agent-ignore files. */ export class RooIgnoreController { private cwd: string @@ -21,7 +21,7 @@ export class RooIgnoreController { this.cwd = cwd this.ignoreInstance = ignore() this.rooIgnoreContent = undefined - // Set up file watcher for .rooignore + // Set up file watcher for .pearai-agent-ignore this.setupFileWatcher() } @@ -34,10 +34,10 @@ export class RooIgnoreController { } /** - * Set up the file watcher for .rooignore changes + * Set up the file watcher for .pearai-agent-ignore changes */ private setupFileWatcher(): void { - const rooignorePattern = new vscode.RelativePattern(this.cwd, ".rooignore") + const rooignorePattern = new vscode.RelativePattern(this.cwd, AGENT_IGNORE_FILE_NAME) const fileWatcher = vscode.workspace.createFileSystemWatcher(rooignorePattern) // Watch for changes and updates @@ -58,24 +58,24 @@ export class RooIgnoreController { } /** - * Load custom patterns from .rooignore if it exists + * Load custom patterns from .pearai-agent-ignore if it exists */ private async loadRooIgnore(): Promise { try { // Reset ignore instance to prevent duplicate patterns this.ignoreInstance = ignore() - const ignorePath = path.join(this.cwd, ".rooignore") + const ignorePath = path.join(this.cwd, AGENT_IGNORE_FILE_NAME) if (await fileExistsAtPath(ignorePath)) { const content = await fs.readFile(ignorePath, "utf8") this.rooIgnoreContent = content this.ignoreInstance.add(content) - this.ignoreInstance.add(".rooignore") + this.ignoreInstance.add(AGENT_IGNORE_FILE_NAME) } else { this.rooIgnoreContent = undefined } } catch (error) { // Should never happen: reading file failed even though it exists - console.error("Unexpected error loading .rooignore:", error) + console.error(`Unexpected error loading ${AGENT_IGNORE_FILE_NAME}:`, error) } } @@ -85,7 +85,7 @@ export class RooIgnoreController { * @returns true if file is accessible, false if ignored */ validateAccess(filePath: string): boolean { - // Always allow access if .rooignore does not exist + // Always allow access if .pearai-agent-ignore does not exist if (!this.rooIgnoreContent) { return true } @@ -109,7 +109,7 @@ export class RooIgnoreController { * @returns path of file that is being accessed if it is being accessed, undefined if command is allowed */ validateCommand(command: string): string | undefined { - // Always allow if no .rooignore exists + // Always allow if no .pearai-agent-ignore exists if (!this.rooIgnoreContent) { return undefined } @@ -188,14 +188,14 @@ export class RooIgnoreController { } /** - * Get formatted instructions about the .rooignore file for the LLM - * @returns Formatted instructions or undefined if .rooignore doesn't exist + * Get formatted instructions about the .pearai-agent-ignore file for the LLM + * @returns Formatted instructions or undefined if .pearai-agent-ignore doesn't exist */ getInstructions(): string | undefined { if (!this.rooIgnoreContent) { return undefined } - return `# .rooignore\n\n(The following is provided by a root-level .rooignore file where the user has specified files and directories that should not be accessed. When using list_files, you'll notice a ${LOCK_TEXT_SYMBOL} next to files that are blocked. Attempting to access the file's contents e.g. through read_file will result in an error.)\n\n${this.rooIgnoreContent}\n.rooignore` + return `# ${AGENT_IGNORE_FILE_NAME}\n\n(The following is provided by a root-level ${AGENT_IGNORE_FILE_NAME} file where the user has specified files and directories that should not be accessed. When using list_files, you'll notice a ${LOCK_TEXT_SYMBOL} next to files that are blocked. Attempting to access the file's contents e.g. through read_file will result in an error.)\n\n${this.rooIgnoreContent}\n${AGENT_IGNORE_FILE_NAME}` } } diff --git a/src/core/ignore/__tests__/RooIgnoreController.security.test.ts b/src/core/ignore/__tests__/RooIgnoreController.security.test.ts index c71c1fcdb6f..91aca076e40 100644 --- a/src/core/ignore/__tests__/RooIgnoreController.security.test.ts +++ b/src/core/ignore/__tests__/RooIgnoreController.security.test.ts @@ -41,7 +41,7 @@ describe("RooIgnoreController Security Tests", () => { mockFileExists = fileExistsAtPath as jest.MockedFunction mockReadFile = fs.readFile as jest.MockedFunction - // By default, setup .rooignore to exist with some patterns + // By default, setup .pearai-agent-ignore to exist with some patterns mockFileExists.mockResolvedValue(true) mockReadFile.mockResolvedValue("node_modules\n.git\nsecrets/**\n*.log\nprivate/") diff --git a/src/core/prompts/__tests__/custom-system-prompt.test.ts b/src/core/prompts/__tests__/custom-system-prompt.test.ts index 977ab051a00..acaeca61a4c 100644 --- a/src/core/prompts/__tests__/custom-system-prompt.test.ts +++ b/src/core/prompts/__tests__/custom-system-prompt.test.ts @@ -3,6 +3,7 @@ import { defaultModeSlug, modes } from "../../../shared/modes" import * as vscode from "vscode" import * as fs from "fs/promises" import { toPosix } from "./utils" +import { AGENT_RULES_DIR } from "../../../shared/constants" // Mock the fs/promises module jest.mock("fs/promises", () => ({ @@ -90,7 +91,7 @@ describe("File-Based Custom System Prompt", () => { const fileCustomSystemPrompt = "Custom system prompt from file" // When called with utf-8 encoding, return a string mockedFs.readFile.mockImplementation((filePath, options) => { - if (toPosix(filePath).includes(`.roo/system-prompt-${defaultModeSlug}`) && options === "utf-8") { + if (toPosix(filePath).includes(`${AGENT_RULES_DIR}/system-prompt-${defaultModeSlug}`) && options === "utf-8") { return Promise.resolve(fileCustomSystemPrompt) } return Promise.reject({ code: "ENOENT" }) @@ -125,7 +126,7 @@ describe("File-Based Custom System Prompt", () => { // Mock the readFile to return content from a file const fileCustomSystemPrompt = "Custom system prompt from file" mockedFs.readFile.mockImplementation((filePath, options) => { - if (toPosix(filePath).includes(`.roo/system-prompt-${defaultModeSlug}`) && options === "utf-8") { + if (toPosix(filePath).includes(`${AGENT_RULES_DIR}/system-prompt-${defaultModeSlug}`) && options === "utf-8") { return Promise.resolve(fileCustomSystemPrompt) } return Promise.reject({ code: "ENOENT" }) diff --git a/src/core/prompts/__tests__/responses-rooignore.test.ts b/src/core/prompts/__tests__/responses-rooignore.test.ts index 46f1bec438a..518f07e4e20 100644 --- a/src/core/prompts/__tests__/responses-rooignore.test.ts +++ b/src/core/prompts/__tests__/responses-rooignore.test.ts @@ -50,9 +50,9 @@ describe("RooIgnore Response Formatting", () => { const errorMessage = formatResponse.rooIgnoreError("secrets/api-keys.json") // Verify error message format - expect(errorMessage).toContain("Access to secrets/api-keys.json is blocked by the .rooignore file settings") + expect(errorMessage).toContain("Access to secrets/api-keys.json is blocked by the .pearai-agent-ignore file settings") expect(errorMessage).toContain("continue in the task without using this file") - expect(errorMessage).toContain("ask the user to update the .rooignore file") + expect(errorMessage).toContain("ask the user to update the .pearai-agent-ignore file") }) /** @@ -207,7 +207,7 @@ describe("RooIgnore Response Formatting", () => { /** * Tests the instructions format */ - it("should format .rooignore instructions for the LLM", async () => { + it("should format .pearai-agent-ignore instructions for the LLM", async () => { // Create controller const controller = new RooIgnoreController(TEST_CWD) await controller.initialize() @@ -216,7 +216,7 @@ describe("RooIgnore Response Formatting", () => { const instructions = controller.getInstructions() // Verify format and content - expect(instructions).toContain("# .rooignore") + expect(instructions).toContain("# .pearai-agent-ignore") expect(instructions).toContain(LOCK_TEXT_SYMBOL) expect(instructions).toContain("node_modules") expect(instructions).toContain(".git") @@ -231,11 +231,11 @@ describe("RooIgnore Response Formatting", () => { /** * Tests null/undefined case */ - it("should return undefined when no .rooignore exists", async () => { - // Set up no .rooignore + it("should return undefined when no .pearai-agent-ignore exists", async () => { + // Set up no .pearai-agent-ignore mockFileExists.mockResolvedValue(false) - // Create controller without .rooignore + // Create controller without .pearai-agent-ignore const controller = new RooIgnoreController(TEST_CWD) await controller.initialize() diff --git a/src/core/prompts/instructions/create-mode.ts b/src/core/prompts/instructions/create-mode.ts index 598e2fccbf4..ad02f6b6ab5 100644 --- a/src/core/prompts/instructions/create-mode.ts +++ b/src/core/prompts/instructions/create-mode.ts @@ -2,6 +2,7 @@ import * as path from "path" import * as vscode from "vscode" import { GlobalFileNames } from "../../../shared/globalFileNames" +import { AGENT_MODES_FILE_NAME } from "../../../shared/constants" export async function createModeInstructions(context: vscode.ExtensionContext | undefined): Promise { if (!context) throw new Error("Missing VSCode Extension Context") @@ -12,12 +13,12 @@ export async function createModeInstructions(context: vscode.ExtensionContext | return ` Custom modes can be configured in two ways: 1. Globally via '${customModesPath}' (created automatically on startup) - 2. Per-workspace via '.roomodes' in the workspace root directory + 2. Per-workspace via '${AGENT_MODES_FILE_NAME}' in the workspace root directory -When modes with the same slug exist in both files, the workspace-specific .roomodes version takes precedence. This allows projects to override global modes or define project-specific modes. +When modes with the same slug exist in both files, the workspace-specific ${AGENT_MODES_FILE_NAME} version takes precedence. This allows projects to override global modes or define project-specific modes. -If asked to create a project mode, create it in .roomodes in the workspace root. If asked to create a global mode, use the global custom modes file. +If asked to create a project mode, create it in ${AGENT_MODES_FILE_NAME} in the workspace root. If asked to create a global mode, use the global custom modes file. - The following fields are required and must not be empty: * slug: A valid slug (lowercase letters, numbers, and hyphens). Must be unique, and shorter is better. diff --git a/src/core/prompts/responses.ts b/src/core/prompts/responses.ts index 314387171af..9c82a848804 100644 --- a/src/core/prompts/responses.ts +++ b/src/core/prompts/responses.ts @@ -2,6 +2,7 @@ import { Anthropic } from "@anthropic-ai/sdk" import * as path from "path" import * as diff from "diff" import { RooIgnoreController, LOCK_TEXT_SYMBOL } from "../ignore/RooIgnoreController" +import { AGENT_IGNORE_FILE_NAME } from "../../shared/constants" export const formatResponse = { toolDenied: () => `The user denied this operation.`, @@ -15,7 +16,7 @@ export const formatResponse = { toolError: (error?: string) => `The tool execution failed with the following error:\n\n${error}\n`, rooIgnoreError: (path: string) => - `Access to ${path} is blocked by the .rooignore file settings. You must try to continue in the task without using this file, or ask the user to update the .rooignore file.`, + `Access to ${path} is blocked by the ${AGENT_IGNORE_FILE_NAME} file settings. You must try to continue in the task without using this file, or ask the user to update the ${AGENT_IGNORE_FILE_NAME} file.`, noToolsUsed: () => `[ERROR] You did not use a tool in your previous response! Please retry with a tool use. diff --git a/src/core/prompts/sections/__tests__/custom-instructions.test.ts b/src/core/prompts/sections/__tests__/custom-instructions.test.ts index e243526d210..5a4ef4cbfcd 100644 --- a/src/core/prompts/sections/__tests__/custom-instructions.test.ts +++ b/src/core/prompts/sections/__tests__/custom-instructions.test.ts @@ -42,7 +42,7 @@ describe("loadRuleFiles", () => { }) it("should read and trim file content", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockResolvedValue(" content with spaces ") const result = await loadRuleFiles("/fake/path") @@ -51,7 +51,7 @@ describe("loadRuleFiles", () => { }) it("should handle ENOENT error", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "ENOENT" }) const result = await loadRuleFiles("/fake/path") @@ -59,7 +59,7 @@ describe("loadRuleFiles", () => { }) it("should handle EISDIR error", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "EISDIR" }) const result = await loadRuleFiles("/fake/path") @@ -67,7 +67,7 @@ describe("loadRuleFiles", () => { }) it("should throw on unexpected errors", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) const error = new Error("Permission denied") as NodeJS.ErrnoException error.code = "EPERM" @@ -79,7 +79,7 @@ describe("loadRuleFiles", () => { }) it("should not combine content from multiple rule files when they exist", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockImplementation((filePath: PathLike) => { if (filePath.toString().endsWith(".roorules")) { @@ -96,7 +96,7 @@ describe("loadRuleFiles", () => { }) it("should handle when no rule files exist", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "ENOENT" }) @@ -105,7 +105,7 @@ describe("loadRuleFiles", () => { }) it("should skip directories with same name as rule files", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockImplementation((filePath: PathLike) => { if (filePath.toString().endsWith(".roorules")) { @@ -121,16 +121,16 @@ describe("loadRuleFiles", () => { expect(result).toBe("") }) - it("should use .roo/rules/ directory when it exists and has files", async () => { - // Simulate .roo/rules directory exists + it("should use .pearai-agent/rules/ directory when it exists and has files", async () => { + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) // Simulate listing files readdirMock.mockResolvedValueOnce([ - { name: "file1.txt", isFile: () => true, isSymbolicLink: () => false, parentPath: "/fake/path/.roo/rules" }, - { name: "file2.txt", isFile: () => true, isSymbolicLink: () => false, parentPath: "/fake/path/.roo/rules" }, + { name: "file1.txt", isFile: () => true, isSymbolicLink: () => false, parentPath: "/fake/path/.pearai-agent/rules" }, + { name: "file2.txt", isFile: () => true, isSymbolicLink: () => false, parentPath: "/fake/path/.pearai-agent/rules" }, ] as any) statMock.mockImplementation( @@ -141,31 +141,31 @@ describe("loadRuleFiles", () => { ) readFileMock.mockImplementation((filePath: PathLike) => { - if (filePath.toString() === "/fake/path/.roo/rules/file1.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/file1.txt") { return Promise.resolve("content of file1") } - if (filePath.toString() === "/fake/path/.roo/rules/file2.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/file2.txt") { return Promise.resolve("content of file2") } return Promise.reject({ code: "ENOENT" }) }) const result = await loadRuleFiles("/fake/path") - expect(result).toContain("# Rules from /fake/path/.roo/rules/file1.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/file1.txt:") expect(result).toContain("content of file1") - expect(result).toContain("# Rules from /fake/path/.roo/rules/file2.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/file2.txt:") expect(result).toContain("content of file2") // We expect both checks because our new implementation checks the files again for validation - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules/file1.txt") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules/file2.txt") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/file1.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/file2.txt", "utf-8") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/file1.txt") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/file2.txt") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/file1.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/file2.txt", "utf-8") }) - it("should fall back to .roorules when .roo/rules/ is empty", async () => { - // Simulate .roo/rules directory exists + it("should fall back to .roorules when .pearai-agent/rules/ is empty", async () => { + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) @@ -186,7 +186,7 @@ describe("loadRuleFiles", () => { }) it("should handle errors when reading directory", async () => { - // Simulate .roo/rules directory exists + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) @@ -206,8 +206,8 @@ describe("loadRuleFiles", () => { expect(result).toBe("\n# Rules from .roorules:\nroo rules content\n") }) - it("should read files from nested subdirectories in .roo/rules/", async () => { - // Simulate .roo/rules directory exists + it("should read files from nested subdirectories in .pearai-agent/rules/", async () => { + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) @@ -219,28 +219,28 @@ describe("loadRuleFiles", () => { isFile: () => false, isSymbolicLink: () => false, isDirectory: () => true, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, { name: "root.txt", isFile: () => true, isSymbolicLink: () => false, isDirectory: () => false, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, { name: "nested1.txt", isFile: () => true, isSymbolicLink: () => false, isDirectory: () => false, - parentPath: "/fake/path/.roo/rules/subdir", + parentPath: "/fake/path/.pearai-agent/rules/subdir", }, { name: "nested2.txt", isFile: () => true, isSymbolicLink: () => false, isDirectory: () => false, - parentPath: "/fake/path/.roo/rules/subdir/subdir2", + parentPath: "/fake/path/.pearai-agent/rules/subdir/subdir2", }, ] as any) @@ -259,13 +259,13 @@ describe("loadRuleFiles", () => { readFileMock.mockImplementation((filePath: PathLike) => { const path = filePath.toString() - if (path === "/fake/path/.roo/rules/root.txt") { + if (path === "/fake/path/.pearai-agent/rules/root.txt") { return Promise.resolve("root file content") } - if (path === "/fake/path/.roo/rules/subdir/nested1.txt") { + if (path === "/fake/path/.pearai-agent/rules/subdir/nested1.txt") { return Promise.resolve("nested file 1 content") } - if (path === "/fake/path/.roo/rules/subdir/subdir2/nested2.txt") { + if (path === "/fake/path/.pearai-agent/rules/subdir/subdir2/nested2.txt") { return Promise.resolve("nested file 2 content") } return Promise.reject({ code: "ENOENT" }) @@ -274,24 +274,24 @@ describe("loadRuleFiles", () => { const result = await loadRuleFiles("/fake/path") // Check root file content - expect(result).toContain("# Rules from /fake/path/.roo/rules/root.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/root.txt:") expect(result).toContain("root file content") // Check nested files content - expect(result).toContain("# Rules from /fake/path/.roo/rules/subdir/nested1.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/subdir/nested1.txt:") expect(result).toContain("nested file 1 content") - expect(result).toContain("# Rules from /fake/path/.roo/rules/subdir/subdir2/nested2.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/subdir/subdir2/nested2.txt:") expect(result).toContain("nested file 2 content") // Verify correct paths were checked - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules/root.txt") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules/subdir/nested1.txt") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules/subdir/subdir2/nested2.txt") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/root.txt") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/subdir/nested1.txt") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/subdir/subdir2/nested2.txt") // Verify files were read with correct paths - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/root.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/subdir/nested1.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/subdir/subdir2/nested2.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/root.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/subdir/nested1.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/subdir/subdir2/nested2.txt", "utf-8") }) }) @@ -301,7 +301,7 @@ describe("addCustomInstructions", () => { }) it("should combine all instruction types when provided", async () => { - // Simulate no .roo/rules-test-mode directory + // Simulate no .pearai-agent/rules-test-mode directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockResolvedValue("mode specific rules") @@ -323,7 +323,7 @@ describe("addCustomInstructions", () => { }) it("should return empty string when no instructions provided", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "ENOENT" }) @@ -333,7 +333,7 @@ describe("addCustomInstructions", () => { }) it("should handle missing mode-specific rules file", async () => { - // Simulate no .roo/rules-test-mode directory + // Simulate no .pearai-agent/rules-test-mode directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "ENOENT" }) @@ -351,7 +351,7 @@ describe("addCustomInstructions", () => { }) it("should handle unknown language codes properly", async () => { - // Simulate no .roo/rules-test-mode directory + // Simulate no .pearai-agent/rules-test-mode directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "ENOENT" }) @@ -370,7 +370,7 @@ describe("addCustomInstructions", () => { }) it("should throw on unexpected errors", async () => { - // Simulate no .roo/rules-test-mode directory + // Simulate no .pearai-agent/rules-test-mode directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) const error = new Error("Permission denied") as NodeJS.ErrnoException @@ -383,7 +383,7 @@ describe("addCustomInstructions", () => { }) it("should skip mode-specific rule files that are directories", async () => { - // Simulate no .roo/rules-test-mode directory + // Simulate no .pearai-agent/rules-test-mode directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockImplementation((filePath: PathLike) => { @@ -405,8 +405,8 @@ describe("addCustomInstructions", () => { expect(result).not.toContain("Rules from .clinerules-test-mode") }) - it("should use .roo/rules-test-mode/ directory when it exists and has files", async () => { - // Simulate .roo/rules-test-mode directory exists + it("should use .pearai-agent/rules-test-mode/ directory when it exists and has files", async () => { + // Simulate .pearai-agent/rules-test-mode directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) @@ -417,13 +417,13 @@ describe("addCustomInstructions", () => { name: "rule1.txt", isFile: () => true, isSymbolicLink: () => false, - parentPath: "/fake/path/.roo/rules-test-mode", + parentPath: "/fake/path/.pearai-agent/rules-test-mode", }, { name: "rule2.txt", isFile: () => true, isSymbolicLink: () => false, - parentPath: "/fake/path/.roo/rules-test-mode", + parentPath: "/fake/path/.pearai-agent/rules-test-mode", }, ] as any) @@ -435,10 +435,10 @@ describe("addCustomInstructions", () => { ) readFileMock.mockImplementation((filePath: PathLike) => { - if (filePath.toString() === "/fake/path/.roo/rules-test-mode/rule1.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules-test-mode/rule1.txt") { return Promise.resolve("mode specific rule 1") } - if (filePath.toString() === "/fake/path/.roo/rules-test-mode/rule2.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules-test-mode/rule2.txt") { return Promise.resolve("mode specific rule 2") } return Promise.reject({ code: "ENOENT" }) @@ -452,21 +452,21 @@ describe("addCustomInstructions", () => { { language: "es" }, ) - expect(result).toContain("# Rules from /fake/path/.roo/rules-test-mode") - expect(result).toContain("# Rules from /fake/path/.roo/rules-test-mode/rule1.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules-test-mode") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules-test-mode/rule1.txt:") expect(result).toContain("mode specific rule 1") - expect(result).toContain("# Rules from /fake/path/.roo/rules-test-mode/rule2.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules-test-mode/rule2.txt:") expect(result).toContain("mode specific rule 2") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules-test-mode") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules-test-mode/rule1.txt") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules-test-mode/rule2.txt") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules-test-mode/rule1.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules-test-mode/rule2.txt", "utf-8") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules-test-mode") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules-test-mode/rule1.txt") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules-test-mode/rule2.txt") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules-test-mode/rule1.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules-test-mode/rule2.txt", "utf-8") }) - it("should fall back to .roorules-test-mode when .roo/rules-test-mode/ does not exist", async () => { - // Simulate .roo/rules-test-mode directory does not exist + it("should fall back to .roorules-test-mode when .pearai-agent/rules-test-mode/ does not exist", async () => { + // Simulate .pearai-agent/rules-test-mode directory does not exist statMock.mockRejectedValueOnce({ code: "ENOENT" }) // Simulate .roorules-test-mode exists @@ -487,8 +487,8 @@ describe("addCustomInstructions", () => { expect(result).toContain("Rules from .roorules-test-mode:\nmode specific rules from file") }) - it("should fall back to .clinerules-test-mode when .roo/rules-test-mode/ and .roorules-test-mode do not exist", async () => { - // Simulate .roo/rules-test-mode directory does not exist + it("should fall back to .clinerules-test-mode when .pearai-agent/rules-test-mode/ and .roorules-test-mode do not exist", async () => { + // Simulate .pearai-agent/rules-test-mode directory does not exist statMock.mockRejectedValueOnce({ code: "ENOENT" }) // Simulate file reading @@ -512,12 +512,12 @@ describe("addCustomInstructions", () => { expect(result).toContain("Rules from .clinerules-test-mode:\nmode specific rules from cline file") }) - it("should correctly format content from directories when using .roo/rules-test-mode/", async () => { + it("should correctly format content from directories when using .pearai-agent/rules-test-mode/", async () => { // Need to reset mockImplementation first to avoid interference from previous tests statMock.mockReset() readFileMock.mockReset() - // Simulate .roo/rules-test-mode directory exists + // Simulate .pearai-agent/rules-test-mode directory exists statMock.mockImplementationOnce(() => Promise.resolve({ isDirectory: jest.fn().mockReturnValue(true), @@ -526,7 +526,7 @@ describe("addCustomInstructions", () => { // Simulate directory has files readdirMock.mockResolvedValueOnce([ - { name: "rule1.txt", isFile: () => true, parentPath: "/fake/path/.roo/rules-test-mode" }, + { name: "rule1.txt", isFile: () => true, parentPath: "/fake/path/.pearai-agent/rules-test-mode" }, ] as any) readFileMock.mockReset() @@ -534,7 +534,7 @@ describe("addCustomInstructions", () => { let statCallCount = 0 statMock.mockImplementation((filePath) => { statCallCount++ - if (filePath === "/fake/path/.roo/rules-test-mode/rule1.txt") { + if (filePath === "/fake/path/.pearai-agent/rules-test-mode/rule1.txt") { return Promise.resolve({ isFile: jest.fn().mockReturnValue(true), isDirectory: jest.fn().mockReturnValue(false), @@ -547,7 +547,7 @@ describe("addCustomInstructions", () => { }) readFileMock.mockImplementation((filePath: PathLike) => { - if (filePath.toString() === "/fake/path/.roo/rules-test-mode/rule1.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules-test-mode/rule1.txt") { return Promise.resolve("mode specific rule content") } return Promise.reject({ code: "ENOENT" }) @@ -560,8 +560,8 @@ describe("addCustomInstructions", () => { "test-mode", ) - expect(result).toContain("# Rules from /fake/path/.roo/rules-test-mode") - expect(result).toContain("# Rules from /fake/path/.roo/rules-test-mode/rule1.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules-test-mode") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules-test-mode/rule1.txt:") expect(result).toContain("mode specific rule content") expect(statCallCount).toBeGreaterThan(0) @@ -589,7 +589,7 @@ describe("Directory existence checks", () => { await loadRuleFiles("/fake/path") // Verify stat was called to check directory existence - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules") }) it("should handle when directory does not exist", async () => { @@ -609,7 +609,7 @@ describe("Directory existence checks", () => { // Indirectly test readTextFilesFromDirectory and formatDirectoryContent through loadRuleFiles describe("Rules directory reading", () => { it("should follow symbolic links in the rules directory", async () => { - // Simulate .roo/rules directory exists + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) @@ -621,29 +621,29 @@ describe("Rules directory reading", () => { name: "regular.txt", isFile: () => true, isSymbolicLink: () => false, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, { name: "link.txt", isFile: () => false, isSymbolicLink: () => true, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, { name: "link_dir", isFile: () => false, isSymbolicLink: () => true, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, { name: "nested_link.txt", isFile: () => false, isSymbolicLink: () => true, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, ] as any) .mockResolvedValueOnce([ - { name: "subdir_link.txt", isFile: () => true, parentPath: "/fake/path/.roo/rules/symlink-target-dir" }, + { name: "subdir_link.txt", isFile: () => true, parentPath: "/fake/path/.pearai-agent/rules/symlink-target-dir" }, ] as any) // Simulate readlink response @@ -657,7 +657,7 @@ describe("Rules directory reading", () => { statMock.mockReset() statMock.mockImplementation((path: string) => { // For directory check - if (path === "/fake/path/.roo/rules" || path.endsWith("dir")) { + if (path === "/fake/path/.pearai-agent/rules" || path.endsWith("dir")) { return Promise.resolve({ isDirectory: jest.fn().mockReturnValue(true), isFile: jest.fn().mockReturnValue(false), @@ -682,16 +682,16 @@ describe("Rules directory reading", () => { // Simulate file content reading readFileMock.mockImplementation((filePath: PathLike) => { - if (filePath.toString() === "/fake/path/.roo/rules/regular.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/regular.txt") { return Promise.resolve("regular file content") } - if (filePath.toString() === "/fake/path/.roo/rules/../symlink-target.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/../symlink-target.txt") { return Promise.resolve("symlink target content") } - if (filePath.toString() === "/fake/path/.roo/rules/symlink-target-dir/subdir_link.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/symlink-target-dir/subdir_link.txt") { return Promise.resolve("regular file content under symlink target dir") } - if (filePath.toString() === "/fake/path/.roo/rules/../nested-symlink-target.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/../nested-symlink-target.txt") { return Promise.resolve("nested symlink target content") } return Promise.reject({ code: "ENOENT" }) @@ -700,47 +700,47 @@ describe("Rules directory reading", () => { const result = await loadRuleFiles("/fake/path") // Verify both regular file and symlink target content are included - expect(result).toContain("# Rules from /fake/path/.roo/rules/regular.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/regular.txt:") expect(result).toContain("regular file content") - expect(result).toContain("# Rules from /fake/path/.roo/rules/../symlink-target.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/../symlink-target.txt:") expect(result).toContain("symlink target content") - expect(result).toContain("# Rules from /fake/path/.roo/rules/symlink-target-dir/subdir_link.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/symlink-target-dir/subdir_link.txt:") expect(result).toContain("regular file content under symlink target dir") - expect(result).toContain("# Rules from /fake/path/.roo/rules/../nested-symlink-target.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/../nested-symlink-target.txt:") expect(result).toContain("nested symlink target content") // Verify readlink was called with the symlink path - expect(readlinkMock).toHaveBeenCalledWith("/fake/path/.roo/rules/link.txt") - expect(readlinkMock).toHaveBeenCalledWith("/fake/path/.roo/rules/link_dir") + expect(readlinkMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/link.txt") + expect(readlinkMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/link_dir") // Verify both files were read - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/regular.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/../symlink-target.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/symlink-target-dir/subdir_link.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/../nested-symlink-target.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/regular.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/../symlink-target.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/symlink-target-dir/subdir_link.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/../nested-symlink-target.txt", "utf-8") }) beforeEach(() => { jest.clearAllMocks() }) it("should correctly format multiple files from directory", async () => { - // Simulate .roo/rules directory exists + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) // Simulate listing files readdirMock.mockResolvedValueOnce([ - { name: "file1.txt", isFile: () => true, parentPath: "/fake/path/.roo/rules" }, - { name: "file2.txt", isFile: () => true, parentPath: "/fake/path/.roo/rules" }, - { name: "file3.txt", isFile: () => true, parentPath: "/fake/path/.roo/rules" }, + { name: "file1.txt", isFile: () => true, parentPath: "/fake/path/.pearai-agent/rules" }, + { name: "file2.txt", isFile: () => true, parentPath: "/fake/path/.pearai-agent/rules" }, + { name: "file3.txt", isFile: () => true, parentPath: "/fake/path/.pearai-agent/rules" }, ] as any) statMock.mockImplementation((path) => { expect([ - "/fake/path/.roo/rules/file1.txt", - "/fake/path/.roo/rules/file2.txt", - "/fake/path/.roo/rules/file3.txt", + "/fake/path/.pearai-agent/rules/file1.txt", + "/fake/path/.pearai-agent/rules/file2.txt", + "/fake/path/.pearai-agent/rules/file3.txt", ]).toContain(path) return Promise.resolve({ @@ -749,13 +749,13 @@ describe("Rules directory reading", () => { }) readFileMock.mockImplementation((filePath: PathLike) => { - if (filePath.toString() === "/fake/path/.roo/rules/file1.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/file1.txt") { return Promise.resolve("content of file1") } - if (filePath.toString() === "/fake/path/.roo/rules/file2.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/file2.txt") { return Promise.resolve("content of file2") } - if (filePath.toString() === "/fake/path/.roo/rules/file3.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/file3.txt") { return Promise.resolve("content of file3") } return Promise.reject({ code: "ENOENT" }) @@ -763,16 +763,16 @@ describe("Rules directory reading", () => { const result = await loadRuleFiles("/fake/path") - expect(result).toContain("# Rules from /fake/path/.roo/rules/file1.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/file1.txt:") expect(result).toContain("content of file1") - expect(result).toContain("# Rules from /fake/path/.roo/rules/file2.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/file2.txt:") expect(result).toContain("content of file2") - expect(result).toContain("# Rules from /fake/path/.roo/rules/file3.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/file3.txt:") expect(result).toContain("content of file3") }) it("should handle empty file list gracefully", async () => { - // Simulate .roo/rules directory exists + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) diff --git a/src/core/prompts/sections/__tests__/custom-system-prompt.test.ts b/src/core/prompts/sections/__tests__/custom-system-prompt.test.ts index 9fc538860ae..b1ae557bd4c 100644 --- a/src/core/prompts/sections/__tests__/custom-system-prompt.test.ts +++ b/src/core/prompts/sections/__tests__/custom-system-prompt.test.ts @@ -2,6 +2,7 @@ import path from "path" import { readFile } from "fs/promises" import { Mode } from "../../../../shared/modes" // Adjusted import path import { loadSystemPromptFile, PromptVariables } from "../custom-system-prompt" +import { AGENT_RULES_DIR } from "../../../../shared/constants" // Mock the fs/promises module jest.mock("fs/promises") @@ -17,7 +18,7 @@ describe("loadSystemPromptFile", () => { const mockCwd = "/mock/cwd" const mockMode: Mode = "test" // Use Mode type, e.g., 'test' // Corrected expected file path format - const expectedFilePath = path.join(mockCwd, ".roo", `system-prompt-${mockMode}`) + const expectedFilePath = path.join(mockCwd, AGENT_RULES_DIR, `system-prompt-${mockMode}`) beforeEach(() => { // Clear mocks before each test diff --git a/src/core/prompts/sections/custom-instructions.ts b/src/core/prompts/sections/custom-instructions.ts index cf1aea24ff4..4f09ce7452c 100644 --- a/src/core/prompts/sections/custom-instructions.ts +++ b/src/core/prompts/sections/custom-instructions.ts @@ -3,6 +3,7 @@ import path from "path" import { LANGUAGES, isLanguage } from "../../../shared/language" import { Dirent } from "fs" +import { AGENT_RULES_DIR } from "../../../shared/constants" /** * Safely read a file and return its trimmed content @@ -156,8 +157,8 @@ function formatDirectoryContent(dirPath: string, files: Array<{ filename: string * Load rule files from the specified directory */ export async function loadRuleFiles(cwd: string): Promise { - // Check for .roo/rules/ directory - const rooRulesDir = path.join(cwd, ".roo", "rules") + // Check for .pearai-agent/rules/ directory + const rooRulesDir = path.join(cwd, AGENT_RULES_DIR, "rules") if (await directoryExists(rooRulesDir)) { const files = await readTextFilesFromDirectory(rooRulesDir) if (files.length > 0) { @@ -192,8 +193,8 @@ export async function addCustomInstructions( let usedRuleFile = "" if (mode) { - // Check for .roo/rules-${mode}/ directory - const modeRulesDir = path.join(cwd, ".roo", `rules-${mode}`) + // Check for .pearai-agent/rules-${mode}/ directory + const modeRulesDir = path.join(cwd, AGENT_RULES_DIR, `rules-${mode}`) if (await directoryExists(modeRulesDir)) { const files = await readTextFilesFromDirectory(modeRulesDir) if (files.length > 0) { @@ -241,7 +242,7 @@ export async function addCustomInstructions( // Add mode-specific rules first if they exist if (modeRuleContent && modeRuleContent.trim()) { - if (usedRuleFile.includes(path.join(".roo", `rules-${mode}`))) { + if (usedRuleFile.includes(path.join(AGENT_RULES_DIR, `rules-${mode}`))) { rules.push(modeRuleContent.trim()) } else { rules.push(`# Rules from ${usedRuleFile}:\n${modeRuleContent}`) diff --git a/src/core/prompts/sections/custom-system-prompt.ts b/src/core/prompts/sections/custom-system-prompt.ts index f401000bb55..8a0c746ffeb 100644 --- a/src/core/prompts/sections/custom-system-prompt.ts +++ b/src/core/prompts/sections/custom-system-prompt.ts @@ -2,6 +2,7 @@ import fs from "fs/promises" import path from "path" import { Mode } from "../../../shared/modes" import { fileExistsAtPath } from "../../../utils/fs" +import { AGENT_RULES_DIR } from "../../../shared/constants" export type PromptVariables = { workspace?: string @@ -46,11 +47,11 @@ async function safeReadFile(filePath: string): Promise { * Get the path to a system prompt file for a specific mode */ export function getSystemPromptFilePath(cwd: string, mode: Mode): string { - return path.join(cwd, ".roo", `system-prompt-${mode}`) + return path.join(cwd, AGENT_RULES_DIR, `system-prompt-${mode}`) } /** - * Loads custom system prompt from a file at .roo/system-prompt-[mode slug] + * Loads custom system prompt from a file at .pearai-agent/system-prompt-[mode slug] * If the file doesn't exist, returns an empty string */ export async function loadSystemPromptFile(cwd: string, mode: Mode, variables: PromptVariables): Promise { @@ -64,10 +65,10 @@ export async function loadSystemPromptFile(cwd: string, mode: Mode, variables: P } /** - * Ensures the .roo directory exists, creating it if necessary + * Ensures the .pearai-agent directory exists, creating it if necessary */ export async function ensureRooDirectory(cwd: string): Promise { - const rooDir = path.join(cwd, ".roo") + const rooDir = path.join(cwd, AGENT_RULES_DIR) // Check if directory already exists if (await fileExistsAtPath(rooDir)) { diff --git a/src/core/webview/__tests__/ClineProvider.test.ts b/src/core/webview/__tests__/ClineProvider.test.ts index 2942bc43b11..344c9672186 100644 --- a/src/core/webview/__tests__/ClineProvider.test.ts +++ b/src/core/webview/__tests__/ClineProvider.test.ts @@ -10,6 +10,7 @@ import { setTtsEnabled } from "../../../utils/tts" import { defaultModeSlug } from "../../../shared/modes" import { experimentDefault } from "../../../shared/experiments" import { ContextProxy } from "../../config/ContextProxy" +import { AGENT_RULES_DIR } from "../../../shared/constants" // Mock setup must come before imports jest.mock("../../prompts/sections/custom-instructions") @@ -1980,7 +1981,7 @@ describe("Project MCP Settings", () => { // Verify directory was created expect(fs.mkdir).toHaveBeenCalledWith( - expect.stringContaining(".roo"), + expect.stringContaining(AGENT_RULES_DIR), expect.objectContaining({ recursive: true }), ) @@ -2023,7 +2024,7 @@ describe("Project MCP Settings", () => { // Verify error message was shown expect(vscode.window.showErrorMessage).toHaveBeenCalledWith( - expect.stringContaining("Failed to create or open .roo/mcp.json"), + expect.stringContaining(`Failed to create or open ${AGENT_RULES_DIR}/mcp.json`), ) }) }) diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 7c4beabd570..003e2523a0c 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -39,6 +39,7 @@ import { GlobalState } from "../../schemas" import { MultiSearchReplaceDiffStrategy } from "../diff/strategies/multi-search-replace" import { getModels } from "../../api/providers/fetchers/cache" import { getpearAIExports } from "../../activate/registerPearListener" +import { AGENT_RULES_DIR } from "../../shared/constants" export const webviewMessageHandler = async (provider: ClineProvider, message: WebviewMessage) => { // Utility functions provided for concise get/update of global state via contextProxy API. @@ -398,7 +399,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We } const workspaceFolder = vscode.workspace.workspaceFolders[0] - const rooDir = path.join(workspaceFolder.uri.fsPath, ".roo") + const rooDir = path.join(workspaceFolder.uri.fsPath, AGENT_RULES_DIR) const mcpPath = path.join(rooDir, "mcp.json") try { diff --git a/src/exports/types.ts b/src/exports/types.ts index e964fdbe46c..c449b349e86 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -2,215 +2,175 @@ // Do not edit it directly. type ProviderSettings = { - apiProvider?: - | ( - | "anthropic" - | "glama" - | "openrouter" - | "bedrock" - | "vertex" - | "openai" - | "ollama" - | "vscode-lm" - | "lmstudio" - | "gemini" - | "openai-native" - | "mistral" - | "deepseek" - | "unbound" - | "requesty" - | "human-relay" - | "fake-ai" - | "pearai" - | "xai" - ) - | undefined - apiModelId?: string | undefined - apiKey?: string | undefined - anthropicBaseUrl?: string | undefined - anthropicUseAuthToken?: boolean | undefined - glamaModelId?: string | undefined - glamaApiKey?: string | undefined - openRouterApiKey?: string | undefined - openRouterModelId?: string | undefined - openRouterBaseUrl?: string | undefined - openRouterSpecificProvider?: string | undefined - openRouterUseMiddleOutTransform?: boolean | undefined - awsAccessKey?: string | undefined - awsSecretKey?: string | undefined - awsSessionToken?: string | undefined - awsRegion?: string | undefined - awsUseCrossRegionInference?: boolean | undefined - awsUsePromptCache?: boolean | undefined - awspromptCacheId?: string | undefined - awsProfile?: string | undefined - awsUseProfile?: boolean | undefined - awsCustomArn?: string | undefined - vertexKeyFile?: string | undefined - vertexJsonCredentials?: string | undefined - vertexProjectId?: string | undefined - vertexRegion?: string | undefined - openAiBaseUrl?: string | undefined - openAiApiKey?: string | undefined - openAiLegacyFormat?: boolean | undefined - openAiR1FormatEnabled?: boolean | undefined - openAiModelId?: string | undefined - openAiCustomModelInfo?: - | ({ - maxTokens?: (number | null) | undefined - maxThinkingTokens?: (number | null) | undefined - contextWindow: number - supportsImages?: boolean | undefined - supportsComputerUse?: boolean | undefined - supportsPromptCache: boolean - isPromptCacheOptional?: boolean | undefined - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - description?: string | undefined - reasoningEffort?: ("low" | "medium" | "high") | undefined - thinking?: boolean | undefined - minTokensPerCachePoint?: number | undefined - maxCachePoints?: number | undefined - cachableFields?: string[] | undefined - underlyingModel?: string | undefined - tiers?: - | { - contextWindow: number - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - }[] - | undefined - } | null) - | undefined - openAiUseAzure?: boolean | undefined - azureApiVersion?: string | undefined - openAiStreamingEnabled?: boolean | undefined - enableReasoningEffort?: boolean | undefined - openAiHostHeader?: string | undefined - openAiHeaders?: - | { - [x: string]: string - } - | undefined - ollamaModelId?: string | undefined - ollamaBaseUrl?: string | undefined - vsCodeLmModelSelector?: - | { - vendor?: string | undefined - family?: string | undefined - version?: string | undefined - id?: string | undefined - } - | undefined - lmStudioModelId?: string | undefined - lmStudioBaseUrl?: string | undefined - lmStudioDraftModelId?: string | undefined - lmStudioSpeculativeDecodingEnabled?: boolean | undefined - geminiApiKey?: string | undefined - googleGeminiBaseUrl?: string | undefined - openAiNativeApiKey?: string | undefined - openAiNativeBaseUrl?: string | undefined - mistralApiKey?: string | undefined - mistralCodestralUrl?: string | undefined - deepSeekBaseUrl?: string | undefined - deepSeekApiKey?: string | undefined - unboundApiKey?: string | undefined - unboundModelId?: string | undefined - requestyApiKey?: string | undefined - requestyModelId?: string | undefined - xaiApiKey?: string | undefined - modelMaxTokens?: number | undefined - modelMaxThinkingTokens?: number | undefined - includeMaxTokens?: boolean | undefined - reasoningEffort?: ("low" | "medium" | "high") | undefined - promptCachingEnabled?: boolean | undefined - diffEnabled?: boolean | undefined - fuzzyMatchThreshold?: number | undefined - modelTemperature?: (number | null) | undefined - rateLimitSeconds?: number | undefined - fakeAi?: unknown | undefined - pearaiBaseUrl?: string | undefined - pearaiModelId?: string | undefined - pearaiApiKey?: string | undefined - pearaiModelInfo?: - | ({ - maxTokens?: (number | null) | undefined - maxThinkingTokens?: (number | null) | undefined - contextWindow: number - supportsImages?: boolean | undefined - supportsComputerUse?: boolean | undefined - supportsPromptCache: boolean - isPromptCacheOptional?: boolean | undefined - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - description?: string | undefined - reasoningEffort?: ("low" | "medium" | "high") | undefined - thinking?: boolean | undefined - minTokensPerCachePoint?: number | undefined - maxCachePoints?: number | undefined - cachableFields?: string[] | undefined - underlyingModel?: string | undefined - tiers?: - | { - contextWindow: number - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - }[] - | undefined - } | null) - | undefined - pearaiAgentModels?: - | { - models: { - [x: string]: { - maxTokens?: (number | null) | undefined - maxThinkingTokens?: (number | null) | undefined - contextWindow: number - supportsImages?: boolean | undefined - supportsComputerUse?: boolean | undefined - supportsPromptCache: boolean - isPromptCacheOptional?: boolean | undefined - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - description?: string | undefined - reasoningEffort?: ("low" | "medium" | "high") | undefined - thinking?: boolean | undefined - minTokensPerCachePoint?: number | undefined - maxCachePoints?: number | undefined - cachableFields?: string[] | undefined - underlyingModel?: string | undefined - tiers?: - | { - contextWindow: number - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - }[] - | undefined - } - } - defaultModelId?: string | undefined - } - | undefined - creatorModeConfig?: - | { - creatorMode?: boolean | undefined - newProjectType?: string | undefined - newProjectPath?: string | undefined - } - | undefined -} + apiProvider?: ("anthropic" | "glama" | "openrouter" | "bedrock" | "vertex" | "openai" | "ollama" | "vscode-lm" | "lmstudio" | "gemini" | "openai-native" | "mistral" | "deepseek" | "unbound" | "requesty" | "human-relay" | "fake-ai" | "pearai" | "xai") | undefined; + apiModelId?: string | undefined; + apiKey?: string | undefined; + anthropicBaseUrl?: string | undefined; + anthropicUseAuthToken?: boolean | undefined; + glamaModelId?: string | undefined; + glamaApiKey?: string | undefined; + openRouterApiKey?: string | undefined; + openRouterModelId?: string | undefined; + openRouterBaseUrl?: string | undefined; + openRouterSpecificProvider?: string | undefined; + openRouterUseMiddleOutTransform?: boolean | undefined; + awsAccessKey?: string | undefined; + awsSecretKey?: string | undefined; + awsSessionToken?: string | undefined; + awsRegion?: string | undefined; + awsUseCrossRegionInference?: boolean | undefined; + awsUsePromptCache?: boolean | undefined; + awspromptCacheId?: string | undefined; + awsProfile?: string | undefined; + awsUseProfile?: boolean | undefined; + awsCustomArn?: string | undefined; + vertexKeyFile?: string | undefined; + vertexJsonCredentials?: string | undefined; + vertexProjectId?: string | undefined; + vertexRegion?: string | undefined; + openAiBaseUrl?: string | undefined; + openAiApiKey?: string | undefined; + openAiLegacyFormat?: boolean | undefined; + openAiR1FormatEnabled?: boolean | undefined; + openAiModelId?: string | undefined; + openAiCustomModelInfo?: ({ + maxTokens?: (number | null) | undefined; + maxThinkingTokens?: (number | null) | undefined; + contextWindow: number; + supportsImages?: boolean | undefined; + supportsComputerUse?: boolean | undefined; + supportsPromptCache: boolean; + isPromptCacheOptional?: boolean | undefined; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + description?: string | undefined; + reasoningEffort?: ("low" | "medium" | "high") | undefined; + thinking?: boolean | undefined; + minTokensPerCachePoint?: number | undefined; + maxCachePoints?: number | undefined; + cachableFields?: string[] | undefined; + underlyingModel?: string | undefined; + tiers?: { + contextWindow: number; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + }[] | undefined; + } | null) | undefined; + openAiUseAzure?: boolean | undefined; + azureApiVersion?: string | undefined; + openAiStreamingEnabled?: boolean | undefined; + enableReasoningEffort?: boolean | undefined; + openAiHostHeader?: string | undefined; + openAiHeaders?: { + [x: string]: string; + } | undefined; + ollamaModelId?: string | undefined; + ollamaBaseUrl?: string | undefined; + vsCodeLmModelSelector?: { + vendor?: string | undefined; + family?: string | undefined; + version?: string | undefined; + id?: string | undefined; + } | undefined; + lmStudioModelId?: string | undefined; + lmStudioBaseUrl?: string | undefined; + lmStudioDraftModelId?: string | undefined; + lmStudioSpeculativeDecodingEnabled?: boolean | undefined; + geminiApiKey?: string | undefined; + googleGeminiBaseUrl?: string | undefined; + openAiNativeApiKey?: string | undefined; + openAiNativeBaseUrl?: string | undefined; + mistralApiKey?: string | undefined; + mistralCodestralUrl?: string | undefined; + deepSeekBaseUrl?: string | undefined; + deepSeekApiKey?: string | undefined; + unboundApiKey?: string | undefined; + unboundModelId?: string | undefined; + requestyApiKey?: string | undefined; + requestyModelId?: string | undefined; + xaiApiKey?: string | undefined; + modelMaxTokens?: number | undefined; + modelMaxThinkingTokens?: number | undefined; + includeMaxTokens?: boolean | undefined; + reasoningEffort?: ("low" | "medium" | "high") | undefined; + promptCachingEnabled?: boolean | undefined; + diffEnabled?: boolean | undefined; + fuzzyMatchThreshold?: number | undefined; + modelTemperature?: (number | null) | undefined; + rateLimitSeconds?: number | undefined; + fakeAi?: unknown | undefined; + pearaiBaseUrl?: string | undefined; + pearaiModelId?: string | undefined; + pearaiApiKey?: string | undefined; + pearaiModelInfo?: ({ + maxTokens?: (number | null) | undefined; + maxThinkingTokens?: (number | null) | undefined; + contextWindow: number; + supportsImages?: boolean | undefined; + supportsComputerUse?: boolean | undefined; + supportsPromptCache: boolean; + isPromptCacheOptional?: boolean | undefined; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + description?: string | undefined; + reasoningEffort?: ("low" | "medium" | "high") | undefined; + thinking?: boolean | undefined; + minTokensPerCachePoint?: number | undefined; + maxCachePoints?: number | undefined; + cachableFields?: string[] | undefined; + underlyingModel?: string | undefined; + tiers?: { + contextWindow: number; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + }[] | undefined; + } | null) | undefined; + pearaiAgentModels?: { + models: { + [x: string]: { + maxTokens?: (number | null) | undefined; + maxThinkingTokens?: (number | null) | undefined; + contextWindow: number; + supportsImages?: boolean | undefined; + supportsComputerUse?: boolean | undefined; + supportsPromptCache: boolean; + isPromptCacheOptional?: boolean | undefined; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + description?: string | undefined; + reasoningEffort?: ("low" | "medium" | "high") | undefined; + thinking?: boolean | undefined; + minTokensPerCachePoint?: number | undefined; + maxCachePoints?: number | undefined; + cachableFields?: string[] | undefined; + underlyingModel?: string | undefined; + tiers?: { + contextWindow: number; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + }[] | undefined; + }; + }; + defaultModelId?: string | undefined; + } | undefined; + creatorModeConfig?: { + creatorMode?: boolean | undefined; + newProjectType?: string | undefined; + newProjectPath?: string | undefined; + } | undefined; +}; export type { ProviderSettings } @@ -392,207 +352,123 @@ type GlobalSettings = { export type { GlobalSettings } type ClineMessage = { - ts: number - type: "ask" | "say" - ask?: - | ( - | "followup" - | "command" - | "command_output" - | "completion_result" - | "tool" - | "api_req_failed" - | "resume_task" - | "resume_completed_task" - | "mistake_limit_reached" - | "browser_action_launch" - | "use_mcp_server" - ) - | undefined - say?: - | ( - | "error" - | "api_req_started" - | "api_req_finished" - | "api_req_retried" - | "api_req_retry_delayed" - | "api_req_deleted" - | "text" - | "reasoning" - | "completion_result" - | "user_feedback" - | "user_feedback_diff" - | "command_output" - | "shell_integration_warning" - | "browser_action" - | "browser_action_result" - | "mcp_server_request_started" - | "mcp_server_response" - | "subtask_result" - | "checkpoint_saved" - | "rooignore_error" - | "diff_error" - ) - | undefined - text?: string | undefined - images?: string[] | undefined - partial?: boolean | undefined - reasoning?: string | undefined - conversationHistoryIndex?: number | undefined - checkpoint?: - | { - [x: string]: unknown - } - | undefined - progressStatus?: - | { - id?: string | undefined - icon?: string | undefined - text?: string | undefined - } - | undefined -} + ts: number; + type: "ask" | "say"; + ask?: ("followup" | "command" | "command_output" | "completion_result" | "tool" | "api_req_failed" | "resume_task" | "resume_completed_task" | "mistake_limit_reached" | "browser_action_launch" | "use_mcp_server") | undefined; + say?: ("error" | "api_req_started" | "api_req_finished" | "api_req_retried" | "api_req_retry_delayed" | "api_req_deleted" | "text" | "reasoning" | "completion_result" | "user_feedback" | "user_feedback_diff" | "command_output" | "shell_integration_warning" | "browser_action" | "browser_action_result" | "mcp_server_request_started" | "mcp_server_response" | "subtask_result" | "checkpoint_saved" | "rooignore_error" | "diff_error") | undefined; + text?: string | undefined; + images?: string[] | undefined; + partial?: boolean | undefined; + reasoning?: string | undefined; + conversationHistoryIndex?: number | undefined; + checkpoint?: { + [x: string]: unknown; + } | undefined; + progressStatus?: { + id?: string | undefined; + icon?: string | undefined; + text?: string | undefined; + } | undefined; +}; export type { ClineMessage } type TokenUsage = { - totalTokensIn: number - totalTokensOut: number - totalCacheWrites?: number | undefined - totalCacheReads?: number | undefined - totalCost: number - contextTokens: number -} + totalTokensIn: number; + totalTokensOut: number; + totalCacheWrites?: number | undefined; + totalCacheReads?: number | undefined; + totalCost: number; + contextTokens: number; +}; export type { TokenUsage } type RooCodeEvents = { - message: [ - { - taskId: string - action: "created" | "updated" - message: { - ts: number - type: "ask" | "say" - ask?: - | ( - | "followup" - | "command" - | "command_output" - | "completion_result" - | "tool" - | "api_req_failed" - | "resume_task" - | "resume_completed_task" - | "mistake_limit_reached" - | "browser_action_launch" - | "use_mcp_server" - ) - | undefined - say?: - | ( - | "error" - | "api_req_started" - | "api_req_finished" - | "api_req_retried" - | "api_req_retry_delayed" - | "api_req_deleted" - | "text" - | "reasoning" - | "completion_result" - | "user_feedback" - | "user_feedback_diff" - | "command_output" - | "shell_integration_warning" - | "browser_action" - | "browser_action_result" - | "mcp_server_request_started" - | "mcp_server_response" - | "subtask_result" - | "checkpoint_saved" - | "rooignore_error" - | "diff_error" - ) - | undefined - text?: string | undefined - images?: string[] | undefined - partial?: boolean | undefined - reasoning?: string | undefined - conversationHistoryIndex?: number | undefined - checkpoint?: - | { - [x: string]: unknown - } - | undefined - progressStatus?: - | { - id?: string | undefined - icon?: string | undefined - text?: string | undefined - } - | undefined - } - }, - ] - taskCreated: [string] - taskStarted: [string] - taskModeSwitched: [string, string] - taskPaused: [string] - taskUnpaused: [string] - taskAskResponded: [string] - taskAborted: [string] - taskSpawned: [string, string] - taskCompleted: [ - string, - { - totalTokensIn: number - totalTokensOut: number - totalCacheWrites?: number | undefined - totalCacheReads?: number | undefined - totalCost: number - contextTokens: number - }, - { - [x: string]: { - attempts: number - failures: number - } - }, - ] - taskTokenUsageUpdated: [ - string, - { - totalTokensIn: number - totalTokensOut: number - totalCacheWrites?: number | undefined - totalCacheReads?: number | undefined - totalCost: number - contextTokens: number - }, - ] - taskToolFailed: [ - string, - ( - | "execute_command" - | "read_file" - | "write_to_file" - | "apply_diff" - | "insert_content" - | "search_and_replace" - | "search_files" - | "list_files" - | "list_code_definition_names" - | "browser_action" - | "use_mcp_tool" - | "access_mcp_resource" - | "ask_followup_question" - | "attempt_completion" - | "switch_mode" - | "new_task" - | "fetch_instructions" - ), - string, - ] -} + message: [ + { + taskId: string; + action: "created" | "updated"; + message: { + ts: number; + type: "ask" | "say"; + ask?: ("followup" | "command" | "command_output" | "completion_result" | "tool" | "api_req_failed" | "resume_task" | "resume_completed_task" | "mistake_limit_reached" | "browser_action_launch" | "use_mcp_server") | undefined; + say?: ("error" | "api_req_started" | "api_req_finished" | "api_req_retried" | "api_req_retry_delayed" | "api_req_deleted" | "text" | "reasoning" | "completion_result" | "user_feedback" | "user_feedback_diff" | "command_output" | "shell_integration_warning" | "browser_action" | "browser_action_result" | "mcp_server_request_started" | "mcp_server_response" | "subtask_result" | "checkpoint_saved" | "rooignore_error" | "diff_error") | undefined; + text?: string | undefined; + images?: string[] | undefined; + partial?: boolean | undefined; + reasoning?: string | undefined; + conversationHistoryIndex?: number | undefined; + checkpoint?: { + [x: string]: unknown; + } | undefined; + progressStatus?: { + id?: string | undefined; + icon?: string | undefined; + text?: string | undefined; + } | undefined; + }; + } + ]; + taskCreated: [ + string + ]; + taskStarted: [ + string + ]; + taskModeSwitched: [ + string, + string + ]; + taskPaused: [ + string + ]; + taskUnpaused: [ + string + ]; + taskAskResponded: [ + string + ]; + taskAborted: [ + string + ]; + taskSpawned: [ + string, + string + ]; + taskCompleted: [ + string, + { + totalTokensIn: number; + totalTokensOut: number; + totalCacheWrites?: number | undefined; + totalCacheReads?: number | undefined; + totalCost: number; + contextTokens: number; + }, + { + [x: string]: { + attempts: number; + failures: number; + }; + } + ]; + taskTokenUsageUpdated: [ + string, + { + totalTokensIn: number; + totalTokensOut: number; + totalCacheWrites?: number | undefined; + totalCacheReads?: number | undefined; + totalCost: number; + contextTokens: number; + } + ]; + taskToolFailed: [ + string, + "execute_command" | "read_file" | "write_to_file" | "apply_diff" | "insert_content" | "search_and_replace" | "search_files" | "list_files" | "list_code_definition_names" | "browser_action" | "use_mcp_tool" | "access_mcp_resource" | "ask_followup_question" | "attempt_completion" | "switch_mode" | "new_task" | "fetch_instructions", + string + ]; +}; -export type { RooCodeEvents } +export type { RooCodeEvents } \ No newline at end of file diff --git a/src/i18n/locales/ca/common.json b/src/i18n/locales/ca/common.json index 673d73687ea..3f9cd4bdb83 100644 --- a/src/i18n/locales/ca/common.json +++ b/src/i18n/locales/ca/common.json @@ -49,7 +49,7 @@ "list_api_config": "Ha fallat l'obtenció de la llista de configuracions de l'API", "update_server_timeout": "Ha fallat l'actualització del temps d'espera del servidor", "failed_update_project_mcp": "Ha fallat l'actualització dels servidors MCP del projecte", - "create_mcp_json": "Ha fallat la creació o obertura de .roo/mcp.json: {{error}}", + "create_mcp_json": "Ha fallat la creació o obertura de .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "El servidor de desenvolupament local no està executant-se, l'HMR no funcionarà. Si us plau, executa 'npm run dev' abans de llançar l'extensió per habilitar l'HMR.", "retrieve_current_mode": "Error en recuperar el mode actual de l'estat.", "failed_delete_repo": "Ha fallat l'eliminació del repositori o branca associada: {{error}}", diff --git a/src/i18n/locales/de/common.json b/src/i18n/locales/de/common.json index cc62749a8d0..efee4e28623 100644 --- a/src/i18n/locales/de/common.json +++ b/src/i18n/locales/de/common.json @@ -45,7 +45,7 @@ "list_api_config": "Fehler beim Abrufen der API-Konfigurationsliste", "update_server_timeout": "Fehler beim Aktualisieren des Server-Timeouts", "failed_update_project_mcp": "Fehler beim Aktualisieren der Projekt-MCP-Server", - "create_mcp_json": "Fehler beim Erstellen oder Öffnen von .roo/mcp.json: {{error}}", + "create_mcp_json": "Fehler beim Erstellen oder Öffnen von .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Der lokale Entwicklungsserver läuft nicht, HMR wird nicht funktionieren. Bitte führen Sie 'npm run dev' vor dem Start der Erweiterung aus, um HMR zu aktivieren.", "retrieve_current_mode": "Fehler beim Abrufen des aktuellen Modus aus dem Zustand.", "failed_delete_repo": "Fehler beim Löschen des zugehörigen Shadow-Repositorys oder -Zweigs: {{error}}", diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index b06f5e8091e..89b1b292fb6 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -44,7 +44,7 @@ "delete_api_config": "Failed to delete api configuration", "list_api_config": "Failed to get list api configuration", "update_server_timeout": "Failed to update server timeout", - "create_mcp_json": "Failed to create or open .roo/mcp.json: {{error}}", + "create_mcp_json": "Failed to create or open .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Local development server is not running, HMR will not work. Please run 'npm run dev' before launching the extension to enable HMR.", "retrieve_current_mode": "Error: failed to retrieve current mode from state.", "failed_delete_repo": "Failed to delete associated shadow repository or branch: {{error}}", diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index 25affcb4581..4a9b82e0be9 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -45,7 +45,7 @@ "list_api_config": "Error al obtener la lista de configuraciones de API", "update_server_timeout": "Error al actualizar el tiempo de espera del servidor", "failed_update_project_mcp": "Error al actualizar los servidores MCP del proyecto", - "create_mcp_json": "Error al crear o abrir .roo/mcp.json: {{error}}", + "create_mcp_json": "Error al crear o abrir .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "El servidor de desarrollo local no está en ejecución, HMR no funcionará. Por favor, ejecuta 'npm run dev' antes de lanzar la extensión para habilitar HMR.", "retrieve_current_mode": "Error al recuperar el modo actual del estado.", "failed_delete_repo": "Error al eliminar el repositorio o rama asociada: {{error}}", diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index d4ed08c1911..55e172100ee 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -45,7 +45,7 @@ "list_api_config": "Erreur lors de l'obtention de la liste des configurations API", "update_server_timeout": "Erreur lors de la mise à jour du délai d'attente du serveur", "failed_update_project_mcp": "Échec de la mise à jour des serveurs MCP du projet", - "create_mcp_json": "Échec de la création ou de l'ouverture de .roo/mcp.json : {{error}}", + "create_mcp_json": "Échec de la création ou de l'ouverture de .pearai-agent/mcp.json : {{error}}", "hmr_not_running": "Le serveur de développement local n'est pas en cours d'exécution, HMR ne fonctionnera pas. Veuillez exécuter 'npm run dev' avant de lancer l'extension pour activer l'HMR.", "retrieve_current_mode": "Erreur lors de la récupération du mode actuel à partir du state.", "failed_delete_repo": "Échec de la suppression du repo fantôme ou de la branche associée : {{error}}", diff --git a/src/i18n/locales/hi/common.json b/src/i18n/locales/hi/common.json index 8c244009d18..e4f3a51ebb8 100644 --- a/src/i18n/locales/hi/common.json +++ b/src/i18n/locales/hi/common.json @@ -45,7 +45,7 @@ "list_api_config": "API कॉन्फ़िगरेशन की सूची प्राप्त करने में विफल", "update_server_timeout": "सर्वर टाइमआउट अपडेट करने में विफल", "failed_update_project_mcp": "प्रोजेक्ट MCP सर्वर अपडेट करने में विफल", - "create_mcp_json": ".roo/mcp.json बनाने या खोलने में विफल: {{error}}", + "create_mcp_json": ".pearai-agent/mcp.json बनाने या खोलने में विफल: {{error}}", "hmr_not_running": "स्थानीय विकास सर्वर चल नहीं रहा है, HMR काम नहीं करेगा। कृपया HMR सक्षम करने के लिए एक्सटेंशन लॉन्च करने से पहले 'npm run dev' चलाएँ।", "retrieve_current_mode": "स्टेट से वर्तमान मोड प्राप्त करने में त्रुटि।", "failed_delete_repo": "संबंधित शैडो रिपॉजिटरी या ब्रांच हटाने में विफल: {{error}}", diff --git a/src/i18n/locales/it/common.json b/src/i18n/locales/it/common.json index 2c9879186f2..94dda7ea3f1 100644 --- a/src/i18n/locales/it/common.json +++ b/src/i18n/locales/it/common.json @@ -45,7 +45,7 @@ "list_api_config": "Errore durante l'ottenimento dell'elenco delle configurazioni API", "update_server_timeout": "Errore durante l'aggiornamento del timeout del server", "failed_update_project_mcp": "Errore durante l'aggiornamento dei server MCP del progetto", - "create_mcp_json": "Impossibile creare o aprire .roo/mcp.json: {{error}}", + "create_mcp_json": "Impossibile creare o aprire .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Il server di sviluppo locale non è in esecuzione, l'HMR non funzionerà. Esegui 'npm run dev' prima di avviare l'estensione per abilitare l'HMR.", "retrieve_current_mode": "Errore durante il recupero della modalità corrente dallo stato.", "failed_delete_repo": "Impossibile eliminare il repository o il ramo associato: {{error}}", diff --git a/src/i18n/locales/ja/common.json b/src/i18n/locales/ja/common.json index a2b283bd83e..dc6a9da9299 100644 --- a/src/i18n/locales/ja/common.json +++ b/src/i18n/locales/ja/common.json @@ -45,7 +45,7 @@ "list_api_config": "API設定リストの取得に失敗しました", "update_server_timeout": "サーバータイムアウトの更新に失敗しました", "failed_update_project_mcp": "プロジェクトMCPサーバーの更新に失敗しました", - "create_mcp_json": ".roo/mcp.jsonの作成または開くことに失敗しました:{{error}}", + "create_mcp_json": ".pearai-agent/mcp.jsonの作成または開くことに失敗しました:{{error}}", "hmr_not_running": "ローカル開発サーバーが実行されていないため、HMRは機能しません。HMRを有効にするには、拡張機能を起動する前に'npm run dev'を実行してください。", "retrieve_current_mode": "現在のモードを状態から取得する際にエラーが発生しました。", "failed_delete_repo": "関連するシャドウリポジトリまたはブランチの削除に失敗しました:{{error}}", diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json index 9700d80f0e0..8e1ba132f44 100644 --- a/src/i18n/locales/ko/common.json +++ b/src/i18n/locales/ko/common.json @@ -45,7 +45,7 @@ "list_api_config": "API 구성 목록 가져오기에 실패했습니다", "update_server_timeout": "서버 타임아웃 업데이트에 실패했습니다", "failed_update_project_mcp": "프로젝트 MCP 서버 업데이트에 실패했습니다", - "create_mcp_json": ".roo/mcp.json 생성 또는 열기 실패: {{error}}", + "create_mcp_json": ".pearai-agent/mcp.json 생성 또는 열기 실패: {{error}}", "hmr_not_running": "로컬 개발 서버가 실행되고 있지 않아 HMR이 작동하지 않습니다. HMR을 활성화하려면 확장 프로그램을 실행하기 전에 'npm run dev'를 실행하세요.", "retrieve_current_mode": "상태에서 현재 모드를 검색하는 데 오류가 발생했습니다.", "failed_delete_repo": "관련 shadow 저장소 또는 브랜치 삭제 실패: {{error}}", diff --git a/src/i18n/locales/pl/common.json b/src/i18n/locales/pl/common.json index bcb345346d8..dbc459ad581 100644 --- a/src/i18n/locales/pl/common.json +++ b/src/i18n/locales/pl/common.json @@ -45,7 +45,7 @@ "list_api_config": "Nie udało się pobrać listy konfiguracji API", "update_server_timeout": "Nie udało się zaktualizować limitu czasu serwera", "failed_update_project_mcp": "Nie udało się zaktualizować serwerów MCP projektu", - "create_mcp_json": "Nie udało się utworzyć lub otworzyć .roo/mcp.json: {{error}}", + "create_mcp_json": "Nie udało się utworzyć lub otworzyć .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Lokalny serwer deweloperski nie jest uruchomiony, HMR nie będzie działać. Uruchom 'npm run dev' przed uruchomieniem rozszerzenia, aby włączyć HMR.", "retrieve_current_mode": "Błąd podczas pobierania bieżącego trybu ze stanu.", "failed_delete_repo": "Nie udało się usunąć powiązanego repozytorium lub gałęzi pomocniczej: {{error}}", diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json index e2ade21da2d..0de62c10a54 100644 --- a/src/i18n/locales/pt-BR/common.json +++ b/src/i18n/locales/pt-BR/common.json @@ -49,7 +49,7 @@ "list_api_config": "Falha ao obter a lista de configurações da API", "update_server_timeout": "Falha ao atualizar o tempo limite do servidor", "failed_update_project_mcp": "Falha ao atualizar os servidores MCP do projeto", - "create_mcp_json": "Falha ao criar ou abrir .roo/mcp.json: {{error}}", + "create_mcp_json": "Falha ao criar ou abrir .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "O servidor de desenvolvimento local não está em execução, o HMR não funcionará. Por favor, execute 'npm run dev' antes de iniciar a extensão para habilitar o HMR.", "retrieve_current_mode": "Erro ao recuperar o modo atual do estado.", "failed_delete_repo": "Falha ao excluir o repositório ou ramificação associada: {{error}}", diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json index 9f2ee4d9e87..f9f3a87b2d0 100644 --- a/src/i18n/locales/ru/common.json +++ b/src/i18n/locales/ru/common.json @@ -44,7 +44,7 @@ "delete_api_config": "Не удалось удалить конфигурацию API", "list_api_config": "Не удалось получить список конфигураций API", "update_server_timeout": "Не удалось обновить таймаут сервера", - "create_mcp_json": "Не удалось создать или открыть .roo/mcp.json: {{error}}", + "create_mcp_json": "Не удалось создать или открыть .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Локальный сервер разработки не запущен, HMR не будет работать. Пожалуйста, запустите 'npm run dev' перед запуском расширения для включения HMR.", "retrieve_current_mode": "Ошибка: не удалось получить текущий режим из состояния.", "failed_delete_repo": "Не удалось удалить связанный теневой репозиторий или ветку: {{error}}", diff --git a/src/i18n/locales/tr/common.json b/src/i18n/locales/tr/common.json index 9991cf0f825..0b3045166c5 100644 --- a/src/i18n/locales/tr/common.json +++ b/src/i18n/locales/tr/common.json @@ -45,7 +45,7 @@ "list_api_config": "API yapılandırma listesi alınamadı", "update_server_timeout": "Sunucu zaman aşımı güncellenemedi", "failed_update_project_mcp": "Proje MCP sunucuları güncellenemedi", - "create_mcp_json": ".roo/mcp.json oluşturulamadı veya açılamadı: {{error}}", + "create_mcp_json": ".pearai-agent/mcp.json oluşturulamadı veya açılamadı: {{error}}", "hmr_not_running": "Yerel geliştirme sunucusu çalışmıyor, HMR çalışmayacak. HMR'yi etkinleştirmek için uzantıyı başlatmadan önce lütfen 'npm run dev' komutunu çalıştırın.", "retrieve_current_mode": "Mevcut mod durumdan alınırken hata oluştu.", "failed_delete_repo": "İlişkili gölge depo veya dal silinemedi: {{error}}", diff --git a/src/i18n/locales/vi/common.json b/src/i18n/locales/vi/common.json index 613c62c8b3e..1375111ed95 100644 --- a/src/i18n/locales/vi/common.json +++ b/src/i18n/locales/vi/common.json @@ -45,7 +45,7 @@ "list_api_config": "Không thể lấy danh sách cấu hình API", "update_server_timeout": "Không thể cập nhật thời gian chờ máy chủ", "failed_update_project_mcp": "Không thể cập nhật máy chủ MCP của dự án", - "create_mcp_json": "Không thể tạo hoặc mở .roo/mcp.json: {{error}}", + "create_mcp_json": "Không thể tạo hoặc mở .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Máy chủ phát triển cục bộ không chạy, HMR sẽ không hoạt động. Vui lòng chạy 'npm run dev' trước khi khởi chạy tiện ích mở rộng để bật HMR.", "retrieve_current_mode": "Lỗi không thể truy xuất chế độ hiện tại từ trạng thái.", "failed_delete_repo": "Không thể xóa kho lưu trữ hoặc nhánh liên quan: {{error}}", diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index 9e4512c584d..66e84d55e07 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -45,7 +45,7 @@ "list_api_config": "获取API配置列表失败", "update_server_timeout": "更新服务器超时设置失败", "failed_update_project_mcp": "更新项目MCP服务器失败", - "create_mcp_json": "创建或打开 .roo/mcp.json 失败:{{error}}", + "create_mcp_json": "创建或打开 .pearai-agent/mcp.json 失败:{{error}}", "hmr_not_running": "本地开发服务器未运行,HMR将不起作用。请在启动扩展前运行'npm run dev'以启用HMR。", "retrieve_current_mode": "从状态中检索当前模式失败。", "failed_delete_repo": "删除关联的影子仓库或分支失败:{{error}}", diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json index 1d12b862907..61f01c30622 100644 --- a/src/i18n/locales/zh-TW/common.json +++ b/src/i18n/locales/zh-TW/common.json @@ -45,7 +45,7 @@ "list_api_config": "取得 API 設定列表失敗", "update_server_timeout": "更新伺服器超時設定失敗", "failed_update_project_mcp": "更新專案 MCP 伺服器失敗", - "create_mcp_json": "建立或開啟 .roo/mcp.json 失敗:{{error}}", + "create_mcp_json": "建立或開啟 .pearai-agent/mcp.json 失敗:{{error}}", "hmr_not_running": "本機開發伺服器沒有執行,HMR 將不起作用。請在啟動擴充套件前執行'npm run dev'以啟用 HMR。", "retrieve_current_mode": "從狀態中檢索目前模式失敗。", "failed_delete_repo": "刪除關聯的影子倉庫或分支失敗:{{error}}", diff --git a/src/services/mcp/McpHub.ts b/src/services/mcp/McpHub.ts index e19dc849dd3..bb6ab004b3a 100644 --- a/src/services/mcp/McpHub.ts +++ b/src/services/mcp/McpHub.ts @@ -32,6 +32,7 @@ import { fileExistsAtPath } from "../../utils/fs" import { arePathsEqual } from "../../utils/path" import { injectEnv } from "../../utils/config" import { PEARAI_URL } from "../../shared/pearaiApi" +import { AGENT_RULES_DIR } from "../../shared/constants" export type McpConnection = { server: McpServer @@ -498,7 +499,7 @@ export class McpHub { } const workspaceFolder = vscode.workspace.workspaceFolders[0] - const projectMcpDir = path.join(workspaceFolder.uri.fsPath, ".roo") + const projectMcpDir = path.join(workspaceFolder.uri.fsPath, AGENT_RULES_DIR) const projectMcpPath = path.join(projectMcpDir, "mcp.json") try { diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index cbd03f0723d..e6f0c1297c8 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -183,7 +183,7 @@ export type ExtensionState = Pick< enableCheckpoints: boolean maxOpenTabsContext: number // Maximum number of VSCode open tabs to include in context (0-500) maxWorkspaceFiles: number // Maximum number of files to include in current working directory details (0-500) - showRooIgnoredFiles: boolean // Whether to show .rooignore'd files in listings + showRooIgnoredFiles: boolean // Whether to show .pearai-agent-ignore'd files in listings maxReadFileLine: number // Maximum number of lines to read from a file before truncating experiments: Record // Map of experiment IDs to their enabled state diff --git a/src/shared/constants.ts b/src/shared/constants.ts new file mode 100644 index 00000000000..ad3b74bf628 --- /dev/null +++ b/src/shared/constants.ts @@ -0,0 +1,5 @@ +export const AGENT_RULES_DIR = ".pearai-agent" + +export const AGENT_IGNORE_FILE_NAME = ".pearai-agent-ignore" + +export const AGENT_MODES_FILE_NAME = ".pearai-agent-modes" diff --git a/src/shared/pearaiApi.ts b/src/shared/pearaiApi.ts index 0d110218aa3..c0a5e4d3656 100644 --- a/src/shared/pearaiApi.ts +++ b/src/shared/pearaiApi.ts @@ -1,8 +1,8 @@ // CHANGE AS NEEDED FOR DEVELOPMENT // PROD: -export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" +// export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" // DEV: -// export const PEARAI_URL = "http://localhost:8000/integrations/cline" +export const PEARAI_URL = "http://localhost:8000/integrations/cline" import { anthropicModels, diff --git a/src/utils/path.ts b/src/utils/path.ts index a58d6301725..296665d907d 100644 --- a/src/utils/path.ts +++ b/src/utils/path.ts @@ -2,6 +2,7 @@ import * as path from "path" import os from "os" import * as vscode from "vscode" + /* The Node.js 'path' module resolves and normalizes paths differently depending on the platform: - On Windows, it uses backslashes (\) as the default path separator. diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx index dcf819b2869..5d17dd04a60 100644 --- a/webview-ui/src/components/prompts/PromptsView.tsx +++ b/webview-ui/src/components/prompts/PromptsView.tsx @@ -29,6 +29,7 @@ import { Tab, TabContent, TabHeader } from "../common/Tab" import i18next from "i18next" import { useAppTranslation } from "@src/i18n/TranslationContext" import { Trans } from "react-i18next" +import { AGENT_MODES_FILE_NAME, AGENT_RULES_DIR } from "@roo/shared/constants" // Get all available groups that should show in prompts view const availableGroups = (Object.keys(TOOL_GROUPS) as ToolGroup[]).filter((group) => !TOOL_GROUPS[group].alwaysAvailable) @@ -459,7 +460,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { e.preventDefault() // Prevent blur vscode.postMessage({ type: "openFile", - text: "./.roomodes", + text: `./${AGENT_MODES_FILE_NAME}`, values: { create: true, content: JSON.stringify({ customModes: [] }, null, 2), @@ -819,7 +820,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { // Open or create an empty file vscode.postMessage({ type: "openFile", - text: `./.roo/rules-${currentMode.slug}/rules.md`, + text: `./${AGENT_RULES_DIR}/rules-${currentMode.slug}/rules.md`, values: { create: true, content: "", @@ -901,7 +902,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { vscode.postMessage({ type: "openFile", - text: `./.roo/system-prompt-${currentMode.slug}`, + text: `./${AGENT_RULES_DIR}/system-prompt-${currentMode.slug}`, values: { create: true, content: "", @@ -956,7 +957,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { onClick={() => vscode.postMessage({ type: "openFile", - text: "./.roo/rules/rules.md", + text: `./${AGENT_RULES_DIR}/rules/rules.md`, values: { create: true, content: "", diff --git a/webview-ui/src/components/settings/ContextManagementSettings.tsx b/webview-ui/src/components/settings/ContextManagementSettings.tsx index 0f24316a12e..91f7d6913b8 100644 --- a/webview-ui/src/components/settings/ContextManagementSettings.tsx +++ b/webview-ui/src/components/settings/ContextManagementSettings.tsx @@ -84,11 +84,11 @@ export const ContextManagementSettings = ({ onChange={(e: any) => setCachedStateField("showRooIgnoredFiles", e.target.checked)} data-testid="show-rooignored-files-checkbox">
- {t("settings:contextManagement.rooignore.description")} + {t("settings:contextManagement.pearai-agent-ignore.description")}
diff --git a/webview-ui/src/components/settings/__tests__/ContextManagementSettings.test.tsx b/webview-ui/src/components/settings/__tests__/ContextManagementSettings.test.tsx index 955ce619369..2de704d9fff 100644 --- a/webview-ui/src/components/settings/__tests__/ContextManagementSettings.test.tsx +++ b/webview-ui/src/components/settings/__tests__/ContextManagementSettings.test.tsx @@ -47,7 +47,7 @@ describe("ContextManagementSettings", () => { const workspaceFilesSlider = screen.getByTestId("workspace-files-limit-slider") expect(workspaceFilesSlider).toBeInTheDocument() - // Show .rooignore'd files + // Show .pearai-agent-ignore'd files const showRooIgnoredFilesCheckbox = screen.getByTestId("show-rooignored-files-checkbox") expect(showRooIgnoredFilesCheckbox).toBeInTheDocument() expect(screen.getByTestId("show-rooignored-files-checkbox")).not.toBeChecked() diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index d0aab2d4529..6deabbd23e7 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -181,7 +181,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode cwd: "", browserToolEnabled: true, telemetrySetting: "unset", - showRooIgnoredFiles: true, // Default to showing .rooignore'd files with lock symbol (current behavior). + showRooIgnoredFiles: true, // Default to showing .pearai-agent-ignore'd files with lock symbol (current behavior). renderContext: "sidebar", maxReadFileLine: 500, // Default max read file line limit pinnedApiConfigs: {}, // Empty object for pinned API configs diff --git a/webview-ui/src/i18n/locales/ca/prompts.json b/webview-ui/src/i18n/locales/ca/prompts.json index d37e8629425..0a1ffc1425f 100644 --- a/webview-ui/src/i18n/locales/ca/prompts.json +++ b/webview-ui/src/i18n/locales/ca/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Crear nou mode", "editModesConfig": "Editar configuració de modes", "editGlobalModes": "Editar modes globals", - "editProjectModes": "Editar modes de projecte (.roomodes)", + "editProjectModes": "Editar modes de projecte (.pearai-agent-ignore)", "createModeHelpText": "Feu clic a + per crear un nou mode personalitzat, o simplement demaneu a Roo al xat que en creï un per a vostè!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Instruccions personalitzades específiques del mode (opcional)", "resetToDefault": "Restablir a valors predeterminats", "description": "Afegiu directrius de comportament específiques per al mode {{modeName}}.", - "loadFromFile": "Les instruccions personalitzades específiques per al mode {{mode}} també es poden carregar des de la carpeta .roo/rules-{{slug}}/ al vostre espai de treball (.roorules-{{slug}} i .clinerules-{{slug}} estan obsolets i deixaran de funcionar aviat)." + "loadFromFile": "Les instruccions personalitzades específiques per al mode {{mode}} també es poden carregar des de la carpeta .pearai-agent/rules-{{slug}}/ al vostre espai de treball (.roorules-{{slug}} i .clinerules-{{slug}} estan obsolets i deixaran de funcionar aviat)." }, "globalCustomInstructions": { "title": "Instruccions personalitzades per a tots els modes", "description": "Aquestes instruccions s'apliquen a tots els modes. Proporcionen un conjunt bàsic de comportaments que es poden millorar amb instruccions específiques de cada mode a continuació.\nSi voleu que Roo pensi i parli en un idioma diferent al de la visualització del vostre editor ({{language}}), podeu especificar-ho aquí.", - "loadFromFile": "Les instruccions també es poden carregar des de la carpeta .roo/rules/ al vostre espai de treball (.roorules i .clinerules estan obsolets i deixaran de funcionar aviat)." + "loadFromFile": "Les instruccions també es poden carregar des de la carpeta .pearai-agent/rules/ al vostre espai de treball (.roorules i .clinerules estan obsolets i deixaran de funcionar aviat)." }, "systemPrompt": { "preview": "Previsualització del prompt del sistema", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Avançat: Sobreescriure prompt del sistema", - "description": "Podeu reemplaçar completament el prompt del sistema per a aquest mode (a part de la definició de rol i instruccions personalitzades) creant un fitxer a .roo/system-prompt-{{slug}} al vostre espai de treball. Aquesta és una funcionalitat molt avançada que eludeix les salvaguardes integrades i les comprovacions de consistència (especialment al voltant de l'ús d'eines), així que aneu amb compte!" + "description": "Podeu reemplaçar completament el prompt del sistema per a aquest mode (a part de la definició de rol i instruccions personalitzades) creant un fitxer a .pearai-agent/system-prompt-{{slug}} al vostre espai de treball. Aquesta és una funcionalitat molt avançada que eludeix les salvaguardes integrades i les comprovacions de consistència (especialment al voltant de l'ús d'eines), així que aneu amb compte!" }, "createModeDialog": { "title": "Crear nou mode", @@ -122,7 +122,7 @@ "description": "Disponible a tots els espais de treball" }, "project": { - "label": "Específic del projecte (.roomodes)", + "label": "Específic del projecte (.pearai-agent-ignore)", "description": "Només disponible en aquest espai de treball, té prioritat sobre el global" } }, diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index aa1c5178327..c8d8361f1f7 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -298,9 +298,9 @@ "label": "Límit de context de fitxers de l'espai de treball", "description": "Nombre màxim de fitxers a incloure als detalls del directori de treball actual. Valors més alts proporcionen més context però augmenten l'ús de token." }, - "rooignore": { - "label": "Mostrar fitxers .rooignore en llistes i cerques", - "description": "Quan està habilitat, els fitxers que coincideixen amb els patrons a .rooignore es mostraran en llistes amb un símbol de cadenat. Quan està deshabilitat, aquests fitxers s'ocultaran completament de les llistes de fitxers i cerques." + "pearai-agent-ignore": { + "label": "Mostrar fitxers .pearai-agent-ignore en llistes i cerques", + "description": "Quan està habilitat, els fitxers que coincideixen amb els patrons a .pearai-agent-ignore es mostraran en llistes amb un símbol de cadenat. Quan està deshabilitat, aquests fitxers s'ocultaran completament de les llistes de fitxers i cerques." }, "maxReadFile": { "label": "Llindar d'auto-truncament de lectura de fitxers", diff --git a/webview-ui/src/i18n/locales/de/prompts.json b/webview-ui/src/i18n/locales/de/prompts.json index 7d0a19ec470..df67f25aee5 100644 --- a/webview-ui/src/i18n/locales/de/prompts.json +++ b/webview-ui/src/i18n/locales/de/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Neuen Modus erstellen", "editModesConfig": "Moduskonfiguration bearbeiten", "editGlobalModes": "Globale Modi bearbeiten", - "editProjectModes": "Projektmodi bearbeiten (.roomodes)", + "editProjectModes": "Projektmodi bearbeiten (.pearai-agent-ignore)", "createModeHelpText": "Klicke auf +, um einen neuen benutzerdefinierten Modus zu erstellen, oder bitte Roo einfach im Chat, einen für dich zu erstellen!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Modusspezifische benutzerdefinierte Anweisungen (optional)", "resetToDefault": "Auf Standardwerte zurücksetzen", "description": "Fügen Sie verhaltensspezifische Richtlinien für den Modus {{modeName}} hinzu.", - "loadFromFile": "Benutzerdefinierte Anweisungen für den Modus {{mode}} können auch aus dem Ordner .roo/rules-{{slug}}/ in deinem Arbeitsbereich geladen werden (.roorules-{{slug}} und .clinerules-{{slug}} sind veraltet und werden bald nicht mehr funktionieren)." + "loadFromFile": "Benutzerdefinierte Anweisungen für den Modus {{mode}} können auch aus dem Ordner .pearai-agent/rules-{{slug}}/ in deinem Arbeitsbereich geladen werden (.roorules-{{slug}} und .clinerules-{{slug}} sind veraltet und werden bald nicht mehr funktionieren)." }, "globalCustomInstructions": { "title": "Benutzerdefinierte Anweisungen für alle Modi", "description": "Diese Anweisungen gelten für alle Modi. Sie bieten einen grundlegenden Satz von Verhaltensweisen, die durch modusspezifische Anweisungen unten erweitert werden können.\nWenn du möchtest, dass Roo in einer anderen Sprache als deiner Editor-Anzeigesprache ({{language}}) denkt und spricht, kannst du das hier angeben.", - "loadFromFile": "Anweisungen können auch aus dem Ordner .roo/rules/ in deinem Arbeitsbereich geladen werden (.roorules und .clinerules sind veraltet und werden bald nicht mehr funktionieren)." + "loadFromFile": "Anweisungen können auch aus dem Ordner .pearai-agent/rules/ in deinem Arbeitsbereich geladen werden (.roorules und .clinerules sind veraltet und werden bald nicht mehr funktionieren)." }, "systemPrompt": { "preview": "System-Prompt Vorschau", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Erweitert: System-Prompt überschreiben", - "description": "Du kannst den System-Prompt für diesen Modus vollständig ersetzen (abgesehen von der Rollendefinition und benutzerdefinierten Anweisungen), indem du eine Datei unter .roo/system-prompt-{{slug}} in deinem Arbeitsbereich erstellst. Dies ist eine sehr fortgeschrittene Funktion, die eingebaute Schutzmaßnahmen und Konsistenzprüfungen umgeht (besonders bei der Werkzeugnutzung), also sei vorsichtig!" + "description": "Du kannst den System-Prompt für diesen Modus vollständig ersetzen (abgesehen von der Rollendefinition und benutzerdefinierten Anweisungen), indem du eine Datei unter .pearai-agent/system-prompt-{{slug}} in deinem Arbeitsbereich erstellst. Dies ist eine sehr fortgeschrittene Funktion, die eingebaute Schutzmaßnahmen und Konsistenzprüfungen umgeht (besonders bei der Werkzeugnutzung), also sei vorsichtig!" }, "createModeDialog": { "title": "Neuen Modus erstellen", @@ -122,7 +122,7 @@ "description": "Verfügbar in allen Arbeitsbereichen" }, "project": { - "label": "Projektspezifisch (.roomodes)", + "label": "Projektspezifisch (.pearai-agent-ignore)", "description": "Nur in diesem Arbeitsbereich verfügbar, hat Vorrang vor global" } }, diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 4cc23c4bab9..f0435b1a61f 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -298,9 +298,9 @@ "label": "Workspace-Dateien Kontextlimit", "description": "Maximale Anzahl von Dateien, die in den Details des aktuellen Arbeitsverzeichnisses enthalten sein sollen. Höhere Werte bieten mehr Kontext, erhöhen aber den Token-Verbrauch." }, - "rooignore": { - "label": ".rooignore-Dateien in Listen und Suchen anzeigen", - "description": "Wenn aktiviert, werden Dateien, die mit Mustern in .rooignore übereinstimmen, in Listen mit einem Schlosssymbol angezeigt. Wenn deaktiviert, werden diese Dateien vollständig aus Dateilisten und Suchen ausgeblendet." + "pearai-agent-ignore": { + "label": ".pearai-agent-ignore-Dateien in Listen und Suchen anzeigen", + "description": "Wenn aktiviert, werden Dateien, die mit Mustern in .pearai-agent-ignore übereinstimmen, in Listen mit einem Schlosssymbol angezeigt. Wenn deaktiviert, werden diese Dateien vollständig aus Dateilisten und Suchen ausgeblendet." }, "maxReadFile": { "label": "Schwellenwert für automatische Dateilesekürzung", diff --git a/webview-ui/src/i18n/locales/en/prompts.json b/webview-ui/src/i18n/locales/en/prompts.json index ce567a48697..8b603c77c50 100644 --- a/webview-ui/src/i18n/locales/en/prompts.json +++ b/webview-ui/src/i18n/locales/en/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Create new mode", "editModesConfig": "Edit modes configuration", "editGlobalModes": "Edit Global Modes", - "editProjectModes": "Edit Project Modes (.roomodes)", + "editProjectModes": "Edit Project Modes (.pearai-agent-ignore)", "createModeHelpText": "Hit the + to create a new custom mode, or just ask Roo in chat to create one for you!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Mode-specific Custom Instructions (optional)", "resetToDefault": "Reset to default", "description": "Add behavioral guidelines specific to {{modeName}} mode.", - "loadFromFile": "Custom instructions specific to {{mode}} mode can also be loaded from the .roo/rules-{{slug}}/ folder in your workspace (.roorules-{{slug}} and .clinerules-{{slug}} are deprecated and will stop working soon)." + "loadFromFile": "Custom instructions specific to {{mode}} mode can also be loaded from the .pearai-agent/rules-{{slug}}/ folder in your workspace (.roorules-{{slug}} and .clinerules-{{slug}} are deprecated and will stop working soon)." }, "globalCustomInstructions": { "title": "Custom Instructions for All Modes", "description": "These instructions apply to all modes. They provide a base set of behaviors that can be enhanced by mode-specific instructions below.\nIf you would like Roo to think and speak in a different language than your editor display language ({{language}}), you can specify it here.", - "loadFromFile": "Instructions can also be loaded from the .roo/rules/ folder in your workspace (.roorules and .clinerules are deprecated and will stop working soon)." + "loadFromFile": "Instructions can also be loaded from the .pearai-agent/rules/ folder in your workspace (.roorules and .clinerules are deprecated and will stop working soon)." }, "systemPrompt": { "preview": "Preview System Prompt", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Advanced: Override System Prompt", - "description": "You can completely replace the system prompt for this mode (aside from the role definition and custom instructions) by creating a file at .roo/system-prompt-{{slug}} in your workspace. This is a very advanced feature that bypasses built-in safeguards and consistency checks (especially around tool usage), so be careful!" + "description": "You can completely replace the system prompt for this mode (aside from the role definition and custom instructions) by creating a file at .pearai-agent/system-prompt-{{slug}} in your workspace. This is a very advanced feature that bypasses built-in safeguards and consistency checks (especially around tool usage), so be careful!" }, "createModeDialog": { "title": "Create New Mode", @@ -122,7 +122,7 @@ "description": "Available in all workspaces" }, "project": { - "label": "Project-specific (.roomodes)", + "label": "Project-specific (.pearai-agent-ignore)", "description": "Only available in this workspace, takes precedence over global" } }, diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index c06a9774116..35f1c4bcb54 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -298,9 +298,9 @@ "label": "Workspace files context limit", "description": "Maximum number of files to include in current working directory details. Higher values provide more context but increase token usage." }, - "rooignore": { - "label": "Show .rooignore'd files in lists and searches", - "description": "When enabled, files matching patterns in .rooignore will be shown in lists with a lock symbol. When disabled, these files will be completely hidden from file lists and searches." + "pearai-agent-ignore": { + "label": "Show .pearai-agent-ignore'd files in lists and searches", + "description": "When enabled, files matching patterns in .pearai-agent-ignore will be shown in lists with a lock symbol. When disabled, these files will be completely hidden from file lists and searches." }, "maxReadFile": { "label": "File read auto-truncate threshold", diff --git a/webview-ui/src/i18n/locales/es/prompts.json b/webview-ui/src/i18n/locales/es/prompts.json index 3c6b0526393..a34f97b0deb 100644 --- a/webview-ui/src/i18n/locales/es/prompts.json +++ b/webview-ui/src/i18n/locales/es/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Crear nuevo modo", "editModesConfig": "Editar configuración de modos", "editGlobalModes": "Editar modos globales", - "editProjectModes": "Editar modos del proyecto (.roomodes)", + "editProjectModes": "Editar modos del proyecto (.pearai-agent-ignore)", "createModeHelpText": "¡Haz clic en + para crear un nuevo modo personalizado, o simplemente pídele a Roo en el chat que te cree uno!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Instrucciones personalizadas para el modo (opcional)", "resetToDefault": "Restablecer a valores predeterminados", "description": "Agrega directrices de comportamiento específicas para el modo {{modeName}}.", - "loadFromFile": "Las instrucciones personalizadas para el modo {{mode}} también se pueden cargar desde la carpeta .roo/rules-{{slug}}/ en tu espacio de trabajo (.roorules-{{slug}} y .clinerules-{{slug}} están obsoletos y dejarán de funcionar pronto)." + "loadFromFile": "Las instrucciones personalizadas para el modo {{mode}} también se pueden cargar desde la carpeta .pearai-agent/rules-{{slug}}/ en tu espacio de trabajo (.roorules-{{slug}} y .clinerules-{{slug}} están obsoletos y dejarán de funcionar pronto)." }, "globalCustomInstructions": { "title": "Instrucciones personalizadas para todos los modos", "description": "Estas instrucciones se aplican a todos los modos. Proporcionan un conjunto base de comportamientos que pueden ser mejorados por instrucciones específicas de cada modo.\nSi quieres que Roo piense y hable en un idioma diferente al idioma de visualización de tu editor ({{language}}), puedes especificarlo aquí.", - "loadFromFile": "Las instrucciones también se pueden cargar desde la carpeta .roo/rules/ en tu espacio de trabajo (.roorules y .clinerules están obsoletos y dejarán de funcionar pronto)." + "loadFromFile": "Las instrucciones también se pueden cargar desde la carpeta .pearai-agent/rules/ en tu espacio de trabajo (.roorules y .clinerules están obsoletos y dejarán de funcionar pronto)." }, "systemPrompt": { "preview": "Vista previa de la solicitud del sistema", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Avanzado: Anular solicitud del sistema", - "description": "Puedes reemplazar completamente la solicitud del sistema para este modo (aparte de la definición de rol e instrucciones personalizadas) creando un archivo en .roo/system-prompt-{{slug}} en tu espacio de trabajo. ¡Esta es una función muy avanzada que omite las salvaguardas integradas y las verificaciones de consistencia (especialmente en torno al uso de herramientas), así que ten cuidado!" + "description": "Puedes reemplazar completamente la solicitud del sistema para este modo (aparte de la definición de rol e instrucciones personalizadas) creando un archivo en .pearai-agent/system-prompt-{{slug}} en tu espacio de trabajo. ¡Esta es una función muy avanzada que omite las salvaguardas integradas y las verificaciones de consistencia (especialmente en torno al uso de herramientas), así que ten cuidado!" }, "createModeDialog": { "title": "Crear nuevo modo", @@ -122,7 +122,7 @@ "description": "Disponible en todos los espacios de trabajo" }, "project": { - "label": "Específico del proyecto (.roomodes)", + "label": "Específico del proyecto (.pearai-agent-ignore)", "description": "Solo disponible en este espacio de trabajo, tiene prioridad sobre el global" } }, diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 0dd75d95820..827c8ebacba 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -298,9 +298,9 @@ "label": "Límite de contexto de archivos del espacio de trabajo", "description": "Número máximo de archivos a incluir en los detalles del directorio de trabajo actual. Valores más altos proporcionan más contexto pero aumentan el uso de token." }, - "rooignore": { - "label": "Mostrar archivos .rooignore en listas y búsquedas", - "description": "Cuando está habilitado, los archivos que coinciden con los patrones en .rooignore se mostrarán en listas con un símbolo de candado. Cuando está deshabilitado, estos archivos se ocultarán completamente de las listas de archivos y búsquedas." + "pearai-agent-ignore": { + "label": "Mostrar archivos .pearai-agent-ignore en listas y búsquedas", + "description": "Cuando está habilitado, los archivos que coinciden con los patrones en .pearai-agent-ignore se mostrarán en listas con un símbolo de candado. Cuando está deshabilitado, estos archivos se ocultarán completamente de las listas de archivos y búsquedas." }, "maxReadFile": { "label": "Umbral de auto-truncado de lectura de archivos", diff --git a/webview-ui/src/i18n/locales/fr/prompts.json b/webview-ui/src/i18n/locales/fr/prompts.json index b746bd83117..72b86999bc3 100644 --- a/webview-ui/src/i18n/locales/fr/prompts.json +++ b/webview-ui/src/i18n/locales/fr/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Créer un nouveau mode", "editModesConfig": "Modifier la configuration des modes", "editGlobalModes": "Modifier les modes globaux", - "editProjectModes": "Modifier les modes du projet (.roomodes)", + "editProjectModes": "Modifier les modes du projet (.pearai-agent-ignore)", "createModeHelpText": "Cliquez sur + pour créer un nouveau mode personnalisé, ou demandez simplement à Roo dans le chat de vous en créer un !" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Instructions personnalisées spécifiques au mode (optionnel)", "resetToDefault": "Réinitialiser aux valeurs par défaut", "description": "Ajoutez des directives comportementales spécifiques au mode {{modeName}}.", - "loadFromFile": "Les instructions personnalisées spécifiques au mode {{mode}} peuvent également être chargées depuis le dossier .roo/rules-{{slug}}/ dans votre espace de travail (.roorules-{{slug}} et .clinerules-{{slug}} sont obsolètes et cesseront de fonctionner bientôt)." + "loadFromFile": "Les instructions personnalisées spécifiques au mode {{mode}} peuvent également être chargées depuis le dossier .pearai-agent/rules-{{slug}}/ dans votre espace de travail (.roorules-{{slug}} et .clinerules-{{slug}} sont obsolètes et cesseront de fonctionner bientôt)." }, "globalCustomInstructions": { "title": "Instructions personnalisées pour tous les modes", "description": "Ces instructions s'appliquent à tous les modes. Elles fournissent un ensemble de comportements de base qui peuvent être améliorés par des instructions spécifiques au mode ci-dessous.\nSi vous souhaitez que Roo pense et parle dans une langue différente de celle de votre éditeur ({{language}}), vous pouvez le spécifier ici.", - "loadFromFile": "Les instructions peuvent également être chargées depuis le dossier .roo/rules/ dans votre espace de travail (.roorules et .clinerules sont obsolètes et cesseront de fonctionner bientôt)." + "loadFromFile": "Les instructions peuvent également être chargées depuis le dossier .pearai-agent/rules/ dans votre espace de travail (.roorules et .clinerules sont obsolètes et cesseront de fonctionner bientôt)." }, "systemPrompt": { "preview": "Aperçu du prompt système", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Avancé : Remplacer le prompt système", - "description": "Vous pouvez complètement remplacer le prompt système pour ce mode (en dehors de la définition du rôle et des instructions personnalisées) en créant un fichier à .roo/system-prompt-{{slug}} dans votre espace de travail. Il s'agit d'une fonctionnalité très avancée qui contourne les garanties intégrées et les vérifications de cohérence (notamment concernant l'utilisation des outils), alors soyez prudent !" + "description": "Vous pouvez complètement remplacer le prompt système pour ce mode (en dehors de la définition du rôle et des instructions personnalisées) en créant un fichier à .pearai-agent/system-prompt-{{slug}} dans votre espace de travail. Il s'agit d'une fonctionnalité très avancée qui contourne les garanties intégrées et les vérifications de cohérence (notamment concernant l'utilisation des outils), alors soyez prudent !" }, "createModeDialog": { "title": "Créer un nouveau mode", @@ -122,7 +122,7 @@ "description": "Disponible dans tous les espaces de travail" }, "project": { - "label": "Spécifique au projet (.roomodes)", + "label": "Spécifique au projet (.pearai-agent-ignore)", "description": "Disponible uniquement dans cet espace de travail, a priorité sur le global" } }, diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index ec921ca41e1..5266698d9c7 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -298,9 +298,9 @@ "label": "Limite de contexte des fichiers de l'espace de travail", "description": "Nombre maximum de fichiers à inclure dans les détails du répertoire de travail actuel. Des valeurs plus élevées fournissent plus de contexte mais augmentent l'utilisation de token." }, - "rooignore": { - "label": "Afficher les fichiers .rooignore dans les listes et recherches", - "description": "Lorsque cette option est activée, les fichiers correspondant aux modèles dans .rooignore seront affichés dans les listes avec un symbole de cadenas. Lorsqu'elle est désactivée, ces fichiers seront complètement masqués des listes de fichiers et des recherches." + "pearai-agent-ignore": { + "label": "Afficher les fichiers .pearai-agent-ignore dans les listes et recherches", + "description": "Lorsque cette option est activée, les fichiers correspondant aux modèles dans .pearai-agent-ignore seront affichés dans les listes avec un symbole de cadenas. Lorsqu'elle est désactivée, ces fichiers seront complètement masqués des listes de fichiers et des recherches." }, "maxReadFile": { "label": "Seuil d'auto-troncature de lecture de fichier", diff --git a/webview-ui/src/i18n/locales/hi/prompts.json b/webview-ui/src/i18n/locales/hi/prompts.json index d5291a577c7..83092ae6a6a 100644 --- a/webview-ui/src/i18n/locales/hi/prompts.json +++ b/webview-ui/src/i18n/locales/hi/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "नया मोड बनाएँ", "editModesConfig": "मोड कॉन्फ़िगरेशन संपादित करें", "editGlobalModes": "ग्लोबल मोड्स संपादित करें", - "editProjectModes": "प्रोजेक्ट मोड्स संपादित करें (.roomodes)", + "editProjectModes": "प्रोजेक्ट मोड्स संपादित करें (.pearai-agent-ignore)", "createModeHelpText": "नया कस्टम मोड बनाने के लिए + पर क्लिक करें, या बस चैट में Roo से आपके लिए एक बनाने को कहें!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "मोड-विशिष्ट कस्टम निर्देश (वैकल्पिक)", "resetToDefault": "डिफ़ॉल्ट पर रीसेट करें", "description": "{{modeName}} मोड के लिए विशिष्ट व्यवहार दिशानिर्देश जोड़ें।", - "loadFromFile": "{{mode}} मोड के लिए विशिष्ट कस्टम निर्देश आपके वर्कस्पेस में .roo/rules-{{slug}}/ फ़ोल्डर से भी लोड किए जा सकते हैं (.roorules-{{slug}} और .clinerules-{{slug}} पुराने हो गए हैं और जल्द ही काम करना बंद कर देंगे)।" + "loadFromFile": "{{mode}} मोड के लिए विशिष्ट कस्टम निर्देश आपके वर्कस्पेस में .pearai-agent/rules-{{slug}}/ फ़ोल्डर से भी लोड किए जा सकते हैं (.roorules-{{slug}} और .clinerules-{{slug}} पुराने हो गए हैं और जल्द ही काम करना बंद कर देंगे)।" }, "globalCustomInstructions": { "title": "सभी मोड्स के लिए कस्टम निर्देश", "description": "ये निर्देश सभी मोड्स पर लागू होते हैं। वे व्यवहारों का एक आधार सेट प्रदान करते हैं जिन्हें नीचे दिए गए मोड-विशिष्ट निर्देशों द्वारा बढ़ाया जा सकता है।\nयदि आप चाहते हैं कि Roo आपके एडिटर की प्रदर्शन भाषा ({{language}}) से अलग भाषा में सोचे और बोले, तो आप यहां इसे निर्दिष्ट कर सकते हैं।", - "loadFromFile": "निर्देश आपके वर्कस्पेस में .roo/rules/ फ़ोल्डर से भी लोड किए जा सकते हैं (.roorules और .clinerules पुराने हो गए हैं और जल्द ही काम करना बंद कर देंगे)।" + "loadFromFile": "निर्देश आपके वर्कस्पेस में .pearai-agent/rules/ फ़ोल्डर से भी लोड किए जा सकते हैं (.roorules और .clinerules पुराने हो गए हैं और जल्द ही काम करना बंद कर देंगे)।" }, "systemPrompt": { "preview": "सिस्टम प्रॉम्प्ट का पूर्वावलोकन", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "उन्नत: सिस्टम प्रॉम्प्ट ओवरराइड करें", - "description": "आप अपने वर्कस्पेस में .roo/system-prompt-{{slug}} पर एक फाइल बनाकर इस मोड के लिए सिस्टम प्रॉम्प्ट को पूरी तरह से बदल सकते हैं (भूमिका परिभाषा और कस्टम निर्देशों को छोड़कर)। यह एक बहुत उन्नत सुविधा है जो अंतर्निहित सुरक्षा उपायों और सामंजस्यता जांचों को बायपास करती है (विशेष रूप से टूल उपयोग के आसपास), इसलिए सावधान रहें!" + "description": "आप अपने वर्कस्पेस में .pearai-agent/system-prompt-{{slug}} पर एक फाइल बनाकर इस मोड के लिए सिस्टम प्रॉम्प्ट को पूरी तरह से बदल सकते हैं (भूमिका परिभाषा और कस्टम निर्देशों को छोड़कर)। यह एक बहुत उन्नत सुविधा है जो अंतर्निहित सुरक्षा उपायों और सामंजस्यता जांचों को बायपास करती है (विशेष रूप से टूल उपयोग के आसपास), इसलिए सावधान रहें!" }, "createModeDialog": { "title": "नया मोड बनाएँ", @@ -122,7 +122,7 @@ "description": "सभी वर्कस्पेस में उपलब्ध" }, "project": { - "label": "प्रोजेक्ट-विशिष्ट (.roomodes)", + "label": "प्रोजेक्ट-विशिष्ट (.pearai-agent-ignore)", "description": "केवल इस वर्कस्पेस में उपलब्ध, ग्लोबल पर प्राथमिकता रखता है" } }, diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index b98879eb37a..489cb5e5d30 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -298,9 +298,9 @@ "label": "वर्कस्पेस फाइल संदर्भ सीमा", "description": "वर्तमान कार्य निर्देशिका विवरण में शामिल करने के लिए फाइलों की अधिकतम संख्या। उच्च मान अधिक संदर्भ प्रदान करते हैं लेकिन token उपयोग बढ़ाते हैं।" }, - "rooignore": { - "label": "सूचियों और खोजों में .rooignore फाइलें दिखाएँ", - "description": "जब सक्षम होता है, .rooignore में पैटर्न से मेल खाने वाली फाइलें लॉक प्रतीक के साथ सूचियों में दिखाई जाएंगी। जब अक्षम होता है, ये फाइलें फाइल सूचियों और खोजों से पूरी तरह छिपा दी जाएंगी।" + "pearai-agent-ignore": { + "label": "सूचियों और खोजों में .pearai-agent-ignore फाइलें दिखाएँ", + "description": "जब सक्षम होता है, .pearai-agent-ignore में पैटर्न से मेल खाने वाली फाइलें लॉक प्रतीक के साथ सूचियों में दिखाई जाएंगी। जब अक्षम होता है, ये फाइलें फाइल सूचियों और खोजों से पूरी तरह छिपा दी जाएंगी।" }, "maxReadFile": { "label": "फ़ाइल पढ़ने का स्वचालित काटने की सीमा", diff --git a/webview-ui/src/i18n/locales/it/prompts.json b/webview-ui/src/i18n/locales/it/prompts.json index 81bb7534def..d9e4ce12966 100644 --- a/webview-ui/src/i18n/locales/it/prompts.json +++ b/webview-ui/src/i18n/locales/it/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Crea nuova modalità", "editModesConfig": "Modifica configurazione modalità", "editGlobalModes": "Modifica modalità globali", - "editProjectModes": "Modifica modalità di progetto (.roomodes)", + "editProjectModes": "Modifica modalità di progetto (.pearai-agent-ignore)", "createModeHelpText": "Clicca sul + per creare una nuova modalità personalizzata, o chiedi semplicemente a Roo nella chat di crearne una per te!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Istruzioni personalizzate specifiche per la modalità (opzionale)", "resetToDefault": "Ripristina predefiniti", "description": "Aggiungi linee guida comportamentali specifiche per la modalità {{modeName}}.", - "loadFromFile": "Le istruzioni personalizzate specifiche per la modalità {{mode}} possono essere caricate anche dalla cartella .roo/rules-{{slug}}/ nel tuo spazio di lavoro (.roorules-{{slug}} e .clinerules-{{slug}} sono obsoleti e smetteranno di funzionare presto)." + "loadFromFile": "Le istruzioni personalizzate specifiche per la modalità {{mode}} possono essere caricate anche dalla cartella .pearai-agent/rules-{{slug}}/ nel tuo spazio di lavoro (.roorules-{{slug}} e .clinerules-{{slug}} sono obsoleti e smetteranno di funzionare presto)." }, "globalCustomInstructions": { "title": "Istruzioni personalizzate per tutte le modalità", "description": "Queste istruzioni si applicano a tutte le modalità. Forniscono un insieme base di comportamenti che possono essere migliorati dalle istruzioni specifiche per modalità qui sotto.\nSe desideri che Roo pensi e parli in una lingua diversa dalla lingua di visualizzazione del tuo editor ({{language}}), puoi specificarlo qui.", - "loadFromFile": "Le istruzioni possono essere caricate anche dalla cartella .roo/rules/ nel tuo spazio di lavoro (.roorules e .clinerules sono obsoleti e smetteranno di funzionare presto)." + "loadFromFile": "Le istruzioni possono essere caricate anche dalla cartella .pearai-agent/rules/ nel tuo spazio di lavoro (.roorules e .clinerules sono obsoleti e smetteranno di funzionare presto)." }, "systemPrompt": { "preview": "Anteprima prompt di sistema", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Avanzato: Sovrascrivi prompt di sistema", - "description": "Puoi sostituire completamente il prompt di sistema per questa modalità (a parte la definizione del ruolo e le istruzioni personalizzate) creando un file in .roo/system-prompt-{{slug}} nel tuo spazio di lavoro. Questa è una funzionalità molto avanzata che bypassa le protezioni integrate e i controlli di coerenza (specialmente riguardo all'uso degli strumenti), quindi fai attenzione!" + "description": "Puoi sostituire completamente il prompt di sistema per questa modalità (a parte la definizione del ruolo e le istruzioni personalizzate) creando un file in .pearai-agent/system-prompt-{{slug}} nel tuo spazio di lavoro. Questa è una funzionalità molto avanzata che bypassa le protezioni integrate e i controlli di coerenza (specialmente riguardo all'uso degli strumenti), quindi fai attenzione!" }, "createModeDialog": { "title": "Crea nuova modalità", @@ -122,7 +122,7 @@ "description": "Disponibile in tutti gli spazi di lavoro" }, "project": { - "label": "Specifico del progetto (.roomodes)", + "label": "Specifico del progetto (.pearai-agent-ignore)", "description": "Disponibile solo in questo spazio di lavoro, ha la precedenza sul globale" } }, diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index ca02aa92132..9ef742c0587 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -298,9 +298,9 @@ "label": "Limite contesto file area di lavoro", "description": "Numero massimo di file da includere nei dettagli della directory di lavoro corrente. Valori più alti forniscono più contesto ma aumentano l'utilizzo di token." }, - "rooignore": { - "label": "Mostra file .rooignore negli elenchi e nelle ricerche", - "description": "Quando abilitato, i file che corrispondono ai pattern in .rooignore verranno mostrati negli elenchi con un simbolo di blocco. Quando disabilitato, questi file saranno completamente nascosti dagli elenchi di file e dalle ricerche." + "pearai-agent-ignore": { + "label": "Mostra file .pearai-agent-ignore negli elenchi e nelle ricerche", + "description": "Quando abilitato, i file che corrispondono ai pattern in .pearai-agent-ignore verranno mostrati negli elenchi con un simbolo di blocco. Quando disabilitato, questi file saranno completamente nascosti dagli elenchi di file e dalle ricerche." }, "maxReadFile": { "label": "Soglia di auto-troncamento lettura file", diff --git a/webview-ui/src/i18n/locales/ja/prompts.json b/webview-ui/src/i18n/locales/ja/prompts.json index 16f30a2ebc5..48c2a030d02 100644 --- a/webview-ui/src/i18n/locales/ja/prompts.json +++ b/webview-ui/src/i18n/locales/ja/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "新しいモードを作成", "editModesConfig": "モード設定を編集", "editGlobalModes": "グローバルモードを編集", - "editProjectModes": "プロジェクトモードを編集 (.roomodes)", + "editProjectModes": "プロジェクトモードを編集 (.pearai-agent-ignore)", "createModeHelpText": "+ をクリックして新しいカスタムモードを作成するか、チャットで Roo に作成を依頼してください!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "モード固有のカスタム指示(オプション)", "resetToDefault": "デフォルトにリセット", "description": "{{modeName}}モードに特化した行動ガイドラインを追加します。", - "loadFromFile": "{{mode}}モード固有のカスタム指示は、ワークスペースの.roo/rules-{{slug}}/フォルダからも読み込めます(.roorules-{{slug}}と.clinerules-{{slug}}は非推奨であり、まもなく機能しなくなります)。" + "loadFromFile": "{{mode}}モード固有のカスタム指示は、ワークスペースの.pearai-agent/rules-{{slug}}/フォルダからも読み込めます(.roorules-{{slug}}と.clinerules-{{slug}}は非推奨であり、まもなく機能しなくなります)。" }, "globalCustomInstructions": { "title": "すべてのモードのカスタム指示", "description": "これらの指示はすべてのモードに適用されます。モード固有の指示で強化できる基本的な動作セットを提供します。\nRooにエディタの表示言語({{language}})とは異なる言語で考えたり話したりさせたい場合は、ここで指定できます。", - "loadFromFile": "指示はワークスペースの.roo/rules/フォルダからも読み込めます(.roorules と .clinerules は非推奨であり、まもなく機能しなくなります)。" + "loadFromFile": "指示はワークスペースの.pearai-agent/rules/フォルダからも読み込めます(.roorules と .clinerules は非推奨であり、まもなく機能しなくなります)。" }, "systemPrompt": { "preview": "システムプロンプトのプレビュー", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "詳細設定:システムプロンプトの上書き", - "description": "ワークスペースの.roo/system-prompt-{{slug}}にファイルを作成することで、このモードのシステムプロンプト(役割定義とカスタム指示以外)を完全に置き換えることができます。これは組み込みの安全対策と一貫性チェック(特にツールの使用に関して)をバイパスする非常に高度な機能なので、注意して使用してください!" + "description": "ワークスペースの.pearai-agent/system-prompt-{{slug}}にファイルを作成することで、このモードのシステムプロンプト(役割定義とカスタム指示以外)を完全に置き換えることができます。これは組み込みの安全対策と一貫性チェック(特にツールの使用に関して)をバイパスする非常に高度な機能なので、注意して使用してください!" }, "createModeDialog": { "title": "新しいモードを作成", @@ -122,7 +122,7 @@ "description": "すべてのワークスペースで利用可能" }, "project": { - "label": "プロジェクト固有 (.roomodes)", + "label": "プロジェクト固有 (.pearai-agent-ignore)", "description": "このワークスペースでのみ使用可能、グローバルよりも優先" } }, diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 0d49e9d1e95..210844ece6b 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -298,7 +298,7 @@ "label": "ワークスペースファイルコンテキスト制限", "description": "現在の作業ディレクトリの詳細に含めるファイルの最大数。高い値はより多くのコンテキストを提供しますが、token使用量が増加します。" }, - "rooignore": { + "pearai-agent-ignore": { "label": "リストと検索で.rooignoreファイルを表示", "description": "有効にすると、.rooignoreのパターンに一致するファイルがロックシンボル付きでリストに表示されます。無効にすると、これらのファイルはファイルリストや検索から完全に非表示になります。" }, diff --git a/webview-ui/src/i18n/locales/ko/prompts.json b/webview-ui/src/i18n/locales/ko/prompts.json index 5942105f055..3c20d6f7cdb 100644 --- a/webview-ui/src/i18n/locales/ko/prompts.json +++ b/webview-ui/src/i18n/locales/ko/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "새 모드 만들기", "editModesConfig": "모드 구성 편집", "editGlobalModes": "전역 모드 편집", - "editProjectModes": "프로젝트 모드 편집 (.roomodes)", + "editProjectModes": "프로젝트 모드 편집 (.pearai-agent-ignore)", "createModeHelpText": "새 커스텀 모드를 만들려면 + 버튼을 클릭하거나, 채팅에서 Roo에게 만들어달라고 요청하세요!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "모드별 사용자 지정 지침 (선택 사항)", "resetToDefault": "기본값으로 재설정", "description": "{{modeName}} 모드에 대한 특정 행동 지침을 추가하세요.", - "loadFromFile": "{{mode}} 모드에 대한 사용자 지정 지침은 작업 공간의 .roo/rules-{{slug}}/ 폴더에서도 로드할 수 있습니다(.roorules-{{slug}}와 .clinerules-{{slug}}는 더 이상 사용되지 않으며 곧 작동을 중단합니다)." + "loadFromFile": "{{mode}} 모드에 대한 사용자 지정 지침은 작업 공간의 .pearai-agent/rules-{{slug}}/ 폴더에서도 로드할 수 있습니다(.roorules-{{slug}}와 .clinerules-{{slug}}는 더 이상 사용되지 않으며 곧 작동을 중단합니다)." }, "globalCustomInstructions": { "title": "모든 모드에 대한 사용자 지정 지침", "description": "이 지침은 모든 모드에 적용됩니다. 아래의 모드별 지침으로 향상될 수 있는 기본 동작 세트를 제공합니다.\nRoo가 에디터 표시 언어({{language}})와 다른 언어로 생각하고 말하기를 원하시면, 여기에 지정할 수 있습니다.", - "loadFromFile": "지침은 작업 공간의 .roo/rules/ 폴더에서도 로드할 수 있습니다(.roorules와 .clinerules는 더 이상 사용되지 않으며 곧 작동을 중단합니다)." + "loadFromFile": "지침은 작업 공간의 .pearai-agent/rules/ 폴더에서도 로드할 수 있습니다(.roorules와 .clinerules는 더 이상 사용되지 않으며 곧 작동을 중단합니다)." }, "systemPrompt": { "preview": "시스템 프롬프트 미리보기", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "고급: 시스템 프롬프트 재정의", - "description": "작업 공간의 .roo/system-prompt-{{slug}}에 파일을 생성하여 이 모드의 시스템 프롬프트(역할 정의 및 사용자 지정 지침 제외)를 완전히 대체할 수 있습니다. 이는 내장된 안전 장치와 일관성 검사(특히 도구 사용 관련)를 우회하는 매우 고급 기능이므로 주의하세요!" + "description": "작업 공간의 .pearai-agent/system-prompt-{{slug}}에 파일을 생성하여 이 모드의 시스템 프롬프트(역할 정의 및 사용자 지정 지침 제외)를 완전히 대체할 수 있습니다. 이는 내장된 안전 장치와 일관성 검사(특히 도구 사용 관련)를 우회하는 매우 고급 기능이므로 주의하세요!" }, "createModeDialog": { "title": "새 모드 만들기", @@ -122,7 +122,7 @@ "description": "모든 작업 공간에서 사용 가능" }, "project": { - "label": "프로젝트별 (.roomodes)", + "label": "프로젝트별 (.pearai-agent-ignore)", "description": "이 작업 공간에서만 사용 가능, 전역보다 우선" } }, diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index d0b07988025..40c2e32f2eb 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -298,8 +298,8 @@ "label": "작업 공간 파일 컨텍스트 제한", "description": "현재 작업 디렉토리 세부 정보에 포함할 파일의 최대 수. 높은 값은 더 많은 컨텍스트를 제공하지만 token 사용량이 증가합니다." }, - "rooignore": { - "label": "목록 및 검색에서 .rooignore 파일 표시", + "pearai-agent-ignore": { + "label": "목록 및 검색에서 .pearai-agent-ignore 파일 표시", "description": "활성화되면 .rooignore의 패턴과 일치하는 파일이 잠금 기호와 함께 목록에 표시됩니다. 비활성화되면 이러한 파일은 파일 목록 및 검색에서 완전히 숨겨집니다." }, "maxReadFile": { diff --git a/webview-ui/src/i18n/locales/pl/prompts.json b/webview-ui/src/i18n/locales/pl/prompts.json index ef8a5ffe083..2782e91a4f9 100644 --- a/webview-ui/src/i18n/locales/pl/prompts.json +++ b/webview-ui/src/i18n/locales/pl/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Utwórz nowy tryb", "editModesConfig": "Edytuj konfigurację trybów", "editGlobalModes": "Edytuj tryby globalne", - "editProjectModes": "Edytuj tryby projektu (.roomodes)", + "editProjectModes": "Edytuj tryby projektu (.pearai-agent-ignore)", "createModeHelpText": "Kliknij +, aby utworzyć nowy niestandardowy tryb, lub po prostu poproś Roo w czacie, aby utworzył go dla Ciebie!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Niestandardowe instrukcje dla trybu (opcjonalne)", "resetToDefault": "Przywróć domyślne", "description": "Dodaj wytyczne dotyczące zachowania specyficzne dla trybu {{modeName}}.", - "loadFromFile": "Niestandardowe instrukcje dla trybu {{modeName}} mogą być również ładowane z folderu .roo/rules-{{modeSlug}}/ w Twoim obszarze roboczym (.roorules-{{modeSlug}} i .clinerules-{{modeSlug}} są przestarzałe i wkrótce przestaną działać)." + "loadFromFile": "Niestandardowe instrukcje dla trybu {{modeName}} mogą być również ładowane z folderu .pearai-agent/rules-{{modeSlug}}/ w Twoim obszarze roboczym (.roorules-{{modeSlug}} i .clinerules-{{modeSlug}} są przestarzałe i wkrótce przestaną działać)." }, "globalCustomInstructions": { "title": "Niestandardowe instrukcje dla wszystkich trybów", "description": "Te instrukcje dotyczą wszystkich trybów. Zapewniają podstawowy zestaw zachowań, które mogą być rozszerzone przez instrukcje specyficzne dla trybów poniżej.\nJeśli chcesz, aby Roo myślał i mówił w języku innym niż język wyświetlania Twojego edytora ({{language}}), możesz to określić tutaj.", - "loadFromFile": "Instrukcje mogą być również ładowane z folderu .roo/rules/ w Twoim obszarze roboczym (.roorules i .clinerules są przestarzałe i wkrótce przestaną działać)." + "loadFromFile": "Instrukcje mogą być również ładowane z folderu .pearai-agent/rules/ w Twoim obszarze roboczym (.roorules i .clinerules są przestarzałe i wkrótce przestaną działać)." }, "systemPrompt": { "preview": "Podgląd podpowiedzi systemowej", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Zaawansowane: Zastąp podpowiedź systemową", - "description": "Możesz całkowicie zastąpić podpowiedź systemową dla tego trybu (oprócz definicji roli i niestandardowych instrukcji) poprzez utworzenie pliku w .roo/system-prompt-{{modeSlug}} w swoim obszarze roboczym. Jest to bardzo zaawansowana funkcja, która omija wbudowane zabezpieczenia i kontrole spójności (szczególnie wokół używania narzędzi), więc bądź ostrożny!" + "description": "Możesz całkowicie zastąpić podpowiedź systemową dla tego trybu (oprócz definicji roli i niestandardowych instrukcji) poprzez utworzenie pliku w .pearai-agent/system-prompt-{{modeSlug}} w swoim obszarze roboczym. Jest to bardzo zaawansowana funkcja, która omija wbudowane zabezpieczenia i kontrole spójności (szczególnie wokół używania narzędzi), więc bądź ostrożny!" }, "createModeDialog": { "title": "Utwórz nowy tryb", @@ -122,7 +122,7 @@ "description": "Dostępny we wszystkich obszarach roboczych" }, "project": { - "label": "Specyficzny dla projektu (.roomodes)", + "label": "Specyficzny dla projektu (.pearai-agent-ignore)", "description": "Dostępny tylko w tym obszarze roboczym, ma pierwszeństwo przed globalnym" } }, diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index 60fe7c28153..4974cd7c8d0 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -298,9 +298,9 @@ "label": "Limit kontekstu plików obszaru roboczego", "description": "Maksymalna liczba plików do uwzględnienia w szczegółach bieżącego katalogu roboczego. Wyższe wartości zapewniają więcej kontekstu, ale zwiększają zużycie token." }, - "rooignore": { - "label": "Pokaż pliki .rooignore na listach i w wyszukiwaniach", - "description": "Gdy włączone, pliki pasujące do wzorców w .rooignore będą pokazywane na listach z symbolem kłódki. Gdy wyłączone, te pliki będą całkowicie ukryte z list plików i wyszukiwań." + "pearai-agent-ignore": { + "label": "Pokaż pliki .pearai-agent-ignore na listach i w wyszukiwaniach", + "description": "Gdy włączone, pliki pasujące do wzorców w .pearai-agent-ignore będą pokazywane na listach z symbolem kłódki. Gdy wyłączone, te pliki będą całkowicie ukryte z list plików i wyszukiwań." }, "maxReadFile": { "label": "Próg automatycznego skracania odczytu pliku", diff --git a/webview-ui/src/i18n/locales/pt-BR/prompts.json b/webview-ui/src/i18n/locales/pt-BR/prompts.json index f255b91a27d..b18b0fa0a70 100644 --- a/webview-ui/src/i18n/locales/pt-BR/prompts.json +++ b/webview-ui/src/i18n/locales/pt-BR/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Criar novo modo", "editModesConfig": "Editar configuração de modos", "editGlobalModes": "Editar modos globais", - "editProjectModes": "Editar modos do projeto (.roomodes)", + "editProjectModes": "Editar modos do projeto (.pearai-agent-ignore)", "createModeHelpText": "Clique em + para criar um novo modo personalizado, ou simplesmente peça ao Roo no chat para criar um para você!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Instruções personalizadas específicas do modo (opcional)", "resetToDefault": "Restaurar para padrão", "description": "Adicione diretrizes comportamentais específicas para o modo {{modeName}}.", - "loadFromFile": "Instruções personalizadas específicas para o modo {{modeName}} também podem ser carregadas da pasta .roo/rules-{{modeSlug}}/ no seu espaço de trabalho (.roorules-{{modeSlug}} e .clinerules-{{modeSlug}} estão obsoletos e deixarão de funcionar em breve)." + "loadFromFile": "Instruções personalizadas específicas para o modo {{modeName}} também podem ser carregadas da pasta .pearai-agent/rules-{{modeSlug}}/ no seu espaço de trabalho (.roorules-{{modeSlug}} e .clinerules-{{modeSlug}} estão obsoletos e deixarão de funcionar em breve)." }, "globalCustomInstructions": { "title": "Instruções personalizadas para todos os modos", "description": "Estas instruções se aplicam a todos os modos. Elas fornecem um conjunto base de comportamentos que podem ser aprimorados por instruções específicas do modo abaixo.\nSe você desejar que o Roo pense e fale em um idioma diferente do idioma de exibição do seu editor ({{language}}), você pode especificá-lo aqui.", - "loadFromFile": "As instruções também podem ser carregadas da pasta .roo/rules/ no seu espaço de trabalho (.roorules e .clinerules estão obsoletos e deixarão de funcionar em breve)." + "loadFromFile": "As instruções também podem ser carregadas da pasta .pearai-agent/rules/ no seu espaço de trabalho (.roorules e .clinerules estão obsoletos e deixarão de funcionar em breve)." }, "systemPrompt": { "preview": "Visualizar prompt do sistema", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Avançado: Substituir prompt do sistema", - "description": "Você pode substituir completamente o prompt do sistema para este modo (além da definição de função e instruções personalizadas) criando um arquivo em .roo/system-prompt-{{modeSlug}} no seu espaço de trabalho. Esta é uma funcionalidade muito avançada que contorna as salvaguardas integradas e verificações de consistência (especialmente em torno do uso de ferramentas), então tenha cuidado!" + "description": "Você pode substituir completamente o prompt do sistema para este modo (além da definição de função e instruções personalizadas) criando um arquivo em .pearai-agent/system-prompt-{{modeSlug}} no seu espaço de trabalho. Esta é uma funcionalidade muito avançada que contorna as salvaguardas integradas e verificações de consistência (especialmente em torno do uso de ferramentas), então tenha cuidado!" }, "createModeDialog": { "title": "Criar novo modo", @@ -122,7 +122,7 @@ "description": "Disponível em todos os espaços de trabalho" }, "project": { - "label": "Específico do projeto (.roomodes)", + "label": "Específico do projeto (.pearai-agent-ignore)", "description": "Disponível apenas neste espaço de trabalho, tem precedência sobre o global" } }, diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 5f229f98780..2fae2b4bf04 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -298,9 +298,9 @@ "label": "Limite de contexto de arquivos do espaço de trabalho", "description": "Número máximo de arquivos a incluir nos detalhes do diretório de trabalho atual. Valores mais altos fornecem mais contexto, mas aumentam o uso de token." }, - "rooignore": { - "label": "Mostrar arquivos .rooignore em listas e pesquisas", - "description": "Quando ativado, os arquivos que correspondem aos padrões em .rooignore serão mostrados em listas com um símbolo de cadeado. Quando desativado, esses arquivos serão completamente ocultos das listas de arquivos e pesquisas." + "pearai-agent-ignore": { + "label": "Mostrar arquivos .pearai-agent-ignore em listas e pesquisas", + "description": "Quando ativado, os arquivos que correspondem aos padrões em .pearai-agent-ignore serão mostrados em listas com um símbolo de cadeado. Quando desativado, esses arquivos serão completamente ocultos das listas de arquivos e pesquisas." }, "maxReadFile": { "label": "Limite de auto-truncamento de leitura de arquivo", diff --git a/webview-ui/src/i18n/locales/ru/prompts.json b/webview-ui/src/i18n/locales/ru/prompts.json index 0ff448bedbd..86058aca833 100644 --- a/webview-ui/src/i18n/locales/ru/prompts.json +++ b/webview-ui/src/i18n/locales/ru/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Создать новый режим", "editModesConfig": "Редактировать конфигурацию режимов", "editGlobalModes": "Редактировать глобальные режимы", - "editProjectModes": "Редактировать режимы проекта (.roomodes)", + "editProjectModes": "Редактировать режимы проекта (.pearai-agent-ignore)", "createModeHelpText": "Нажмите +, чтобы создать новый пользовательский режим, или просто попросите Roo в чате создать его для вас!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Пользовательские инструкции для режима (необязательно)", "resetToDefault": "Сбросить по умолчанию", "description": "Добавьте рекомендации по поведению, специфичные для режима {{modeName}}.", - "loadFromFile": "Пользовательские инструкции для режима {{mode}} также можно загрузить из папки .roo/rules-{{slug}}/ в вашем рабочем пространстве (.roorules-{{slug}} и .clinerules-{{slug}} устарели и скоро перестанут работать)." + "loadFromFile": "Пользовательские инструкции для режима {{mode}} также можно загрузить из папки .pearai-agent/rules-{{slug}}/ в вашем рабочем пространстве (.roorules-{{slug}} и .clinerules-{{slug}} устарели и скоро перестанут работать)." }, "globalCustomInstructions": { "title": "Пользовательские инструкции для всех режимов", "description": "Эти инструкции применяются ко всем режимам. Они задают базовое поведение, которое можно расширить с помощью инструкций ниже.\nЕсли вы хотите, чтобы Roo думал и говорил на другом языке, отличном от языка редактора ({{language}}), укажите это здесь.", - "loadFromFile": "Инструкции также можно загрузить из папки .roo/rules/ в вашем рабочем пространстве (.roorules и .clinerules устарели и скоро перестанут работать)." + "loadFromFile": "Инструкции также можно загрузить из папки .pearai-agent/rules/ в вашем рабочем пространстве (.roorules и .clinerules устарели и скоро перестанут работать)." }, "systemPrompt": { "preview": "Предпросмотр системного промпта", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Дополнительно: переопределить системный промпт", - "description": "Вы можете полностью заменить системный промпт для этого режима (кроме определения роли и пользовательских инструкций), создав файл .roo/system-prompt-{{slug}} в вашем рабочем пространстве. Это продвинутая функция, которая обходит встроенные ограничения и проверки (особенно для инструментов), поэтому будьте осторожны!" + "description": "Вы можете полностью заменить системный промпт для этого режима (кроме определения роли и пользовательских инструкций), создав файл .pearai-agent/system-prompt-{{slug}} в вашем рабочем пространстве. Это продвинутая функция, которая обходит встроенные ограничения и проверки (особенно для инструментов), поэтому будьте осторожны!" }, "createModeDialog": { "title": "Создать новый режим", @@ -122,7 +122,7 @@ "description": "Доступно во всех рабочих пространствах" }, "project": { - "label": "Для проекта (.roomodes)", + "label": "Для проекта (.pearai-agent-ignore)", "description": "Доступно только в этом рабочем пространстве, имеет приоритет над глобальными" } }, diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index 94783f4995f..54d60dbbeec 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -298,9 +298,9 @@ "label": "Лимит контекста файлов рабочей области", "description": "Максимальное количество файлов, включаемых в детали текущей рабочей директории. Большее значение даёт больше контекста, но увеличивает расход токенов." }, - "rooignore": { - "label": "Показывать .rooignore-файлы в списках и поиске", - "description": "Если включено, файлы, совпадающие с шаблонами в .rooignore, будут отображаться в списках с символом замка. Если выключено, такие файлы полностью скрываются из списков и поиска." + "pearai-agent-ignore": { + "label": "Показывать .pearai-agent-ignore-файлы в списках и поиске", + "description": "Если включено, файлы, совпадающие с шаблонами в .pearai-agent-ignore, будут отображаться в списках с символом замка. Если выключено, такие файлы полностью скрываются из списков и поиска." }, "maxReadFile": { "label": "Порог автообрезки при чтении файла", diff --git a/webview-ui/src/i18n/locales/tr/prompts.json b/webview-ui/src/i18n/locales/tr/prompts.json index 8d7c7b9305a..1e505dc07de 100644 --- a/webview-ui/src/i18n/locales/tr/prompts.json +++ b/webview-ui/src/i18n/locales/tr/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Yeni mod oluştur", "editModesConfig": "Mod yapılandırmasını düzenle", "editGlobalModes": "Global modları düzenle", - "editProjectModes": "Proje modlarını düzenle (.roomodes)", + "editProjectModes": "Proje modlarını düzenle (.pearai-agent-ignore)", "createModeHelpText": "Yeni bir özel mod oluşturmak için + düğmesine tıklayın veya sohbette Roo'dan sizin için bir tane oluşturmasını isteyin!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Moda özgü özel talimatlar (isteğe bağlı)", "resetToDefault": "Varsayılana sıfırla", "description": "{{modeName}} modu için özel davranış yönergeleri ekleyin.", - "loadFromFile": "{{mode}} moduna özgü özel talimatlar ayrıca çalışma alanınızdaki .roo/rules-{{slug}}/ klasöründen yüklenebilir (.roorules-{{slug}} ve .clinerules-{{slug}} kullanımdan kaldırılmıştır ve yakında çalışmayı durduracaklardır)." + "loadFromFile": "{{mode}} moduna özgü özel talimatlar ayrıca çalışma alanınızdaki .pearai-agent/rules-{{slug}}/ klasöründen yüklenebilir (.roorules-{{slug}} ve .clinerules-{{slug}} kullanımdan kaldırılmıştır ve yakında çalışmayı durduracaklardır)." }, "globalCustomInstructions": { "title": "Tüm Modlar için Özel Talimatlar", "description": "Bu talimatlar tüm modlara uygulanır. Aşağıdaki moda özgü talimatlarla geliştirilebilen temel davranış seti sağlarlar.\nRoo'nun editörünüzün görüntüleme dilinden ({{language}}) farklı bir dilde düşünmesini ve konuşmasını istiyorsanız, burada belirtebilirsiniz.", - "loadFromFile": "Talimatlar ayrıca çalışma alanınızdaki .roo/rules/ klasöründen de yüklenebilir (.roorules ve .clinerules kullanımdan kaldırılmıştır ve yakında çalışmayı durduracaklardır)." + "loadFromFile": "Talimatlar ayrıca çalışma alanınızdaki .pearai-agent/rules/ klasöründen de yüklenebilir (.roorules ve .clinerules kullanımdan kaldırılmıştır ve yakında çalışmayı durduracaklardır)." }, "systemPrompt": { "preview": "Sistem promptunu önizle", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Gelişmiş: Sistem Promptunu Geçersiz Kıl", - "description": "Çalışma alanınızda .roo/system-prompt-{{slug}} adresinde bir dosya oluşturarak bu mod için sistem istemini tamamen değiştirebilirsiniz (rol tanımı ve özel talimatlar hariç). Bu, yerleşik güvenlik önlemlerini ve tutarlılık kontrollerini (özellikle araç kullanımıyla ilgili) aşan çok gelişmiş bir özelliktir, bu yüzden dikkatli olun!" + "description": "Çalışma alanınızda .pearai-agent/system-prompt-{{slug}} adresinde bir dosya oluşturarak bu mod için sistem istemini tamamen değiştirebilirsiniz (rol tanımı ve özel talimatlar hariç). Bu, yerleşik güvenlik önlemlerini ve tutarlılık kontrollerini (özellikle araç kullanımıyla ilgili) aşan çok gelişmiş bir özelliktir, bu yüzden dikkatli olun!" }, "createModeDialog": { "title": "Yeni Mod Oluştur", @@ -122,7 +122,7 @@ "description": "Tüm çalışma alanlarında kullanılabilir" }, "project": { - "label": "Projeye özgü (.roomodes)", + "label": "Projeye özgü (.pearai-agent-ignore)", "description": "Yalnızca bu çalışma alanında kullanılabilir, globale göre önceliklidir" } }, diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 1a8bb25750e..dad295788d7 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -298,9 +298,9 @@ "label": "Çalışma alanı dosyaları bağlam sınırı", "description": "Mevcut çalışma dizini ayrıntılarına dahil edilecek maksimum dosya sayısı. Daha yüksek değerler daha fazla bağlam sağlar ancak token kullanımını artırır." }, - "rooignore": { - "label": "Listelerde ve aramalarda .rooignore dosyalarını göster", - "description": "Etkinleştirildiğinde, .rooignore'daki desenlerle eşleşen dosyalar kilit sembolü ile listelerde gösterilecektir. Devre dışı bırakıldığında, bu dosyalar dosya listelerinden ve aramalardan tamamen gizlenecektir." + "pearai-agent-ignore": { + "label": "Listelerde ve aramalarda .pearai-agent-ignore dosyalarını göster", + "description": "Etkinleştirildiğinde, .pearai-agent-ignore'daki desenlerle eşleşen dosyalar kilit sembolü ile listelerde gösterilecektir. Devre dışı bırakıldığında, bu dosyalar dosya listelerinden ve aramalardan tamamen gizlenecektir." }, "maxReadFile": { "label": "Dosya okuma otomatik kısaltma eşiği", diff --git a/webview-ui/src/i18n/locales/vi/prompts.json b/webview-ui/src/i18n/locales/vi/prompts.json index 4b62d3718e6..5583a8757e0 100644 --- a/webview-ui/src/i18n/locales/vi/prompts.json +++ b/webview-ui/src/i18n/locales/vi/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Tạo chế độ mới", "editModesConfig": "Chỉnh sửa cấu hình chế độ", "editGlobalModes": "Chỉnh sửa chế độ toàn cục", - "editProjectModes": "Chỉnh sửa chế độ dự án (.roomodes)", + "editProjectModes": "Chỉnh sửa chế độ dự án (.pearai-agent-ignore)", "createModeHelpText": "Nhấn + để tạo chế độ tùy chỉnh mới, hoặc chỉ cần yêu cầu Roo trong chat tạo một chế độ cho bạn!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Hướng dẫn tùy chỉnh dành riêng cho chế độ (tùy chọn)", "resetToDefault": "Đặt lại về mặc định", "description": "Thêm hướng dẫn hành vi dành riêng cho chế độ {{modeName}}.", - "loadFromFile": "Hướng dẫn tùy chỉnh dành riêng cho chế độ {{modeName}} cũng có thể được tải từ thư mục .roo/rules-{{modeSlug}}/ trong không gian làm việc của bạn (.roorules-{{modeSlug}} và .clinerules-{{modeSlug}} đã lỗi thời và sẽ sớm ngừng hoạt động)." + "loadFromFile": "Hướng dẫn tùy chỉnh dành riêng cho chế độ {{modeName}} cũng có thể được tải từ thư mục .pearai-agent/rules-{{modeSlug}}/ trong không gian làm việc của bạn (.roorules-{{modeSlug}} và .clinerules-{{modeSlug}} đã lỗi thời và sẽ sớm ngừng hoạt động)." }, "globalCustomInstructions": { "title": "Hướng dẫn tùy chỉnh cho tất cả các chế độ", "description": "Những hướng dẫn này áp dụng cho tất cả các chế độ. Chúng cung cấp một bộ hành vi cơ bản có thể được nâng cao bởi hướng dẫn dành riêng cho chế độ bên dưới.\nNếu bạn muốn Roo suy nghĩ và nói bằng ngôn ngữ khác với ngôn ngữ hiển thị trình soạn thảo của bạn ({{language}}), bạn có thể chỉ định ở đây.", - "loadFromFile": "Hướng dẫn cũng có thể được tải từ thư mục .roo/rules/ trong không gian làm việc của bạn (.roorules và .clinerules đã lỗi thời và sẽ sớm ngừng hoạt động)." + "loadFromFile": "Hướng dẫn cũng có thể được tải từ thư mục .pearai-agent/rules/ trong không gian làm việc của bạn (.roorules và .clinerules đã lỗi thời và sẽ sớm ngừng hoạt động)." }, "systemPrompt": { "preview": "Xem trước lời nhắc hệ thống", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Nâng cao: Ghi đè lời nhắc hệ thống", - "description": "Bạn có thể hoàn toàn thay thế lời nhắc hệ thống cho chế độ này (ngoài định nghĩa vai trò và hướng dẫn tùy chỉnh) bằng cách tạo một tệp tại .roo/system-prompt-{{modeSlug}} trong không gian làm việc của bạn. Đây là một tính năng rất nâng cao bỏ qua các biện pháp bảo vệ và kiểm tra nhất quán tích hợp sẵn (đặc biệt là xung quanh việc sử dụng công cụ), vì vậy hãy cẩn thận!" + "description": "Bạn có thể hoàn toàn thay thế lời nhắc hệ thống cho chế độ này (ngoài định nghĩa vai trò và hướng dẫn tùy chỉnh) bằng cách tạo một tệp tại .pearai-agent/system-prompt-{{modeSlug}} trong không gian làm việc của bạn. Đây là một tính năng rất nâng cao bỏ qua các biện pháp bảo vệ và kiểm tra nhất quán tích hợp sẵn (đặc biệt là xung quanh việc sử dụng công cụ), vì vậy hãy cẩn thận!" }, "createModeDialog": { "title": "Tạo chế độ mới", @@ -122,7 +122,7 @@ "description": "Có sẵn trong tất cả các không gian làm việc" }, "project": { - "label": "Dành riêng cho dự án (.roomodes)", + "label": "Dành riêng cho dự án (.pearai-agent-ignore)", "description": "Chỉ có sẵn trong không gian làm việc này, được ưu tiên hơn toàn cục" } }, diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 9d8764951ef..b4367171827 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -298,9 +298,9 @@ "label": "Giới hạn ngữ cảnh tệp workspace", "description": "Số lượng tệp tối đa để đưa vào chi tiết thư mục làm việc hiện tại. Giá trị cao hơn cung cấp nhiều ngữ cảnh hơn nhưng tăng sử dụng token." }, - "rooignore": { - "label": "Hiển thị tệp .rooignore trong danh sách và tìm kiếm", - "description": "Khi được bật, các tệp khớp với mẫu trong .rooignore sẽ được hiển thị trong danh sách với biểu tượng khóa. Khi bị tắt, các tệp này sẽ hoàn toàn bị ẩn khỏi danh sách tệp và tìm kiếm." + "pearai-agent-ignore": { + "label": "Hiển thị tệp .pearai-agent-ignore trong danh sách và tìm kiếm", + "description": "Khi được bật, các tệp khớp với mẫu trong .pearai-agent-ignore sẽ được hiển thị trong danh sách với biểu tượng khóa. Khi bị tắt, các tệp này sẽ hoàn toàn bị ẩn khỏi danh sách tệp và tìm kiếm." }, "maxReadFile": { "label": "Ngưỡng tự động cắt ngắn khi đọc tệp", diff --git a/webview-ui/src/i18n/locales/zh-CN/prompts.json b/webview-ui/src/i18n/locales/zh-CN/prompts.json index 2980bd66997..9c8dbb504d0 100644 --- a/webview-ui/src/i18n/locales/zh-CN/prompts.json +++ b/webview-ui/src/i18n/locales/zh-CN/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "新建模式", "editModesConfig": "模式设置", "editGlobalModes": "修改全局模式", - "editProjectModes": "编辑项目模式 (.roomodes)", + "editProjectModes": "编辑项目模式 (.pearai-agent-ignore)", "createModeHelpText": "点击 + 创建模式,或在对话时让Roo创建一个新模式。" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "模式专属规则(可选)", "resetToDefault": "重置为默认值", "description": "{{modeName}}模式的专属规则", - "loadFromFile": "支持从.roo/rules-{{slug}}/目录读取配置(.roorules-{{slug}}和.clinerules-{{slug}}已弃用并将很快停止工作)。" + "loadFromFile": "支持从.pearai-agent/rules-{{slug}}/目录读取配置(.roorules-{{slug}}和.clinerules-{{slug}}已弃用并将很快停止工作)。" }, "globalCustomInstructions": { "title": "所有模式的自定义指令", "description": "所有模式通用规则\n当前语言:{{language}}", - "loadFromFile": "支持从.roo/rules/目录读取全局配置(.roorules和.clinerules已弃用并将很快停止工作)。" + "loadFromFile": "支持从.pearai-agent/rules/目录读取全局配置(.roorules和.clinerules已弃用并将很快停止工作)。" }, "systemPrompt": { "preview": "预览系统提示词", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "高级:覆盖系统提示词", - "description": "您可以通过在工作区创建文件 .roo/system-prompt-{{slug}},完全替换此模式的系统提示(角色定义和自定义指令除外)。这是一个非常高级的功能,会绕过内置的安全措施和一致性检查(尤其是与工具使用相关的部分),请谨慎操作!" + "description": "您可以通过在工作区创建文件 .pearai-agent/system-prompt-{{slug}},完全替换此模式的系统提示(角色定义和自定义指令除外)。这是一个非常高级的功能,会绕过内置的安全措施和一致性检查(尤其是与工具使用相关的部分),请谨慎操作!" }, "createModeDialog": { "title": "创建新模式", @@ -122,7 +122,7 @@ "description": "全局可用" }, "project": { - "label": "项目特定 (.roomodes)", + "label": "项目特定 (.pearai-agent-ignore)", "description": "仅当前项目有效" } }, diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 5158586ab2d..71456795d62 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -298,9 +298,9 @@ "label": "工作区文件限制", "description": "允许纳入上下文的最大文件数(值越大消耗token越多)" }, - "rooignore": { - "label": "在列表和搜索中显示 .rooignore 文件", - "description": "启用后,与 .rooignore 中模式匹配的文件将在列表中显示锁定符号。禁用时,这些文件将从文件列表和搜索中完全隐藏。" + "pearai-agent-ignore": { + "label": "在列表和搜索中显示 .pearai-agent-ignore 文件", + "description": "启用后,与 .pearai-agent-ignore 中模式匹配的文件将在列表中显示锁定符号。禁用时,这些文件将从文件列表和搜索中完全隐藏。" }, "maxReadFile": { "label": "文件读取自动截断阈值", diff --git a/webview-ui/src/i18n/locales/zh-TW/prompts.json b/webview-ui/src/i18n/locales/zh-TW/prompts.json index 9b99707cf67..876175b83fd 100644 --- a/webview-ui/src/i18n/locales/zh-TW/prompts.json +++ b/webview-ui/src/i18n/locales/zh-TW/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "建立新模式", "editModesConfig": "編輯模式設定", "editGlobalModes": "編輯全域模式", - "editProjectModes": "編輯專案模式 (.roomodes)", + "editProjectModes": "編輯專案模式 (.pearai-agent-ignore)", "createModeHelpText": "點選 + 建立新的自訂模式,或者在聊天中直接請 Roo 為您建立!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "模式專屬自訂指令(選用)", "resetToDefault": "重設為預設值", "description": "為 {{modeName}} 模式新增專屬的行為指南。", - "loadFromFile": "{{mode}} 模式的自訂指令也可以從工作區的 .roo/rules-{{slug}}/ 資料夾載入(.roorules-{{slug}} 和 .clinerules-{{slug}} 已棄用並將很快停止運作)。" + "loadFromFile": "{{mode}} 模式的自訂指令也可以從工作區的 .pearai-agent/rules-{{slug}}/ 資料夾載入(.roorules-{{slug}} 和 .clinerules-{{slug}} 已棄用並將很快停止運作)。" }, "globalCustomInstructions": { "title": "所有模式的自訂指令", "description": "這些指令適用於所有模式。它們提供了一組基本行為,可以透過下方的模式專屬自訂指令來強化。\n如果您希望 Roo 使用與編輯器顯示語言 ({{language}}) 不同的語言來思考和對話,您可以在這裡指定。", - "loadFromFile": "指令也可以從工作區的 .roo/rules/ 資料夾載入(.roorules 和 .clinerules 已棄用並將很快停止運作)。" + "loadFromFile": "指令也可以從工作區的 .pearai-agent/rules/ 資料夾載入(.roorules 和 .clinerules 已棄用並將很快停止運作)。" }, "systemPrompt": { "preview": "預覽系統提示詞", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "進階:覆寫系統提示詞", - "description": "您可以透過在工作區建立檔案 .roo/system-prompt-{{slug}} 來完全替換此模式的系統提示詞(角色定義和自訂指令除外)。這是一個非常進階的功能,會繞過內建的安全措施和一致性檢查(尤其是與工具使用相關的檢查),請謹慎使用!" + "description": "您可以透過在工作區建立檔案 .pearai-agent/system-prompt-{{slug}} 來完全替換此模式的系統提示詞(角色定義和自訂指令除外)。這是一個非常進階的功能,會繞過內建的安全措施和一致性檢查(尤其是與工具使用相關的檢查),請謹慎使用!" }, "createModeDialog": { "title": "建立新模式", @@ -122,7 +122,7 @@ "description": "在所有工作區可用" }, "project": { - "label": "專案特定 (.roomodes)", + "label": "專案特定 (.pearai-agent-ignore)", "description": "僅在此工作區可用,優先於全域模式" } }, diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 1d329752fe1..6618a1b9153 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -298,9 +298,9 @@ "label": "工作區檔案的上下文限制", "description": "目前工作目錄中最多包含多少個檔案。數值越高提供的上下文越多,但 token 用量也會增加。" }, - "rooignore": { - "label": "在列表和搜尋中顯示被 .rooignore 排除的檔案", - "description": "啟用後,符合 .rooignore 規則的檔案會在列表中顯示並標示鎖定圖示。停用後,這些檔案將完全從檔案列表和搜尋結果中隱藏。" + "pearai-agent-ignore": { + "label": "在列表和搜尋中顯示被 .pearai-agent-ignore 排除的檔案", + "description": "啟用後,符合 .pearai-agent-ignore 規則的檔案會在列表中顯示並標示鎖定圖示。停用後,這些檔案將完全從檔案列表和搜尋結果中隱藏。" }, "maxReadFile": { "label": "檔案讀取自動截斷閾值", From 480f999b9e03f1c8ade4842c9914680ef81f41d4 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Mon, 12 May 2025 18:50:04 +0100 Subject: [PATCH 33/80] fix: duplicate key --- evals/packages/types/src/roo-code.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/evals/packages/types/src/roo-code.ts b/evals/packages/types/src/roo-code.ts index b3f69e16788..4318603edc5 100644 --- a/evals/packages/types/src/roo-code.ts +++ b/evals/packages/types/src/roo-code.ts @@ -400,8 +400,6 @@ export const providerSettingsSchema = z.object({ // OpenAI Native openAiNativeApiKey: z.string().optional(), openAiNativeBaseUrl: z.string().optional(), - // XAI - xaiApiKey: z.string().optional(), // Mistral mistralApiKey: z.string().optional(), mistralCodestralUrl: z.string().optional(), From 5135c134363ef907665856c5fdd94f7c4eab0b58 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 11:21:49 +0100 Subject: [PATCH 34/80] WIP: creator mode shizz --- package-lock.json | 1 - src/activate/index.ts | 1 + src/extension.ts | 9 ++++++++- src/shared/creatorMode.ts | 10 ++++++++++ src/shared/modes.ts | 10 +++++++++- 5 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 src/shared/creatorMode.ts diff --git a/package-lock.json b/package-lock.json index 5abe8b91a57..4d90382ae92 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17081,7 +17081,6 @@ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "chalk": "^2.4.1", diff --git a/src/activate/index.ts b/src/activate/index.ts index 658bf467f7a..2fff46a5f04 100644 --- a/src/activate/index.ts +++ b/src/activate/index.ts @@ -2,3 +2,4 @@ export { handleUri } from "./handleUri" export { registerCommands } from "./registerCommands" export { registerCodeActions } from "./registerCodeActions" export { registerTerminalActions } from "./registerTerminalActions" +export { registerPearListener } from "./registerPearListener" diff --git a/src/extension.ts b/src/extension.ts index c391aaf0cd2..d4dfe7e7fcc 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -26,7 +26,13 @@ import { TerminalRegistry } from "./integrations/terminal/TerminalRegistry" import { API } from "./exports/api" import { migrateSettings } from "./utils/migrateSettings" -import { handleUri, registerCommands, registerCodeActions, registerTerminalActions } from "./activate" +import { + handleUri, + registerCommands, + registerCodeActions, + registerTerminalActions, + registerPearListener, +} from "./activate" import { formatLanguage } from "./shared/language" /** @@ -202,6 +208,7 @@ export async function activate(context: vscode.ExtensionContext) { registerCodeActions(context) registerTerminalActions(context) + registerPearListener() context.subscriptions.push( vscode.commands.registerCommand("roo-cline.focus", async (...args: any[]) => { diff --git a/src/shared/creatorMode.ts b/src/shared/creatorMode.ts new file mode 100644 index 00000000000..350deea3f39 --- /dev/null +++ b/src/shared/creatorMode.ts @@ -0,0 +1,10 @@ +export const CREATOR_MODE_PLANNING_PROMPT = ` +Depending on the user's request, you may need to do some information gathering (for example using read_file or search_files) to get more context about the task. +You may also ask the user clarifying questions to get a better understanding of the task. +Once you've gained more context about the user's request, you should create a detailed plan for how to accomplish the task. +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. +(Directly write the plan to a markdown file instead of showing it as normal response.)\n\n +Once you create and write the plan, you mark the task as completed. +You only make plans and you should not ask or switch to any other mode. +Keep the plan brief, mainly feature based (include a feature list), and no steps, a product outline.` diff --git a/src/shared/modes.ts b/src/shared/modes.ts index 257f4bcf946..a1fe5e676d3 100644 --- a/src/shared/modes.ts +++ b/src/shared/modes.ts @@ -1,9 +1,9 @@ import * as vscode from "vscode" - import { GroupOptions, GroupEntry, ModeConfig, PromptComponent, CustomModePrompts, ExperimentId } from "../schemas" import { TOOL_GROUPS, ToolGroup, ALWAYS_AVAILABLE_TOOLS } from "./tools" import { addCustomInstructions } from "../core/prompts/sections/custom-instructions" import { EXPERIMENT_IDS } from "./experiments" +import { CREATOR_MODE_PLANNING_PROMPT } from "./creatorMode" export type Mode = string export type { GroupOptions, GroupEntry, ModeConfig, PromptComponent, CustomModePrompts } @@ -52,6 +52,14 @@ 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: CREATOR_MODE_PLANNING_PROMPT, + }, { slug: "code", name: "💻 Code", From 614bc3ab819c60b7649d532575e025d890fbf6f0 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 11:24:06 +0100 Subject: [PATCH 35/80] WIP: registering pear listener for messages from submodule --- src/activate/registerPearListener.ts | 78 ++++++++++++++++++++++++++++ src/core/webview/ClineProvider.ts | 19 ++++++- src/utils/util.ts | 19 +++++++ 3 files changed, 115 insertions(+), 1 deletion(-) create mode 100644 src/activate/registerPearListener.ts create mode 100644 src/utils/util.ts diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts new file mode 100644 index 00000000000..4a5e5a66bd3 --- /dev/null +++ b/src/activate/registerPearListener.ts @@ -0,0 +1,78 @@ +import * as vscode from "vscode" +import { ClineProvider } from "../core/webview/ClineProvider" +import { assert } from "../utils/util" + +export const getPearaiExtension = async () => { + const pearAiExtension = vscode.extensions.getExtension("pearai.pearai") + + assert(!!pearAiExtension, "PearAI extension not found") + + if (!pearAiExtension.isActive) { + await pearAiExtension.activate() + } + + return pearAiExtension +} + +export const registerPearListener = async () => { + // Getting the pear ai extension instance + const pearAiExtension = await getPearaiExtension() + + // Access the API directly from exports + if (pearAiExtension.exports) { + pearAiExtension.exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg: any) => { + console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`) + + // Get the sidebar provider + const sidebarProvider = ClineProvider.getSidebarInstance() + + if (sidebarProvider) { + // Focus the sidebar first + await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") + + // Wait for the view to be ready using a helper function + await ensureViewIsReady(sidebarProvider) + + // Switch to creator mode + await sidebarProvider.handleModeSwitch("creator") + await sidebarProvider.postStateToWebview() + + // Navigate to chat view + await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) + + // Wait a brief moment for UI to update + await new Promise((resolve) => setTimeout(resolve, 300)) + + // Initialize with task + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, true) + } + }) + } else { + console.error("⚠️⚠️ PearAI API not available in exports ⚠️⚠️") + } +} + +// TODO: decide if this is needed +// Helper function to ensure the webview is ready +async function ensureViewIsReady(provider: ClineProvider): Promise { + // If the view is already launched, we're good to go + if (provider.viewLaunched) { + return + } + + // Otherwise, we need to wait for it to initialize + return new Promise((resolve) => { + // Set up a one-time listener for when the view is ready + const disposable = provider.on("clineAdded", () => { + // Clean up the listener + disposable.dispose() + resolve() + }) + + // Set a timeout just in case + setTimeout(() => { + disposable.dispose() + resolve() + }, 5000) + }) +} diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 23eb295c9eb..3b33f5b0ad9 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -86,6 +86,7 @@ export class ClineProvider extends EventEmitter implements private readonly outputChannel: vscode.OutputChannel, private readonly renderContext: "sidebar" | "editor" = "sidebar", public readonly contextProxy: ContextProxy, + private readonly isCreatorView: boolean = false, ) { super() @@ -115,6 +116,16 @@ export class ClineProvider extends EventEmitter implements }) } + public static getSidebarInstance(): ClineProvider | undefined { + const sidebar = Array.from(this.activeInstances).find((instance) => !instance.isCreatorView) + + if (!sidebar?.view?.visible) { + vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") + } + + return sidebar + } + // Adds a new Cline instance to clineStack, marking the start of a new task. // The instance is pushed to the top of the stack (LIFO order). // When the task is completed, the top instance is removed, reactivating the previous task. @@ -474,6 +485,7 @@ export class ClineProvider extends EventEmitter implements | "experiments" > > = {}, + creatorMode?: boolean ) { const { apiConfiguration, @@ -493,7 +505,12 @@ export class ClineProvider extends EventEmitter implements const cline = new Cline({ provider: this, - apiConfiguration: { ...apiConfiguration, pearaiAgentModels: pearaiAgentModels }, + apiConfiguration: { + ...apiConfiguration, + ...apiConfiguration, + pearaiAgentModels: pearaiAgentModels + creatorMode, + }, customInstructions: effectiveInstructions, enableDiff, enableCheckpoints, diff --git a/src/utils/util.ts b/src/utils/util.ts new file mode 100644 index 00000000000..54e5cbc8f04 --- /dev/null +++ b/src/utils/util.ts @@ -0,0 +1,19 @@ +class AssertionError extends Error { + constructor(message: string) { + super(message) + // Adding the stack info to error. + // Inspired by: https://blog.dennisokeeffe.com/blog/2020-08-07-error-tracing-with-sentry-and-es6-classes + if (Error.captureStackTrace) { + Error.captureStackTrace(this, AssertionError) + } else { + this.stack = new Error(message).stack + } + this.name = "AssertionError" + } +} + +export function assert(condition: boolean, message: string): asserts condition { + if (!condition) { + throw new AssertionError(message) + } +} From 5d5ed70a7222d6f2bd0975b979e02ca7285463a7 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Thu, 17 Apr 2025 13:50:40 +0100 Subject: [PATCH 36/80] fix: sending roo code when we're in creator mode --- src/core/Cline.ts | 5 +++++ src/core/webview/ClineProvider.ts | 33 +++++++++++++++++++++++++++---- src/schemas/index.ts | 2 ++ 3 files changed, 36 insertions(+), 4 deletions(-) diff --git a/src/core/Cline.ts b/src/core/Cline.ts index d32581be9fa..669c1b93f3e 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -127,6 +127,7 @@ export type ClineOptions = { taskNumber?: number onCreated?: (cline: Cline) => void pearaiModels?: Record + creatorMode?: boolean } export class Cline extends EventEmitter { @@ -142,6 +143,7 @@ export class Cline extends EventEmitter { pausedModeSlug: string = defaultModeSlug private pauseInterval: NodeJS.Timeout | undefined + public creatorMode: boolean readonly apiConfiguration: ApiConfiguration api: ApiHandler private promptCacheKey: string @@ -220,6 +222,7 @@ export class Cline extends EventEmitter { parentTask, taskNumber = -1, onCreated, + creatorMode, }: ClineOptions) { super() @@ -257,6 +260,8 @@ export class Cline extends EventEmitter { this.diffViewProvider = new DiffViewProvider(this.cwd) this.enableCheckpoints = enableCheckpoints + this.creatorMode = creatorMode ?? false + this.rootTask = rootTask this.parentTask = parentTask this.taskNumber = taskNumber diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 3b33f5b0ad9..7b0f89f3c9a 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -498,6 +498,15 @@ export class ClineProvider extends EventEmitter implements experiments, } = await this.getState() + // Update API configuration with creator mode + await this.updateApiConfiguration({ + ...apiConfiguration, + creatorMode, + }) + + // Post updated state to webview immediately + await this.postStateToWebview() + const modePrompt = customModePrompts?.[mode] as PromptComponent const effectiveInstructions = [globalInstructions, modePrompt?.customInstructions].filter(Boolean).join("\n\n") @@ -508,7 +517,7 @@ export class ClineProvider extends EventEmitter implements apiConfiguration: { ...apiConfiguration, ...apiConfiguration, - pearaiAgentModels: pearaiAgentModels + pearaiAgentModels: pearaiAgentModels, creatorMode, }, customInstructions: effectiveInstructions, @@ -523,6 +532,7 @@ export class ClineProvider extends EventEmitter implements taskNumber: this.clineStack.length + 1, onCreated: (cline) => this.emit("clineCreated", cline), ...options, + creatorMode, }) await this.addClineToStack(cline) @@ -841,6 +851,13 @@ export class ClineProvider extends EventEmitter implements async updateApiConfiguration(providerSettings: ProviderSettings) { // Update mode's default config. const { mode } = await this.getState() + const currentCline = this.getCurrentCline() + + // Preserve creator mode when updating configuration + const updatedConfig = { + ...providerSettings, + creatorMode: currentCline?.creatorMode, + } satisfies ProviderSettings; if (mode) { const currentApiConfigName = this.getGlobalState("currentApiConfigName") @@ -852,10 +869,10 @@ export class ClineProvider extends EventEmitter implements } } - await this.contextProxy.setProviderSettings(providerSettings) + await this.contextProxy.setProviderSettings(updatedConfig) if (this.getCurrentCline()) { - this.getCurrentCline()!.api = buildApiHandler(providerSettings) + this.getCurrentCline()!.api = buildApiHandler(updatedConfig) } } @@ -1167,8 +1184,10 @@ export class ClineProvider extends EventEmitter implements } async getStateToPostToWebview() { + const currentCline = this.getCurrentCline() + // Get base state const { - apiConfiguration, + apiConfiguration: baseApiConfiguration, lastShownAnnouncementId, customInstructions, alwaysAllowReadOnly, @@ -1228,6 +1247,12 @@ export class ClineProvider extends EventEmitter implements historyPreviewCollapsed, } = await this.getState() + // Construct API configuration with creator mode + const apiConfiguration = { + ...baseApiConfiguration, + creatorMode: currentCline?.creatorMode, + } + const telemetryKey = process.env.POSTHOG_API_KEY const machineId = vscode.env.machineId const allowedCommands = vscode.workspace.getConfiguration("roo-cline").get("allowedCommands") || [] diff --git a/src/schemas/index.ts b/src/schemas/index.ts index db61b52a2e2..159cfcb7bf7 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -449,6 +449,7 @@ export const providerSettingsSchema = z.object({ defaultModelId: z.string().optional(), }) .optional(), + creatorMode: z.boolean().optional(), }) export type ProviderSettings = z.infer @@ -546,6 +547,7 @@ const providerSettingsRecord: ProviderSettingsRecord = { pearaiApiKey: undefined, pearaiModelInfo: undefined, pearaiAgentModels: undefined, + creatorMode: undefined, // X.AI (Grok) xaiApiKey: undefined, } From 5d49cc6a6d188e3ce8a9dd626ec0603ccebfc565 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Thu, 17 Apr 2025 14:39:49 +0100 Subject: [PATCH 37/80] feat: added creator mode bar --- webview-ui/src/components/chat/ChatView.tsx | 4 + .../src/components/chat/CreatorModeBar.tsx | 64 ++++++++++ .../src/components/chat/button/index.tsx | 116 ++++++++++++++++++ 3 files changed, 184 insertions(+) create mode 100644 webview-ui/src/components/chat/CreatorModeBar.tsx create mode 100644 webview-ui/src/components/chat/button/index.tsx diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 33eb1916aa3..2bc0fb98f14 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -49,6 +49,7 @@ import { vscInputBorder, vscSidebarBorder, } from "../ui" +import { CreatorModeBar } from "./CreatorModeBar" import SystemPromptWarning from "./SystemPromptWarning" import { usePearAIModels } from "@/hooks/usePearAIModels" @@ -1237,6 +1238,9 @@ const ChatViewComponent: React.ForwardRefRenderFunction + {apiConfiguration?.creatorMode === true && ( + + )} {task ? ( <> void + nextCallback?: () => void + className?: string +} +// from: https://vscode.dev/github/trypear/pearai-submodule/blob/acorn/253-submodule-api-fixed/gui/src/pages/creator/ui/planningBar.tsx#L15-L50 +// TODO: UI LIBRARY COMPONENT SHARING SHIZZ HERE! + +export const CreatorModeBar: FC = ({ + isGenerating, + requestedPlan, + playCallback, + nextCallback, + className, +}) => { + return ( +
+ {isGenerating &&
} +
+
+
+
+
Planning
+
+
{requestedPlan}
+
+
+ +
+
+ + + +
+ + {/* */} +
+
+ ) +} diff --git a/webview-ui/src/components/chat/button/index.tsx b/webview-ui/src/components/chat/button/index.tsx new file mode 100644 index 00000000000..a5e043aa6e8 --- /dev/null +++ b/webview-ui/src/components/chat/button/index.tsx @@ -0,0 +1,116 @@ +import * as React from "react" +import { Slot } from "@radix-ui/react-slot" +import { cva, type VariantProps } from "class-variance-authority" + +import { cn } from "@/lib/utils" +// FROM: https://vscode.dev/github/trypear/pearai-submodule/blob/acorn/253-submodule-api-fixed/gui/src/pages/creator/ui/button/index.tsx#L1-L121 +// TODO: UI LIBRARY COMPONENT SHARING SHIZZ HERE! +const buttonVariants = cva( + "inline-flex items-center justify-center gap-2 border-none whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[#a1a1aa] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + { + variants: { + variant: { + default: "bg-[#18181b] text-[#fafafa] shadow hover:bg-[#27272a]", + destructive: "bg-[#ef4444] text-[#fafafa] shadow-sm hover:bg-[#dc2626]", + outline: "border border-[#e4e4e7] bg-[#ffffff] shadow-sm hover:bg-[#f4f4f5] hover:text-[#18181b]", + secondary: "bg-[#f4f4f5] text-[#18181b] hover:bg-[#e4e4e7]", + ghost: "hover:bg-[#f4f4f5] hover:text-[#18181b]", + link: "text-[#18181b] underline-offset-4 hover:underline", + }, + size: { + // default: "h-9 px-4 py-2", + default: "h-7 rounded-md px-2 text-md", + sm: "h-6 rounded-md px-2 text-xs", + lg: "h-10 rounded-md px-8", + icon: "h-9 w-9", + }, + toggled: { + true: "", + }, + }, + compoundVariants: [ + { + variant: "default", + toggled: true, + className: " bg-[#3030ad] text-[#0B84FF] hover:bg-[#3a3ad2]", // bg-[#27272a] text-[#fafafa] + }, + { + variant: "destructive", + toggled: true, + className: "bg-[#dc2626] text-[#fafafa]", + }, + { + variant: "outline", + toggled: true, + className: "bg-[#f4f4f5] text-[#18181b] border-[#a1a1aa]", + }, + { + variant: "secondary", + toggled: true, + // className: "bg-[#e4e4e7] text-[#18181b]" + className: "bg-[#E3EFFF] text-[#4388F8] hover:bg-[#D1E3FF]", + }, + { + variant: "ghost", + toggled: true, + className: "bg-[#f4f4f5] text-[#18181b]", + }, + { + variant: "link", + toggled: true, + className: "text-[#18181b] underline", + }, + ], + defaultVariants: { + variant: "default", + size: "default", + toggled: false, + }, + }, +) + +export interface ButtonProps + extends React.ButtonHTMLAttributes, + VariantProps { + asChild?: boolean + onToggle?: (toggled: boolean) => void +} + +const Button = React.forwardRef( + ( + { className, variant, size, toggled: initialToggled = false, asChild = false, onToggle, onClick, ...props }, + ref, + ) => { + const Comp = asChild ? Slot : "button" + const [toggled, setToggled] = React.useState(initialToggled) + + const handleClick = (event: React.MouseEvent) => { + if (onToggle) { + const newToggled = !toggled + setToggled(newToggled) + onToggle(newToggled) + } + + onClick?.(event) + } + + return ( + + ) + }, +) +Button.displayName = "Button" + +export { Button, buttonVariants } From 1d77a4677465ce9d41913c9b2684435fd39e1d1c Mon Sep 17 00:00:00 2001 From: nang-dev Date: Sat, 19 Apr 2025 17:05:33 -0400 Subject: [PATCH 38/80] Added newProject filtering --- src/activate/registerPearListener.ts | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 4a5e5a66bd3..198276dae94 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -33,10 +33,11 @@ export const registerPearListener = async () => { // Wait for the view to be ready using a helper function await ensureViewIsReady(sidebarProvider) - // Switch to creator mode - await sidebarProvider.handleModeSwitch("creator") - await sidebarProvider.postStateToWebview() - + if (msg.newProject) { + // Switch to creator mode + await sidebarProvider.handleModeSwitch("creator") + await sidebarProvider.postStateToWebview() + } // Navigate to chat view await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) @@ -44,7 +45,7 @@ export const registerPearListener = async () => { await new Promise((resolve) => setTimeout(resolve, 300)) // Initialize with task - await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, true) + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, msg.newProject) } }) } else { From 6eb671b7dd1d07b4f80f0de083c66b3e7ca9654a Mon Sep 17 00:00:00 2001 From: nang-dev Date: Wed, 23 Apr 2025 21:42:53 -0400 Subject: [PATCH 39/80] Progress --- src/activate/registerPearListener.ts | 10 ++++++++-- src/api/providers/anthropic.ts | 9 ++++++++- src/core/Cline.ts | 4 ++++ src/core/webview/ClineProvider.ts | 17 +++++++++-------- src/exports/roo-code.d.ts | 2 ++ src/exports/types.ts | 2 ++ src/schemas/index.ts | 2 ++ src/shared/creatorMode.ts | 10 ---------- src/shared/modes.ts | 4 ++-- src/shared/pearaiApi.ts | 4 ++-- 10 files changed, 39 insertions(+), 25 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 198276dae94..d557dd197d8 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -33,7 +33,7 @@ export const registerPearListener = async () => { // Wait for the view to be ready using a helper function await ensureViewIsReady(sidebarProvider) - if (msg.newProject) { + if (msg.creatorMode) { // Switch to creator mode await sidebarProvider.handleModeSwitch("creator") await sidebarProvider.postStateToWebview() @@ -45,7 +45,13 @@ export const registerPearListener = async () => { await new Promise((resolve) => setTimeout(resolve, 300)) // Initialize with task - await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, msg.newProject) + await sidebarProvider.initClineWithTask( + msg.plan, + undefined, + undefined, + msg.creatorMode, + msg.newProjectType, + ) } }) } else { diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index f80fde03439..e39b3b1d67d 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -105,8 +105,15 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa case "claude-3-opus-20240229": case "claude-3-haiku-20240307": betas.push("prompt-caching-2024-07-31") + + // Include prompt_key if newProjectType is set return { - headers: { "anthropic-beta": betas.join(",") }, + headers: { + "anthropic-beta": betas.join(","), + ...(String(this.options.newProjectType) + ? { prompt_key: String(this.options.newProjectType) } + : {}), + }, authorization: `Bearer ${this.options.apiKey}`, } default: diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 669c1b93f3e..c76ecebccb6 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -128,6 +128,7 @@ export type ClineOptions = { onCreated?: (cline: Cline) => void pearaiModels?: Record creatorMode?: boolean + newProjectType?: string } export class Cline extends EventEmitter { @@ -144,6 +145,7 @@ export class Cline extends EventEmitter { private pauseInterval: NodeJS.Timeout | undefined public creatorMode: boolean + public newProjectType: string readonly apiConfiguration: ApiConfiguration api: ApiHandler private promptCacheKey: string @@ -223,6 +225,7 @@ export class Cline extends EventEmitter { taskNumber = -1, onCreated, creatorMode, + newProjectType, }: ClineOptions) { super() @@ -261,6 +264,7 @@ export class Cline extends EventEmitter { this.enableCheckpoints = enableCheckpoints this.creatorMode = creatorMode ?? false + this.newProjectType = newProjectType ?? "" this.rootTask = rootTask this.parentTask = parentTask diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 7b0f89f3c9a..659df144af7 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -464,12 +464,9 @@ export class ClineProvider extends EventEmitter implements return this.initClineWithTask(task, images, parent) } - // When initializing a new task, (not from history but from a tool command - // new_task) there is no need to remove the previouse task since the new - // task is a subtask of the previous one, and when it finishes it is removed - // from the stack and the caller is resumed in this way we can have a chain - // of tasks, each one being a sub task of the previous one until the main - // task is finished. + // when initializing a new task, (not from history but from a tool command new_task) there is no need to remove the previouse task + // since the new task is a sub task of the previous one, and when it finishes it is removed from the stack and the caller is resumed + // in this way we can have a chain of tasks, each one being a sub task of the previous one until the main task is finished public async initClineWithTask( task?: string, images?: string[], @@ -485,7 +482,8 @@ export class ClineProvider extends EventEmitter implements | "experiments" > > = {}, - creatorMode?: boolean + creatorMode?: boolean, + newProjectType?: string, ) { const { apiConfiguration, @@ -502,6 +500,7 @@ export class ClineProvider extends EventEmitter implements await this.updateApiConfiguration({ ...apiConfiguration, creatorMode, + newProjectType, }) // Post updated state to webview immediately @@ -516,7 +515,6 @@ export class ClineProvider extends EventEmitter implements provider: this, apiConfiguration: { ...apiConfiguration, - ...apiConfiguration, pearaiAgentModels: pearaiAgentModels, creatorMode, }, @@ -533,6 +531,7 @@ export class ClineProvider extends EventEmitter implements onCreated: (cline) => this.emit("clineCreated", cline), ...options, creatorMode, + newProjectType, }) await this.addClineToStack(cline) @@ -857,6 +856,7 @@ export class ClineProvider extends EventEmitter implements const updatedConfig = { ...providerSettings, creatorMode: currentCline?.creatorMode, + newProjectType: currentCline?.newProjectType, } satisfies ProviderSettings; if (mode) { @@ -1251,6 +1251,7 @@ export class ClineProvider extends EventEmitter implements const apiConfiguration = { ...baseApiConfiguration, creatorMode: currentCline?.creatorMode, + newProjectType: currentCline?.newProjectType, } const telemetryKey = process.env.POSTHOG_API_KEY diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index 4eef2426dab..7978f5a3850 100644 --- a/src/exports/roo-code.d.ts +++ b/src/exports/roo-code.d.ts @@ -202,6 +202,8 @@ type ProviderSettings = { defaultModelId?: string | undefined } | undefined + creatorMode?: boolean | undefined + newProjectType?: string | undefined } type GlobalSettings = { diff --git a/src/exports/types.ts b/src/exports/types.ts index 0b557dd0baf..69b1f9f4d79 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -203,6 +203,8 @@ type ProviderSettings = { defaultModelId?: string | undefined } | undefined + creatorMode?: boolean | undefined + newProjectType?: string | undefined } export type { ProviderSettings } diff --git a/src/schemas/index.ts b/src/schemas/index.ts index 159cfcb7bf7..edfdb2d32a1 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -450,6 +450,7 @@ export const providerSettingsSchema = z.object({ }) .optional(), creatorMode: z.boolean().optional(), + newProjectType: z.string().optional(), }) export type ProviderSettings = z.infer @@ -548,6 +549,7 @@ const providerSettingsRecord: ProviderSettingsRecord = { pearaiModelInfo: undefined, pearaiAgentModels: undefined, creatorMode: undefined, + newProjectType: undefined, // X.AI (Grok) xaiApiKey: undefined, } diff --git a/src/shared/creatorMode.ts b/src/shared/creatorMode.ts index 350deea3f39..e69de29bb2d 100644 --- a/src/shared/creatorMode.ts +++ b/src/shared/creatorMode.ts @@ -1,10 +0,0 @@ -export const CREATOR_MODE_PLANNING_PROMPT = ` -Depending on the user's request, you may need to do some information gathering (for example using read_file or search_files) to get more context about the task. -You may also ask the user clarifying questions to get a better understanding of the task. -Once you've gained more context about the user's request, you should create a detailed plan for how to accomplish the task. -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. -(Directly write the plan to a markdown file instead of showing it as normal response.)\n\n -Once you create and write the plan, you mark the task as completed. -You only make plans and you should not ask or switch to any other mode. -Keep the plan brief, mainly feature based (include a feature list), and no steps, a product outline.` diff --git a/src/shared/modes.ts b/src/shared/modes.ts index a1fe5e676d3..8809d3515d7 100644 --- a/src/shared/modes.ts +++ b/src/shared/modes.ts @@ -3,7 +3,8 @@ import { GroupOptions, GroupEntry, ModeConfig, PromptComponent, CustomModePrompt import { TOOL_GROUPS, ToolGroup, ALWAYS_AVAILABLE_TOOLS } from "./tools" import { addCustomInstructions } from "../core/prompts/sections/custom-instructions" import { EXPERIMENT_IDS } from "./experiments" -import { CREATOR_MODE_PLANNING_PROMPT } from "./creatorMode" + +// Mode types export type Mode = string export type { GroupOptions, GroupEntry, ModeConfig, PromptComponent, CustomModePrompts } @@ -58,7 +59,6 @@ export const modes: readonly ModeConfig[] = [ 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: CREATOR_MODE_PLANNING_PROMPT, }, { slug: "code", diff --git a/src/shared/pearaiApi.ts b/src/shared/pearaiApi.ts index 0d110218aa3..c0a5e4d3656 100644 --- a/src/shared/pearaiApi.ts +++ b/src/shared/pearaiApi.ts @@ -1,8 +1,8 @@ // CHANGE AS NEEDED FOR DEVELOPMENT // PROD: -export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" +// export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" // DEV: -// export const PEARAI_URL = "http://localhost:8000/integrations/cline" +export const PEARAI_URL = "http://localhost:8000/integrations/cline" import { anthropicModels, From f9ad0223d9ffb876d074f90c9c3e625372c638bb Mon Sep 17 00:00:00 2001 From: nang-dev Date: Wed, 23 Apr 2025 23:09:49 -0400 Subject: [PATCH 40/80] Added creatorModeConfig --- src/activate/registerPearListener.ts | 22 +++++++++++--------- src/api/providers/anthropic.ts | 12 ++++++----- src/core/Cline.ts | 14 +++++-------- src/core/webview/ClineProvider.ts | 23 ++++++++------------- src/exports/roo-code.d.ts | 9 ++++++-- src/exports/types.ts | 9 ++++++-- src/schemas/index.ts | 14 +++++++++---- src/shared/pearaiApi.ts | 4 ++-- webview-ui/src/components/chat/ChatView.tsx | 2 +- 9 files changed, 60 insertions(+), 49 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index d557dd197d8..0120332522a 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -1,6 +1,8 @@ import * as vscode from "vscode" import { ClineProvider } from "../core/webview/ClineProvider" import { assert } from "../utils/util" +import { CreatorModeConfig } from "../schemas" + export const getPearaiExtension = async () => { const pearAiExtension = vscode.extensions.getExtension("pearai.pearai") @@ -33,7 +35,7 @@ export const registerPearListener = async () => { // Wait for the view to be ready using a helper function await ensureViewIsReady(sidebarProvider) - if (msg.creatorMode) { + if (msg.creatorModeConfig?.creatorMode) { // Switch to creator mode await sidebarProvider.handleModeSwitch("creator") await sidebarProvider.postStateToWebview() @@ -44,14 +46,14 @@ export const registerPearListener = async () => { // Wait a brief moment for UI to update await new Promise((resolve) => setTimeout(resolve, 300)) + let creatorModeConifig = { + creatorMode: msg.creatorMode, + newProjectType: msg.newProjectType, + newProjectPath: msg.newProjectPath, + } satisfies CreatorModeConfig; + // Initialize with task - await sidebarProvider.initClineWithTask( - msg.plan, - undefined, - undefined, - msg.creatorMode, - msg.newProjectType, - ) + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConifig) } }) } else { @@ -68,9 +70,9 @@ async function ensureViewIsReady(provider: ClineProvider): Promise { } // Otherwise, we need to wait for it to initialize - return new Promise((resolve) => { + return new Promise((resolve) => { // Set up a one-time listener for when the view is ready - const disposable = provider.on("clineAdded", () => { + const disposable = provider.on("clineCreated", () => { // Clean up the listener disposable.dispose() resolve() diff --git a/src/api/providers/anthropic.ts b/src/api/providers/anthropic.ts index e39b3b1d67d..b65e89e0bb3 100644 --- a/src/api/providers/anthropic.ts +++ b/src/api/providers/anthropic.ts @@ -105,16 +105,18 @@ export class AnthropicHandler extends BaseProvider implements SingleCompletionHa case "claude-3-opus-20240229": case "claude-3-haiku-20240307": betas.push("prompt-caching-2024-07-31") - // Include prompt_key if newProjectType is set return { headers: { "anthropic-beta": betas.join(","), - ...(String(this.options.newProjectType) - ? { prompt_key: String(this.options.newProjectType) } - : {}), + prompt_key: this.options.creatorModeConfig?.newProjectType + ? String(this.options.creatorModeConfig.newProjectType) + : undefined, + project_path: this.options.creatorModeConfig?.newProjectPath + ? String(this.options.creatorModeConfig.newProjectPath) + : undefined, + authorization: `Bearer ${this.options.apiKey}`, }, - authorization: `Bearer ${this.options.apiKey}`, } default: return undefined diff --git a/src/core/Cline.ts b/src/core/Cline.ts index c76ecebccb6..4b627a27262 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -11,7 +11,7 @@ import { serializeError } from "serialize-error" import * as vscode from "vscode" // schemas -import { TokenUsage, ToolUsage, ToolName, ModelInfo } from "../schemas" +import { TokenUsage, ToolUsage, ToolName, ModelInfo, CreatorModeConfig } from "../schemas" // api import { ApiHandler, buildApiHandler } from "../api" @@ -127,8 +127,7 @@ export type ClineOptions = { taskNumber?: number onCreated?: (cline: Cline) => void pearaiModels?: Record - creatorMode?: boolean - newProjectType?: string + creatorModeConfig?: CreatorModeConfig } export class Cline extends EventEmitter { @@ -144,8 +143,7 @@ export class Cline extends EventEmitter { pausedModeSlug: string = defaultModeSlug private pauseInterval: NodeJS.Timeout | undefined - public creatorMode: boolean - public newProjectType: string + public creatorModeConfig: CreatorModeConfig readonly apiConfiguration: ApiConfiguration api: ApiHandler private promptCacheKey: string @@ -224,8 +222,7 @@ export class Cline extends EventEmitter { parentTask, taskNumber = -1, onCreated, - creatorMode, - newProjectType, + creatorModeConfig, }: ClineOptions) { super() @@ -263,8 +260,7 @@ export class Cline extends EventEmitter { this.diffViewProvider = new DiffViewProvider(this.cwd) this.enableCheckpoints = enableCheckpoints - this.creatorMode = creatorMode ?? false - this.newProjectType = newProjectType ?? "" + this.creatorModeConfig = creatorModeConfig ?? { creatorMode: false } this.rootTask = rootTask this.parentTask = parentTask diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 659df144af7..0f811f090d9 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -9,7 +9,7 @@ import axios from "axios" import pWaitFor from "p-wait-for" import * as vscode from "vscode" -import { GlobalState, ProviderSettings, RooCodeSettings } from "../../schemas" +import { CreatorModeConfig, GlobalState, ProviderSettings, RooCodeSettings } from "../../schemas" import { t } from "../../i18n" import { setPanel } from "../../activate/registerCommands" import { @@ -482,8 +482,7 @@ export class ClineProvider extends EventEmitter implements | "experiments" > > = {}, - creatorMode?: boolean, - newProjectType?: string, + creatorModeConfig?: CreatorModeConfig, ) { const { apiConfiguration, @@ -499,8 +498,7 @@ export class ClineProvider extends EventEmitter implements // Update API configuration with creator mode await this.updateApiConfiguration({ ...apiConfiguration, - creatorMode, - newProjectType, + creatorModeConfig, }) // Post updated state to webview immediately @@ -515,9 +513,10 @@ export class ClineProvider extends EventEmitter implements provider: this, apiConfiguration: { ...apiConfiguration, - pearaiAgentModels: pearaiAgentModels, - creatorMode, + creatorModeConfig, + pearaiAgentModels, }, + creatorModeConfig, customInstructions: effectiveInstructions, enableDiff, enableCheckpoints, @@ -530,8 +529,6 @@ export class ClineProvider extends EventEmitter implements taskNumber: this.clineStack.length + 1, onCreated: (cline) => this.emit("clineCreated", cline), ...options, - creatorMode, - newProjectType, }) await this.addClineToStack(cline) @@ -855,9 +852,8 @@ export class ClineProvider extends EventEmitter implements // Preserve creator mode when updating configuration const updatedConfig = { ...providerSettings, - creatorMode: currentCline?.creatorMode, - newProjectType: currentCline?.newProjectType, - } satisfies ProviderSettings; + creatorModeConfig: currentCline?.creatorModeConfig, + } if (mode) { const currentApiConfigName = this.getGlobalState("currentApiConfigName") @@ -1250,8 +1246,7 @@ export class ClineProvider extends EventEmitter implements // Construct API configuration with creator mode const apiConfiguration = { ...baseApiConfiguration, - creatorMode: currentCline?.creatorMode, - newProjectType: currentCline?.newProjectType, + creatorModeConfig: currentCline?.creatorModeConfig, } const telemetryKey = process.env.POSTHOG_API_KEY diff --git a/src/exports/roo-code.d.ts b/src/exports/roo-code.d.ts index 7978f5a3850..c6069a5d225 100644 --- a/src/exports/roo-code.d.ts +++ b/src/exports/roo-code.d.ts @@ -202,8 +202,13 @@ type ProviderSettings = { defaultModelId?: string | undefined } | undefined - creatorMode?: boolean | undefined - newProjectType?: string | undefined + creatorModeConfig?: + | { + creatorMode?: boolean | undefined + newProjectType?: string | undefined + newProjectPath?: string | undefined + } + | undefined } type GlobalSettings = { diff --git a/src/exports/types.ts b/src/exports/types.ts index 69b1f9f4d79..2795442a125 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -203,8 +203,13 @@ type ProviderSettings = { defaultModelId?: string | undefined } | undefined - creatorMode?: boolean | undefined - newProjectType?: string | undefined + creatorModeConfig?: + | { + creatorMode?: boolean | undefined + newProjectType?: string | undefined + newProjectPath?: string | undefined + } + | undefined } export type { ProviderSettings } diff --git a/src/schemas/index.ts b/src/schemas/index.ts index edfdb2d32a1..6aa954e1c58 100644 --- a/src/schemas/index.ts +++ b/src/schemas/index.ts @@ -339,6 +339,14 @@ export type Experiments = z.infer type _AssertExperiments = AssertEqual>> +export const creatorModeConfigSchema = z.object({ + creatorMode: z.boolean().optional(), + newProjectType: z.string().optional(), + newProjectPath: z.string().optional(), +}); + +export type CreatorModeConfig = z.infer + /** * ProviderSettings */ @@ -449,8 +457,7 @@ export const providerSettingsSchema = z.object({ defaultModelId: z.string().optional(), }) .optional(), - creatorMode: z.boolean().optional(), - newProjectType: z.string().optional(), + creatorModeConfig: creatorModeConfigSchema.optional(), }) export type ProviderSettings = z.infer @@ -548,8 +555,7 @@ const providerSettingsRecord: ProviderSettingsRecord = { pearaiApiKey: undefined, pearaiModelInfo: undefined, pearaiAgentModels: undefined, - creatorMode: undefined, - newProjectType: undefined, + creatorModeConfig: undefined, // X.AI (Grok) xaiApiKey: undefined, } diff --git a/src/shared/pearaiApi.ts b/src/shared/pearaiApi.ts index c0a5e4d3656..0d110218aa3 100644 --- a/src/shared/pearaiApi.ts +++ b/src/shared/pearaiApi.ts @@ -1,8 +1,8 @@ // CHANGE AS NEEDED FOR DEVELOPMENT // PROD: -// export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" +export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" // DEV: -export const PEARAI_URL = "http://localhost:8000/integrations/cline" +// export const PEARAI_URL = "http://localhost:8000/integrations/cline" import { anthropicModels, diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 2bc0fb98f14..69795636d48 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1238,7 +1238,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction - {apiConfiguration?.creatorMode === true && ( + {apiConfiguration?.creatorModeConfig?.creatorMode === true && ( )} {task ? ( From 53b876cb2a60f2e29a5f263a0fb39b19e029249f Mon Sep 17 00:00:00 2001 From: James Arnott Date: Tue, 6 May 2025 19:28:02 +0100 Subject: [PATCH 41/80] fix:build --- package-lock.json | 1 + src/core/webview/ClineProvider.ts | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index 4d90382ae92..5abe8b91a57 100644 --- a/package-lock.json +++ b/package-lock.json @@ -17081,6 +17081,7 @@ "resolved": "https://registry.npmjs.org/npm-run-all/-/npm-run-all-4.1.5.tgz", "integrity": "sha512-Oo82gJDAVcaMdi3nuoKFavkIHBRVqQ1qvMb+9LHk/cF4P6B2m8aP04hGf7oL6wZ9BuGwX1onlLhpuoofSyoQDQ==", "dev": true, + "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "chalk": "^2.4.1", diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 0f811f090d9..761f3052d54 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -850,10 +850,11 @@ export class ClineProvider extends EventEmitter implements const currentCline = this.getCurrentCline() // Preserve creator mode when updating configuration - const updatedConfig = { + const updatedConfig: ProviderSettings = { ...providerSettings, creatorModeConfig: currentCline?.creatorModeConfig, } + if (mode) { const currentApiConfigName = this.getGlobalState("currentApiConfigName") From dd80a75c24a31bfc2239a7d61c2f202bd340f328 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Thu, 8 May 2025 18:11:20 +0100 Subject: [PATCH 42/80] chore: spelling + types --- src/activate/registerPearListener.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 0120332522a..7a51f905627 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -46,14 +46,14 @@ export const registerPearListener = async () => { // Wait a brief moment for UI to update await new Promise((resolve) => setTimeout(resolve, 300)) - let creatorModeConifig = { + let creatorModeConfig = { creatorMode: msg.creatorMode, newProjectType: msg.newProjectType, newProjectPath: msg.newProjectPath, } satisfies CreatorModeConfig; // Initialize with task - await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConifig) + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig) } }) } else { From b16e957df149b4ee6a274261c097989eb4b162d7 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 11:02:07 +0100 Subject: [PATCH 43/80] fix: not using deep compare effect --- webview-ui/src/components/chat/ChatView.tsx | 352 ++++++++++---------- 1 file changed, 176 insertions(+), 176 deletions(-) diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 69795636d48..f2272f52d11 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -160,182 +160,6 @@ const ChatViewComponent: React.ForwardRefRenderFunction { - // if last message is an ask, show user ask UI - // if user finished a task, then start a new task with a new conversation history since in this moment that the extension is waiting for user response, the user could close the extension and the conversation history would be lost. - // basically as long as a task is active, the conversation history will be persisted - if (lastMessage) { - switch (lastMessage.type) { - case "ask": - const isPartial = lastMessage.partial === true - switch (lastMessage.ask) { - case "api_req_failed": - playSound("progress_loop") - setTextAreaDisabled(true) - setClineAsk("api_req_failed") - setEnableButtons(true) - setPrimaryButtonText(t("chat:retry.title")) - setSecondaryButtonText(t("chat:startNewTask.title")) - break - case "mistake_limit_reached": - playSound("progress_loop") - setTextAreaDisabled(false) - setClineAsk("mistake_limit_reached") - setEnableButtons(true) - setPrimaryButtonText(t("chat:proceedAnyways.title")) - setSecondaryButtonText(t("chat:startNewTask.title")) - break - case "followup": - if (!isPartial) { - playSound("notification") - } - setTextAreaDisabled(isPartial) - setClineAsk("followup") - // setting enable buttons to `false` would trigger a focus grab when - // the text area is enabled which is undesirable. - // We have no buttons for this tool, so no problem having them "enabled" - // to workaround this issue. See #1358. - setEnableButtons(true) - setPrimaryButtonText(undefined) - setSecondaryButtonText(undefined) - break - case "tool": - if (!isAutoApproved(lastMessage) && !isPartial) { - playSound("notification") - } - setTextAreaDisabled(isPartial) - setClineAsk("tool") - setEnableButtons(!isPartial) - const tool = JSON.parse(lastMessage.text || "{}") as ClineSayTool - switch (tool.tool) { - case "editedExistingFile": - case "appliedDiff": - case "newFileCreated": - case "insertContent": - setPrimaryButtonText(t("chat:save.title")) - setSecondaryButtonText(t("chat:reject.title")) - break - case "finishTask": - setPrimaryButtonText(t("chat:completeSubtaskAndReturn")) - setSecondaryButtonText(undefined) - break - default: - setPrimaryButtonText(t("chat:approve.title")) - setSecondaryButtonText(t("chat:reject.title")) - break - } - break - case "browser_action_launch": - if (!isAutoApproved(lastMessage) && !isPartial) { - playSound("notification") - } - setTextAreaDisabled(isPartial) - setClineAsk("browser_action_launch") - setEnableButtons(!isPartial) - setPrimaryButtonText(t("chat:approve.title")) - setSecondaryButtonText(t("chat:reject.title")) - break - case "command": - if (!isAutoApproved(lastMessage) && !isPartial) { - playSound("notification") - } - setTextAreaDisabled(isPartial) - setClineAsk("command") - setEnableButtons(!isPartial) - setPrimaryButtonText(t("chat:runCommand.title")) - setSecondaryButtonText(t("chat:reject.title")) - break - case "command_output": - setTextAreaDisabled(false) - setClineAsk("command_output") - setEnableButtons(true) - setPrimaryButtonText(t("chat:proceedWhileRunning.title")) - setSecondaryButtonText(t("chat:killCommand.title")) - break - case "use_mcp_server": - if (!isAutoApproved(lastMessage) && !isPartial) { - playSound("notification") - } - setTextAreaDisabled(isPartial) - setClineAsk("use_mcp_server") - setEnableButtons(!isPartial) - setPrimaryButtonText(t("chat:approve.title")) - setSecondaryButtonText(t("chat:reject.title")) - break - case "completion_result": - // extension waiting for feedback. but we can just present a new task button - if (!isPartial) { - playSound("celebration") - } - setTextAreaDisabled(isPartial) - setClineAsk("completion_result") - setEnableButtons(!isPartial) - setPrimaryButtonText(t("chat:startNewTask.title")) - setSecondaryButtonText(undefined) - break - case "resume_task": - if (!isAutoApproved(lastMessage) && !isPartial) { - playSound("notification") - } - setTextAreaDisabled(false) - setClineAsk("resume_task") - setEnableButtons(true) - setPrimaryButtonText(t("chat:resumeTask.title")) - setSecondaryButtonText(t("chat:terminate.title")) - setDidClickCancel(false) // special case where we reset the cancel button state - break - case "resume_completed_task": - if (!isPartial) { - playSound("celebration") - } - setTextAreaDisabled(false) - setClineAsk("resume_completed_task") - setEnableButtons(true) - setPrimaryButtonText(t("chat:startNewTask.title")) - setSecondaryButtonText(undefined) - setDidClickCancel(false) - break - } - break - case "say": - // Don't want to reset since there could be a "say" after - // an "ask" while ask is waiting for response. - switch (lastMessage.say) { - case "api_req_retry_delayed": - setTextAreaDisabled(true) - break - case "api_req_started": - if (secondLastMessage?.ask === "command_output") { - // If the last ask is a command_output, and we - // receive an api_req_started, then that means - // the command has finished and we don't need - // input from the user anymore (in every other - // case, the user has to interact with input - // field or buttons to continue, which does the - // following automatically). - setInputValue("") - setTextAreaDisabled(true) - setSelectedImages([]) - setClineAsk(undefined) - setEnableButtons(false) - } - break - case "api_req_finished": - case "error": - case "text": - case "browser_action": - case "browser_action_result": - case "command_output": - case "mcp_server_request_started": - case "mcp_server_response": - case "completion_result": - break - } - break - } - } - }, [lastMessage, secondLastMessage]) - useEffect(() => { if (messages.length === 0) { setTextAreaDisabled(false) @@ -850,6 +674,182 @@ const ChatViewComponent: React.ForwardRefRenderFunction { + // if last message is an ask, show user ask UI + // if user finished a task, then start a new task with a new conversation history since in this moment that the extension is waiting for user response, the user could close the extension and the conversation history would be lost. + // basically as long as a task is active, the conversation history will be persisted + if (lastMessage) { + switch (lastMessage.type) { + case "ask": + const isPartial = lastMessage.partial === true + switch (lastMessage.ask) { + case "api_req_failed": + playSound("progress_loop") + setTextAreaDisabled(true) + setClineAsk("api_req_failed") + setEnableButtons(true) + setPrimaryButtonText(t("chat:retry.title")) + setSecondaryButtonText(t("chat:startNewTask.title")) + break + case "mistake_limit_reached": + playSound("progress_loop") + setTextAreaDisabled(false) + setClineAsk("mistake_limit_reached") + setEnableButtons(true) + setPrimaryButtonText(t("chat:proceedAnyways.title")) + setSecondaryButtonText(t("chat:startNewTask.title")) + break + case "followup": + if (!isPartial) { + playSound("notification") + } + setTextAreaDisabled(isPartial) + setClineAsk("followup") + // setting enable buttons to `false` would trigger a focus grab when + // the text area is enabled which is undesirable. + // We have no buttons for this tool, so no problem having them "enabled" + // to workaround this issue. See #1358. + setEnableButtons(true) + setPrimaryButtonText(undefined) + setSecondaryButtonText(undefined) + break + case "tool": + if (!isAutoApproved(lastMessage) && !isPartial) { + playSound("notification") + } + setTextAreaDisabled(isPartial) + setClineAsk("tool") + setEnableButtons(!isPartial) + const tool = JSON.parse(lastMessage.text || "{}") as ClineSayTool + switch (tool.tool) { + case "editedExistingFile": + case "appliedDiff": + case "newFileCreated": + case "insertContent": + setPrimaryButtonText(t("chat:save.title")) + setSecondaryButtonText(t("chat:reject.title")) + break + case "finishTask": + setPrimaryButtonText(t("chat:completeSubtaskAndReturn")) + setSecondaryButtonText(undefined) + break + default: + setPrimaryButtonText(t("chat:approve.title")) + setSecondaryButtonText(t("chat:reject.title")) + break + } + break + case "browser_action_launch": + if (!isAutoApproved(lastMessage) && !isPartial) { + playSound("notification") + } + setTextAreaDisabled(isPartial) + setClineAsk("browser_action_launch") + setEnableButtons(!isPartial) + setPrimaryButtonText(t("chat:approve.title")) + setSecondaryButtonText(t("chat:reject.title")) + break + case "command": + if (!isAutoApproved(lastMessage) && !isPartial) { + playSound("notification") + } + setTextAreaDisabled(isPartial) + setClineAsk("command") + setEnableButtons(!isPartial) + setPrimaryButtonText(t("chat:runCommand.title")) + setSecondaryButtonText(t("chat:reject.title")) + break + case "command_output": + setTextAreaDisabled(false) + setClineAsk("command_output") + setEnableButtons(true) + setPrimaryButtonText(t("chat:proceedWhileRunning.title")) + setSecondaryButtonText(t("chat:killCommand.title")) + break + case "use_mcp_server": + if (!isAutoApproved(lastMessage) && !isPartial) { + playSound("notification") + } + setTextAreaDisabled(isPartial) + setClineAsk("use_mcp_server") + setEnableButtons(!isPartial) + setPrimaryButtonText(t("chat:approve.title")) + setSecondaryButtonText(t("chat:reject.title")) + break + case "completion_result": + // extension waiting for feedback. but we can just present a new task button + if (!isPartial) { + playSound("celebration") + } + setTextAreaDisabled(isPartial) + setClineAsk("completion_result") + setEnableButtons(!isPartial) + setPrimaryButtonText(t("chat:startNewTask.title")) + setSecondaryButtonText(undefined) + break + case "resume_task": + if (!isAutoApproved(lastMessage) && !isPartial) { + playSound("notification") + } + setTextAreaDisabled(false) + setClineAsk("resume_task") + setEnableButtons(true) + setPrimaryButtonText(t("chat:resumeTask.title")) + setSecondaryButtonText(t("chat:terminate.title")) + setDidClickCancel(false) // special case where we reset the cancel button state + break + case "resume_completed_task": + if (!isPartial) { + playSound("celebration") + } + setTextAreaDisabled(false) + setClineAsk("resume_completed_task") + setEnableButtons(true) + setPrimaryButtonText(t("chat:startNewTask.title")) + setSecondaryButtonText(undefined) + setDidClickCancel(false) + break + } + break + case "say": + // Don't want to reset since there could be a "say" after + // an "ask" while ask is waiting for response. + switch (lastMessage.say) { + case "api_req_retry_delayed": + setTextAreaDisabled(true) + break + case "api_req_started": + if (secondLastMessage?.ask === "command_output") { + // If the last ask is a command_output, and we + // receive an api_req_started, then that means + // the command has finished and we don't need + // input from the user anymore (in every other + // case, the user has to interact with input + // field or buttons to continue, which does the + // following automatically). + setInputValue("") + setTextAreaDisabled(true) + setSelectedImages([]) + setClineAsk(undefined) + setEnableButtons(false) + } + break + case "api_req_finished": + case "error": + case "text": + case "browser_action": + case "browser_action_result": + case "command_output": + case "mcp_server_request_started": + case "mcp_server_response": + case "completion_result": + break + } + break + } + } + }, [lastMessage, secondLastMessage, isAutoApproved, t]) + useEffect(() => { // This ensures the first message is not read, future user messages are // labeled as `user_feedback`. From 78f1dc0a6e5ad7eeee7184776cb3de84171899ce Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 12:20:31 +0100 Subject: [PATCH 44/80] fix: creator shizz --- src/activate/registerPearListener.ts | 68 ++++++++++++++++------------ 1 file changed, 38 insertions(+), 30 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 7a51f905627..9d0d62ba6e3 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -24,38 +24,46 @@ export const registerPearListener = async () => { if (pearAiExtension.exports) { pearAiExtension.exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg: any) => { console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`) - // Get the sidebar provider - const sidebarProvider = ClineProvider.getSidebarInstance() - - if (sidebarProvider) { - // Focus the sidebar first - await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") - - // Wait for the view to be ready using a helper function - await ensureViewIsReady(sidebarProvider) - - if (msg.creatorModeConfig?.creatorMode) { - // Switch to creator mode - await sidebarProvider.handleModeSwitch("creator") - await sidebarProvider.postStateToWebview() - } - // Navigate to chat view - await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) - - // Wait a brief moment for UI to update - await new Promise((resolve) => setTimeout(resolve, 300)) - - let creatorModeConfig = { - creatorMode: msg.creatorMode, - newProjectType: msg.newProjectType, - newProjectPath: msg.newProjectPath, - } satisfies CreatorModeConfig; - - // Initialize with task - await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig) + let sidebarProvider = ClineProvider.getVisibleInstance() + + // TODO: LOOK INTO THIS - THIS IS A JANKY FIX AND IT FEELS LIKE THIS IS TEMPERAMENTAL + while (!sidebarProvider) { + await new Promise((resolve) => setTimeout(resolve, 500)) + sidebarProvider = ClineProvider.getVisibleInstance() } - }) + + // Focus the sidebar first + await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") + + // Wait for the view to be ready using a helper function + await ensureViewIsReady(sidebarProvider) + + if (msg.creatorModeConfig?.creatorMode) { + // Switch to creator mode + await sidebarProvider.handleModeSwitch("creator") + await sidebarProvider.postStateToWebview() + } + // Navigate to chat view + await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) + + // Wait a brief moment for UI to update + await new Promise((resolve) => setTimeout(resolve, 300)) + + let creatorModeConfig = { + creatorMode: true, + newProjectType: msg.newProjectType, + newProjectPath: msg.newProjectPath, + } + + console.log('Called init with taskk', msg.plan, undefined, undefined, undefined, creatorModeConfig); + + // Initialize with task + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig); + }); + // If there's a creator event in the cache after the extensions were refreshed, we need to get it! + pearAiExtension.exports.pearAPI.creatorMode.triggerCachedCreatorEvent(true); + console.log("triggerCachedCreatorEvent CALLED!") } else { console.error("⚠️⚠️ PearAI API not available in exports ⚠️⚠️") } From c9ca0fcf79c4d9b874cd6cb041879d6492e46243 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 16:46:55 +0100 Subject: [PATCH 45/80] fix: creator mode style --- webview-ui/src/components/chat/ChatView.tsx | 4 +- .../src/components/chat/CreatorModeBar.tsx | 64 ------------------ .../src/components/chat/PlanningBar.tsx | 65 +++++++++++++++++++ webview-ui/src/index.css | 55 ++++++++++++++++ 4 files changed, 122 insertions(+), 66 deletions(-) delete mode 100644 webview-ui/src/components/chat/CreatorModeBar.tsx create mode 100644 webview-ui/src/components/chat/PlanningBar.tsx diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index f2272f52d11..04a3df32d7e 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -49,7 +49,7 @@ import { vscInputBorder, vscSidebarBorder, } from "../ui" -import { CreatorModeBar } from "./CreatorModeBar" +import { PlanningBar } from "./PlanningBar" import SystemPromptWarning from "./SystemPromptWarning" import { usePearAIModels } from "@/hooks/usePearAIModels" @@ -1239,7 +1239,7 @@ const ChatViewComponent: React.ForwardRefRenderFunction {apiConfiguration?.creatorModeConfig?.creatorMode === true && ( - + )} {task ? ( <> diff --git a/webview-ui/src/components/chat/CreatorModeBar.tsx b/webview-ui/src/components/chat/CreatorModeBar.tsx deleted file mode 100644 index c9007cec2ed..00000000000 --- a/webview-ui/src/components/chat/CreatorModeBar.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { CodeBracketIcon, PlayIcon, DocumentTextIcon as OutlineDocumentTextIcon } from "@heroicons/react/24/outline" -import { Button } from "./button" -import { DocumentTextIcon as SolidDocumentTextIcon } from "@heroicons/react/24/solid" -import { FC } from "react" -import { cn } from "@/lib/utils" - -export type PlanningBarProps = { - isGenerating?: boolean - requestedPlan: string - playCallback?: () => void - nextCallback?: () => void - className?: string -} -// from: https://vscode.dev/github/trypear/pearai-submodule/blob/acorn/253-submodule-api-fixed/gui/src/pages/creator/ui/planningBar.tsx#L15-L50 -// TODO: UI LIBRARY COMPONENT SHARING SHIZZ HERE! - -export const CreatorModeBar: FC = ({ - isGenerating, - requestedPlan, - playCallback, - nextCallback, - className, -}) => { - return ( -
- {isGenerating &&
} -
-
-
-
-
Planning
-
-
{requestedPlan}
-
-
- -
-
- - - -
- - {/* */} -
-
- ) -} diff --git a/webview-ui/src/components/chat/PlanningBar.tsx b/webview-ui/src/components/chat/PlanningBar.tsx new file mode 100644 index 00000000000..937022d1841 --- /dev/null +++ b/webview-ui/src/components/chat/PlanningBar.tsx @@ -0,0 +1,65 @@ +import { CodeBracketIcon } from "@heroicons/react/24/outline" +import { Button } from "./button" +import { DocumentTextIcon as SolidDocumentTextIcon } from "@heroicons/react/24/solid" +import { FC } from "react" +import { cn } from "@/lib/utils" + +export type PlanningBarProps = { + isGenerating?: boolean; + requestedPlan: string; + nextCallback?: () => void; + className?: string; +}; + +export const PlanningBar: FC = ({ + isGenerating, + requestedPlan, + nextCallback, + className, +}) => { + return ( +
+ {/* {isGenerating &&
} */} +
+
+
+
+
Planning
+
+
+ {requestedPlan} +
+
+
+ +
+
+ + +
+ + {/* */} +
+
+ ); +}; diff --git a/webview-ui/src/index.css b/webview-ui/src/index.css index f8bf1ab5a64..97f049e3447 100644 --- a/webview-ui/src/index.css +++ b/webview-ui/src/index.css @@ -413,3 +413,58 @@ input[cmdk-input]:focus { .codicon[class*="codicon-"] { text-rendering: geometricPrecision !important; } + + +/* _-_-_-_-_-_-_-_- PEARAI CREATOR STYLES _-_-_-_-_-_-_-_- */ + +.circle { + position: absolute; + left: 50%; + top: 50%; + transform: translateX(-50%) translateY(-50%); + width: 10px; + height: 10px; +} + +/* Static green dot */ +.circle::after { + content: ""; + position: absolute; + left: 0; + top: 0; + display: block; + width: 100%; + height: 100%; + background-color: #75daad; + border-radius: 50px; + z-index: 2; +} + +/* Pulsing outer ring */ +.animated-circle::before { + content: ""; + position: absolute; + left: 0; + top: 0; + display: block; + width: 100%; + height: 100%; + border-radius: 50px; + background-color: #75daad; + opacity: 0.6; + z-index: 1; + animation: pulse-ring 1.5s cubic-bezier(0.215, 0.61, 0.355, 1) infinite; +} + +@keyframes pulse-ring { + 0% { + transform: scale(1); + opacity: 0.6; + } + 100% { + transform: scale(3); + opacity: 0; + } +} + +/* _-_-_-_-_-_-_-_- PEARAI CREATOR STYLES _-_-_-_-_-_-_-_- */ From 669bd55c4f7c0f456388f5a6cecef0b13a79f127 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 17:24:58 +0100 Subject: [PATCH 46/80] fix: task + stop btn --- src/activate/registerPearListener.ts | 2 -- webview-ui/src/components/chat/ChatView.tsx | 6 +++- .../src/components/chat/PlanningBar.tsx | 31 ++++++++++--------- .../src/components/chat/button/index.tsx | 2 +- 4 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 9d0d62ba6e3..c4b87ce3035 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -1,8 +1,6 @@ import * as vscode from "vscode" import { ClineProvider } from "../core/webview/ClineProvider" import { assert } from "../utils/util" -import { CreatorModeConfig } from "../schemas" - export const getPearaiExtension = async () => { const pearAiExtension = vscode.extensions.getExtension("pearai.pearai") diff --git a/webview-ui/src/components/chat/ChatView.tsx b/webview-ui/src/components/chat/ChatView.tsx index 04a3df32d7e..76e170c0ae1 100644 --- a/webview-ui/src/components/chat/ChatView.tsx +++ b/webview-ui/src/components/chat/ChatView.tsx @@ -1239,7 +1239,11 @@ const ChatViewComponent: React.ForwardRefRenderFunction {apiConfiguration?.creatorModeConfig?.creatorMode === true && ( - + vscode.postMessage({ type: "cancelTask" })} + /> )} {task ? ( <> diff --git a/webview-ui/src/components/chat/PlanningBar.tsx b/webview-ui/src/components/chat/PlanningBar.tsx index 937022d1841..d6d372a0d90 100644 --- a/webview-ui/src/components/chat/PlanningBar.tsx +++ b/webview-ui/src/components/chat/PlanningBar.tsx @@ -1,26 +1,26 @@ import { CodeBracketIcon } from "@heroicons/react/24/outline" import { Button } from "./button" -import { DocumentTextIcon as SolidDocumentTextIcon } from "@heroicons/react/24/solid" +import { DocumentTextIcon as SolidDocumentTextIcon, StopCircleIcon, StopIcon } from "@heroicons/react/24/solid" import { FC } from "react" import { cn } from "@/lib/utils" export type PlanningBarProps = { isGenerating?: boolean; requestedPlan: string; - nextCallback?: () => void; + stopCallback?: () => void; className?: string; }; export const PlanningBar: FC = ({ isGenerating, requestedPlan, - nextCallback, + stopCallback, className, }) => { return (
@@ -38,26 +38,27 @@ export const PlanningBar: FC = ({
-
+
+
- +
+ + +
- {/* */}
diff --git a/webview-ui/src/components/chat/button/index.tsx b/webview-ui/src/components/chat/button/index.tsx index a5e043aa6e8..82025df2d12 100644 --- a/webview-ui/src/components/chat/button/index.tsx +++ b/webview-ui/src/components/chat/button/index.tsx @@ -6,7 +6,7 @@ import { cn } from "@/lib/utils" // FROM: https://vscode.dev/github/trypear/pearai-submodule/blob/acorn/253-submodule-api-fixed/gui/src/pages/creator/ui/button/index.tsx#L1-L121 // TODO: UI LIBRARY COMPONENT SHARING SHIZZ HERE! const buttonVariants = cva( - "inline-flex items-center justify-center gap-2 border-none whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[#a1a1aa] disabled:pointer-events-none disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", + "inline-flex items-center justify-center gap-2 border-none whitespace-nowrap rounded-md text-sm font-medium transition-colors focus-visible:outline-none focus-visible:ring-1 focus-visible:ring-[#a1a1aa] disabled:pointer-events-none cursor-pointer disabled:cursor-default disabled:opacity-50 [&_svg]:pointer-events-none [&_svg]:size-4 [&_svg]:shrink-0", { variants: { variant: { From 9cc10dbb3011a9c14c9930a128f9876efbac918d Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 17:45:16 +0100 Subject: [PATCH 47/80] feat: added message emitter to handle creator mode updates --- src/activate/registerPearListener.ts | 18 +++++++++++++++++- src/shared/ExtensionMessage.ts | 1 + 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index c4b87ce3035..30c145ce942 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -14,6 +14,9 @@ export const getPearaiExtension = async () => { return pearAiExtension } +// TODO: SHOULD HAVE TYPE SYNCED WITH THE PEARAI SUBMODULE! +type CreatorModeState = "OVERLAY_CLOSED" | "OVERLAY_OPEN" | "OVERLAY_CLOSED_CREATOR_ACTIVE" + export const registerPearListener = async () => { // Getting the pear ai extension instance const pearAiExtension = await getPearaiExtension() @@ -61,7 +64,20 @@ export const registerPearListener = async () => { }); // If there's a creator event in the cache after the extensions were refreshed, we need to get it! pearAiExtension.exports.pearAPI.creatorMode.triggerCachedCreatorEvent(true); - console.log("triggerCachedCreatorEvent CALLED!") + + pearAiExtension.exports.pearAPI.creatorMode.onDidChangeCreatorModeState(async (state: CreatorModeState) => { + // Get the sidebar provider + const sidebarProvider = ClineProvider.getVisibleInstance(); + + if (sidebarProvider) { + // Send a message to the webview that will trigger a window event + sidebarProvider.postMessageToWebview({ + type: "creatorModeUpdate", + text: state, + }); + } + }); + } else { console.error("⚠️⚠️ PearAI API not available in exports ⚠️⚠️") } diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index ec686e5e7e7..5fa819c5cf4 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -68,6 +68,7 @@ export interface ExtensionMessage { | "acceptInput" | "setHistoryPreviewCollapsed" | "commandExecutionStatus" + | "creatorModeUpdate" text?: string action?: | "chatButtonClicked" From a87a3793539d4c3ed3211a8b6855c5874a764d65 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 21:24:46 +0100 Subject: [PATCH 48/80] fix: sizing --- webview-ui/src/components/chat/PlanningBar.tsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/webview-ui/src/components/chat/PlanningBar.tsx b/webview-ui/src/components/chat/PlanningBar.tsx index d6d372a0d90..b6b9a8006f5 100644 --- a/webview-ui/src/components/chat/PlanningBar.tsx +++ b/webview-ui/src/components/chat/PlanningBar.tsx @@ -25,13 +25,13 @@ export const PlanningBar: FC = ({ )} > {/* {isGenerating &&
} */} -
-
+
+
-
Planning
-
-
+
Planning
+
+
{requestedPlan}
From 75953a1befb03b8baec64a34d98bf5b5a41b9c26 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Fri, 9 May 2025 21:29:50 +0100 Subject: [PATCH 49/80] chore: lil switchup --- src/activate/registerPearListener.ts | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 30c145ce942..bd7c6e7f64a 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -39,25 +39,21 @@ export const registerPearListener = async () => { // Wait for the view to be ready using a helper function await ensureViewIsReady(sidebarProvider) - - if (msg.creatorModeConfig?.creatorMode) { - // Switch to creator mode - await sidebarProvider.handleModeSwitch("creator") - await sidebarProvider.postStateToWebview() - } - // Navigate to chat view - await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) - // Wait a brief moment for UI to update await new Promise((resolve) => setTimeout(resolve, 300)) - let creatorModeConfig = { + // * This does actually work but the UI update does not happen. This method calls this.postStateToWebview() so not sure what is going on - James + await sidebarProvider.handleModeSwitch("Creator") + + // Clicl the chat btn + await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) + + const creatorModeConfig = { creatorMode: true, newProjectType: msg.newProjectType, newProjectPath: msg.newProjectPath, } - console.log('Called init with taskk', msg.plan, undefined, undefined, undefined, creatorModeConfig); // Initialize with task await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig); From acba172af6c247dc19b365014f66d2efdced4fa0 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Sat, 10 May 2025 11:41:30 +0100 Subject: [PATCH 50/80] feat: handling the feedback button --- src/activate/registerPearListener.ts | 118 +++++++++--------- src/core/webview/webviewMessageHandler.ts | 9 ++ src/shared/WebviewMessage.ts | 1 + .../src/components/chat/PlanningBar.tsx | 3 +- 4 files changed, 73 insertions(+), 58 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index bd7c6e7f64a..622f3555f7d 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -14,69 +14,73 @@ export const getPearaiExtension = async () => { return pearAiExtension } +// TODO: TYPES +export const getpearAIExports = async () => { + const pearAiExtension = await getPearaiExtension() + + assert(!!pearAiExtension.exports, "⚠️⚠️ Error, no PearAI Exports could be found :( ⚠️⚠️"); + + return pearAiExtension.exports; +} + // TODO: SHOULD HAVE TYPE SYNCED WITH THE PEARAI SUBMODULE! type CreatorModeState = "OVERLAY_CLOSED" | "OVERLAY_OPEN" | "OVERLAY_CLOSED_CREATOR_ACTIVE" export const registerPearListener = async () => { // Getting the pear ai extension instance - const pearAiExtension = await getPearaiExtension() + const exports = await getpearAIExports() + + exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg: any) => { + console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`) + // Get the sidebar provider + let sidebarProvider = ClineProvider.getVisibleInstance() + + // TODO: LOOK INTO THIS - THIS IS A JANKY FIX AND IT FEELS LIKE THIS IS TEMPERAMENTAL + while (!sidebarProvider) { + await new Promise((resolve) => setTimeout(resolve, 500)) + sidebarProvider = ClineProvider.getVisibleInstance() + } + + // Focus the sidebar first + await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") + + // Wait for the view to be ready using a helper function + await ensureViewIsReady(sidebarProvider) + // Wait a brief moment for UI to update + await new Promise((resolve) => setTimeout(resolve, 300)) + + // * This does actually work but the UI update does not happen. This method calls this.postStateToWebview() so not sure what is going on - James + await sidebarProvider.handleModeSwitch("Creator") + + // Clicl the chat btn + await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) + + const creatorModeConfig = { + creatorMode: true, + newProjectType: msg.newProjectType, + newProjectPath: msg.newProjectPath, + } + + + // Initialize with task + await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig); + }); + // If there's a creator event in the cache after the extensions were refreshed, we need to get it! + exports.pearAPI.creatorMode.triggerCachedCreatorEvent(true); + + exports.pearAPI.creatorMode.onDidChangeCreatorModeState(async (state: CreatorModeState) => { + // Get the sidebar provider + const sidebarProvider = ClineProvider.getVisibleInstance(); + + if (sidebarProvider) { + // Send a message to the webview that will trigger a window event + sidebarProvider.postMessageToWebview({ + type: "creatorModeUpdate", + text: state, + }); + } + }); - // Access the API directly from exports - if (pearAiExtension.exports) { - pearAiExtension.exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg: any) => { - console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`) - // Get the sidebar provider - let sidebarProvider = ClineProvider.getVisibleInstance() - - // TODO: LOOK INTO THIS - THIS IS A JANKY FIX AND IT FEELS LIKE THIS IS TEMPERAMENTAL - while (!sidebarProvider) { - await new Promise((resolve) => setTimeout(resolve, 500)) - sidebarProvider = ClineProvider.getVisibleInstance() - } - - // Focus the sidebar first - await vscode.commands.executeCommand("pearai-roo-cline.SidebarProvider.focus") - - // Wait for the view to be ready using a helper function - await ensureViewIsReady(sidebarProvider) - // Wait a brief moment for UI to update - await new Promise((resolve) => setTimeout(resolve, 300)) - - // * This does actually work but the UI update does not happen. This method calls this.postStateToWebview() so not sure what is going on - James - await sidebarProvider.handleModeSwitch("Creator") - - // Clicl the chat btn - await sidebarProvider.postMessageToWebview({ type: "action", action: "chatButtonClicked" }) - - const creatorModeConfig = { - creatorMode: true, - newProjectType: msg.newProjectType, - newProjectPath: msg.newProjectPath, - } - - - // Initialize with task - await sidebarProvider.initClineWithTask(msg.plan, undefined, undefined, undefined, creatorModeConfig); - }); - // If there's a creator event in the cache after the extensions were refreshed, we need to get it! - pearAiExtension.exports.pearAPI.creatorMode.triggerCachedCreatorEvent(true); - - pearAiExtension.exports.pearAPI.creatorMode.onDidChangeCreatorModeState(async (state: CreatorModeState) => { - // Get the sidebar provider - const sidebarProvider = ClineProvider.getVisibleInstance(); - - if (sidebarProvider) { - // Send a message to the webview that will trigger a window event - sidebarProvider.postMessageToWebview({ - type: "creatorModeUpdate", - text: state, - }); - } - }); - - } else { - console.error("⚠️⚠️ PearAI API not available in exports ⚠️⚠️") - } } // TODO: decide if this is needed diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index ae14b5e1b53..b36d11cc909 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -38,6 +38,7 @@ import { buildApiHandler } from "../../api" import { GlobalState } from "../../schemas" import { MultiSearchReplaceDiffStrategy } from "../diff/strategies/multi-search-replace" import { getModels } from "../../api/providers/fetchers/cache" +import { getpearAIExports } from "../../activate/registerPearListener" export const webviewMessageHandler = async (provider: ClineProvider, message: WebviewMessage) => { // Utility functions provided for concise get/update of global state via contextProxy API. @@ -1269,6 +1270,14 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We ), ) break + case "openPearAICreatorFeedbackOverlay": + const pearAIExports = await getpearAIExports(); + const currentCline = provider.getCurrentCline(); + + + // Open the feedback form with the chat history + pearAIExports.pearAPI.creatorMode.openFeedbackForm(currentCline?.clineMessages || []); + break } } diff --git a/src/shared/WebviewMessage.ts b/src/shared/WebviewMessage.ts index d26a20ee3d9..60bd0a5daa9 100644 --- a/src/shared/WebviewMessage.ts +++ b/src/shared/WebviewMessage.ts @@ -128,6 +128,7 @@ export interface WebviewMessage { | "toggleApiConfigPin" | "setHistoryPreviewCollapsed" | "openPearAIAuth" + | "openPearAICreatorFeedbackOverlay" text?: string disabled?: boolean askResponse?: ClineAskResponse diff --git a/webview-ui/src/components/chat/PlanningBar.tsx b/webview-ui/src/components/chat/PlanningBar.tsx index b6b9a8006f5..6407b670a15 100644 --- a/webview-ui/src/components/chat/PlanningBar.tsx +++ b/webview-ui/src/components/chat/PlanningBar.tsx @@ -3,6 +3,7 @@ import { Button } from "./button" import { DocumentTextIcon as SolidDocumentTextIcon, StopCircleIcon, StopIcon } from "@heroicons/react/24/solid" import { FC } from "react" import { cn } from "@/lib/utils" +import { vscode } from "@src/utils/vscode" export type PlanningBarProps = { isGenerating?: boolean; @@ -52,7 +53,7 @@ export const PlanningBar: FC = ({
- - -
+
+
+
+ + +
- - -
- {/* */} -
-
- ); -}; + + +
+ {/* */} +
+
+ ) +} diff --git a/webview-ui/src/index.css b/webview-ui/src/index.css index 97f049e3447..50603c6ac58 100644 --- a/webview-ui/src/index.css +++ b/webview-ui/src/index.css @@ -467,4 +467,39 @@ input[cmdk-input]:focus { } } +/* Rainbow border glow effect */ +.rainbow-border-glow { + position: absolute; + inset: -2px; + background: linear-gradient( + 90deg, + rgba(255, 128, 128, 0.7) 0%, + rgba(255, 192, 128, 0.7) 14%, + rgba(255, 255, 128, 0.7) 28%, + rgba(128, 255, 128, 0.7) 42%, + rgba(128, 255, 255, 0.7) 56%, + rgba(128, 128, 255, 0.7) 70%, + rgba(192, 128, 255, 0.7) 84%, + rgba(255, 128, 192, 0.7) 100% + ); + background-size: 200% auto; + filter: blur(5px); + animation: rainbow-flow 3s linear infinite; + z-index: -1; /* Ensure it's behind the button */ + opacity: 0; /* Start invisible */ + transition: opacity 0.5s ease; /* Add transition for smooth opacity changes */ +} + +/* Class to show the element */ +.rainbow-border-glow-visible { + opacity: 0.7; +} + +@keyframes rainbow-flow { + to { + background-position: 200% center; + } +} + + /* _-_-_-_-_-_-_-_- PEARAI CREATOR STYLES _-_-_-_-_-_-_-_- */ From 291a9c0d0631ec295af45c278cd295fb3cedafd4 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Mon, 12 May 2025 11:27:33 +0100 Subject: [PATCH 64/80] fix: creator mode new tasks are also in creator mode --- src/core/tools/newTaskTool.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/tools/newTaskTool.ts b/src/core/tools/newTaskTool.ts index dc45c73d3a0..f2e9e178e44 100644 --- a/src/core/tools/newTaskTool.ts +++ b/src/core/tools/newTaskTool.ts @@ -78,7 +78,8 @@ export async function newTaskTool( // Delay to allow mode change to take effect before next tool is executed. await delay(500) - const newCline = await provider.initClineWithTask(message, undefined, cline) + // Pass the creator mode config from the parent task to ensure creator mode is preserved + const newCline = await provider.initClineWithTask(message, undefined, cline, {}, cline.creatorModeConfig) cline.emit("taskSpawned", newCline.taskId) pushToolResult(`Successfully created new task in ${targetMode.name} mode with message: ${message}`) From d3e62e06b7ebe45a5edda5e87ac9dd4f0b0ff355 Mon Sep 17 00:00:00 2001 From: nang-dev Date: Mon, 12 May 2025 14:01:30 -0400 Subject: [PATCH 65/80] rename roo rules (#80) * rename .roo -> .pearai-agent * pearai-agent-ignore * pearai-agent-modes --- .vscodeignore | 3 + src/core/config/CustomModesManager.ts | 14 +- .../__tests__/CustomModesManager.test.ts | 26 +- src/core/ignore/RooIgnoreController.ts | 28 +- .../RooIgnoreController.security.test.ts | 2 +- .../__tests__/custom-system-prompt.test.ts | 5 +- .../__tests__/responses-rooignore.test.ts | 14 +- src/core/prompts/instructions/create-mode.ts | 7 +- src/core/prompts/responses.ts | 3 +- .../__tests__/custom-instructions.test.ts | 216 +++--- .../__tests__/custom-system-prompt.test.ts | 3 +- .../prompts/sections/custom-instructions.ts | 11 +- .../prompts/sections/custom-system-prompt.ts | 9 +- .../webview/__tests__/ClineProvider.test.ts | 5 +- src/core/webview/webviewMessageHandler.ts | 3 +- src/exports/types.ts | 684 +++++++----------- src/i18n/locales/ca/common.json | 2 +- src/i18n/locales/de/common.json | 2 +- src/i18n/locales/en/common.json | 2 +- src/i18n/locales/es/common.json | 2 +- src/i18n/locales/fr/common.json | 2 +- src/i18n/locales/hi/common.json | 2 +- src/i18n/locales/it/common.json | 2 +- src/i18n/locales/ja/common.json | 2 +- src/i18n/locales/ko/common.json | 2 +- src/i18n/locales/pl/common.json | 2 +- src/i18n/locales/pt-BR/common.json | 2 +- src/i18n/locales/ru/common.json | 2 +- src/i18n/locales/tr/common.json | 2 +- src/i18n/locales/vi/common.json | 2 +- src/i18n/locales/zh-CN/common.json | 2 +- src/i18n/locales/zh-TW/common.json | 2 +- src/services/mcp/McpHub.ts | 3 +- src/shared/ExtensionMessage.ts | 2 +- src/shared/constants.ts | 5 + src/shared/pearaiApi.ts | 4 +- src/utils/path.ts | 1 + .../src/components/prompts/PromptsView.tsx | 9 +- .../settings/ContextManagementSettings.tsx | 4 +- .../ContextManagementSettings.test.tsx | 2 +- .../src/context/ExtensionStateContext.tsx | 2 +- webview-ui/src/i18n/locales/ca/prompts.json | 10 +- webview-ui/src/i18n/locales/ca/settings.json | 6 +- webview-ui/src/i18n/locales/de/prompts.json | 10 +- webview-ui/src/i18n/locales/de/settings.json | 6 +- webview-ui/src/i18n/locales/en/prompts.json | 10 +- webview-ui/src/i18n/locales/en/settings.json | 6 +- webview-ui/src/i18n/locales/es/prompts.json | 10 +- webview-ui/src/i18n/locales/es/settings.json | 6 +- webview-ui/src/i18n/locales/fr/prompts.json | 10 +- webview-ui/src/i18n/locales/fr/settings.json | 6 +- webview-ui/src/i18n/locales/hi/prompts.json | 10 +- webview-ui/src/i18n/locales/hi/settings.json | 6 +- webview-ui/src/i18n/locales/it/prompts.json | 10 +- webview-ui/src/i18n/locales/it/settings.json | 6 +- webview-ui/src/i18n/locales/ja/prompts.json | 10 +- webview-ui/src/i18n/locales/ja/settings.json | 2 +- webview-ui/src/i18n/locales/ko/prompts.json | 10 +- webview-ui/src/i18n/locales/ko/settings.json | 4 +- webview-ui/src/i18n/locales/pl/prompts.json | 10 +- webview-ui/src/i18n/locales/pl/settings.json | 6 +- .../src/i18n/locales/pt-BR/prompts.json | 10 +- .../src/i18n/locales/pt-BR/settings.json | 6 +- webview-ui/src/i18n/locales/ru/prompts.json | 10 +- webview-ui/src/i18n/locales/ru/settings.json | 6 +- webview-ui/src/i18n/locales/tr/prompts.json | 10 +- webview-ui/src/i18n/locales/tr/settings.json | 6 +- webview-ui/src/i18n/locales/vi/prompts.json | 10 +- webview-ui/src/i18n/locales/vi/settings.json | 6 +- .../src/i18n/locales/zh-CN/prompts.json | 10 +- .../src/i18n/locales/zh-CN/settings.json | 6 +- .../src/i18n/locales/zh-TW/prompts.json | 10 +- .../src/i18n/locales/zh-TW/settings.json | 6 +- 73 files changed, 621 insertions(+), 726 deletions(-) create mode 100644 src/shared/constants.ts diff --git a/.vscodeignore b/.vscodeignore index 53fd3798c01..1bc718e577e 100644 --- a/.vscodeignore +++ b/.vscodeignore @@ -29,6 +29,9 @@ jest.* .roomodes .rooignore .roo/** +.pearai-agent/** +.pearai-agent-ignore +.pearai-agent-modes benchmark/** cline_docs/** e2e/** diff --git a/src/core/config/CustomModesManager.ts b/src/core/config/CustomModesManager.ts index eed7dee9485..69235e15e31 100644 --- a/src/core/config/CustomModesManager.ts +++ b/src/core/config/CustomModesManager.ts @@ -7,9 +7,9 @@ import { fileExistsAtPath } from "../../utils/fs" import { arePathsEqual, getWorkspacePath } from "../../utils/path" import { logger } from "../../utils/logging" import { GlobalFileNames } from "../../shared/globalFileNames" +import { AGENT_MODES_FILE_NAME } from "../../shared/constants" -const ROOMODES_FILENAME = ".roomodes" - +const ROOMODES_FILENAME = AGENT_MODES_FILE_NAME export class CustomModesManager { private static readonly cacheTTL = 10_000 @@ -154,11 +154,11 @@ export class CustomModesManager { return } - // Get modes from .roomodes if it exists (takes precedence) + // Get modes from .pearai-agent-modes if it exists (takes precedence) const roomodesPath = await this.getWorkspaceRoomodes() const roomodesModes = roomodesPath ? await this.loadModesFromFile(roomodesPath) : [] - // Merge modes from both sources (.roomodes takes precedence) + // Merge modes from both sources (.pearai-agent-modes takes precedence) const mergedModes = await this.mergeCustomModes(roomodesModes, result.data.customModes) await this.context.globalState.update("customModes", mergedModes) this.clearCache() @@ -167,7 +167,7 @@ export class CustomModesManager { }), ) - // Watch .roomodes file if it exists + // Watch .pearai-agent-modes file if it exists const roomodesPath = await this.getWorkspaceRoomodes() if (roomodesPath) { @@ -176,7 +176,7 @@ export class CustomModesManager { if (arePathsEqual(document.uri.fsPath, roomodesPath)) { const settingsModes = await this.loadModesFromFile(settingsPath) const roomodesModes = await this.loadModesFromFile(roomodesPath) - // .roomodes takes precedence + // .pearai-agent-modes takes precedence const mergedModes = await this.mergeCustomModes(roomodesModes, settingsModes) await this.context.globalState.update("customModes", mergedModes) this.clearCache() @@ -199,7 +199,7 @@ export class CustomModesManager { const settingsPath = await this.getCustomModesFilePath() const settingsModes = await this.loadModesFromFile(settingsPath) - // Get modes from .roomodes if it exists. + // Get modes from .pearai-agent-modes if it exists const roomodesPath = await this.getWorkspaceRoomodes() const roomodesModes = roomodesPath ? await this.loadModesFromFile(roomodesPath) : [] diff --git a/src/core/config/__tests__/CustomModesManager.test.ts b/src/core/config/__tests__/CustomModesManager.test.ts index 065f1478285..dabf4e4bcb7 100644 --- a/src/core/config/__tests__/CustomModesManager.test.ts +++ b/src/core/config/__tests__/CustomModesManager.test.ts @@ -23,7 +23,7 @@ describe("CustomModesManager", () => { // Use path.sep to ensure correct path separators for the current platform const mockStoragePath = `${path.sep}mock${path.sep}settings` const mockSettingsPath = path.join(mockStoragePath, "settings", GlobalFileNames.customModes) - const mockRoomodes = `${path.sep}mock${path.sep}workspace${path.sep}.roomodes` + const mockRoomodes = `${path.sep}mock${path.sep}workspace${path.sep}.pearai-agent-ignore` beforeEach(() => { mockOnUpdate = jest.fn() @@ -60,7 +60,7 @@ describe("CustomModesManager", () => { }) describe("getCustomModes", () => { - it("should merge modes with .roomodes taking precedence", async () => { + it("should merge modes with .pearai-agent-ignore taking precedence", async () => { const settingsModes = [ { slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] }, { slug: "mode2", name: "Mode 2", roleDefinition: "Role 2", groups: ["read"] }, @@ -87,13 +87,13 @@ describe("CustomModesManager", () => { expect(modes).toHaveLength(3) expect(modes.map((m) => m.slug)).toEqual(["mode2", "mode3", "mode1"]) - // mode2 should come from .roomodes since it takes precedence + // mode2 should come from .pearai-agent-ignore since it takes precedence const mode2 = modes.find((m) => m.slug === "mode2") expect(mode2?.name).toBe("Mode 2 Override") expect(mode2?.roleDefinition).toBe("Role 2 Override") }) - it("should handle missing .roomodes file", async () => { + it("should handle missing .pearai-agent-ignore file", async () => { const settingsModes = [{ slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] }] ;(fileExistsAtPath as jest.Mock).mockImplementation(async (path: string) => { @@ -112,7 +112,7 @@ describe("CustomModesManager", () => { expect(modes[0].slug).toBe("mode1") }) - it("should handle invalid JSON in .roomodes", async () => { + it("should handle invalid JSON in .pearai-agent-ignore", async () => { const settingsModes = [{ slug: "mode1", name: "Mode 1", roleDefinition: "Role 1", groups: ["read"] }] ;(fs.readFile as jest.Mock).mockImplementation(async (path: string) => { @@ -127,7 +127,7 @@ describe("CustomModesManager", () => { const modes = await manager.getCustomModes() - // Should fall back to settings modes when .roomodes is invalid + // Should fall back to settings modes when .pearai-agent-ignore is invalid expect(modes).toHaveLength(1) expect(modes[0].slug).toBe("mode1") }) @@ -385,7 +385,7 @@ describe("CustomModesManager", () => { }) describe("updateCustomMode", () => { - it("should update mode in settings file while preserving .roomodes precedence", async () => { + it("should update mode in settings file while preserving .pearai-agent-ignore precedence", async () => { const newMode: ModeConfig = { slug: "mode1", name: "Updated Mode 1", @@ -449,13 +449,13 @@ describe("CustomModesManager", () => { }), ) - // Should update global state with merged modes where .roomodes takes precedence + // Should update global state with merged modes where .pearai-agent-ignore takes precedence expect(mockContext.globalState.update).toHaveBeenCalledWith( "customModes", expect.arrayContaining([ expect.objectContaining({ slug: "mode1", - name: "Roomodes Mode 1", // .roomodes version should take precedence + name: "Roomodes Mode 1", // .pearai-agent-ignore version should take precedence source: "project", }), ]), @@ -465,7 +465,7 @@ describe("CustomModesManager", () => { expect(mockOnUpdate).toHaveBeenCalled() }) - it("creates .roomodes file when adding project-specific mode", async () => { + it("creates .pearai-agent-ignore file when adding project-specific mode", async () => { const projectMode: ModeConfig = { slug: "project-mode", name: "Project Mode", @@ -474,7 +474,7 @@ describe("CustomModesManager", () => { source: "project", } - // Mock .roomodes to not exist initially + // Mock .pearai-agent-ignore to not exist initially let roomodesContent: any = null ;(fileExistsAtPath as jest.Mock).mockImplementation(async (path: string) => { return path === mockSettingsPath @@ -500,7 +500,7 @@ describe("CustomModesManager", () => { await manager.updateCustomMode("project-mode", projectMode) - // Verify .roomodes was created with the project mode + // Verify .pearai-agent-ignore was created with the project mode expect(fs.writeFile).toHaveBeenCalledWith( expect.any(String), // Don't check exact path as it may have different separators on different platforms expect.stringContaining("project-mode"), @@ -511,7 +511,7 @@ describe("CustomModesManager", () => { const writeCall = (fs.writeFile as jest.Mock).mock.calls[0] expect(path.normalize(writeCall[0])).toBe(path.normalize(mockRoomodes)) - // Verify the content written to .roomodes + // Verify the content written to .pearai-agent-ignore expect(roomodesContent).toEqual({ customModes: [ expect.objectContaining({ diff --git a/src/core/ignore/RooIgnoreController.ts b/src/core/ignore/RooIgnoreController.ts index fda6c371757..cd794aa9850 100644 --- a/src/core/ignore/RooIgnoreController.ts +++ b/src/core/ignore/RooIgnoreController.ts @@ -3,13 +3,13 @@ import { fileExistsAtPath } from "../../utils/fs" import fs from "fs/promises" import ignore, { Ignore } from "ignore" import * as vscode from "vscode" +import { AGENT_IGNORE_FILE_NAME } from "../../shared/constants" export const LOCK_TEXT_SYMBOL = "\u{1F512}" - /** * Controls LLM access to files by enforcing ignore patterns. * Designed to be instantiated once in Cline.ts and passed to file manipulation services. - * Uses the 'ignore' library to support standard .gitignore syntax in .rooignore files. + * Uses the 'ignore' library to support standard .gitignore syntax in .pearai-agent-ignore files. */ export class RooIgnoreController { private cwd: string @@ -21,7 +21,7 @@ export class RooIgnoreController { this.cwd = cwd this.ignoreInstance = ignore() this.rooIgnoreContent = undefined - // Set up file watcher for .rooignore + // Set up file watcher for .pearai-agent-ignore this.setupFileWatcher() } @@ -34,10 +34,10 @@ export class RooIgnoreController { } /** - * Set up the file watcher for .rooignore changes + * Set up the file watcher for .pearai-agent-ignore changes */ private setupFileWatcher(): void { - const rooignorePattern = new vscode.RelativePattern(this.cwd, ".rooignore") + const rooignorePattern = new vscode.RelativePattern(this.cwd, AGENT_IGNORE_FILE_NAME) const fileWatcher = vscode.workspace.createFileSystemWatcher(rooignorePattern) // Watch for changes and updates @@ -58,24 +58,24 @@ export class RooIgnoreController { } /** - * Load custom patterns from .rooignore if it exists + * Load custom patterns from .pearai-agent-ignore if it exists */ private async loadRooIgnore(): Promise { try { // Reset ignore instance to prevent duplicate patterns this.ignoreInstance = ignore() - const ignorePath = path.join(this.cwd, ".rooignore") + const ignorePath = path.join(this.cwd, AGENT_IGNORE_FILE_NAME) if (await fileExistsAtPath(ignorePath)) { const content = await fs.readFile(ignorePath, "utf8") this.rooIgnoreContent = content this.ignoreInstance.add(content) - this.ignoreInstance.add(".rooignore") + this.ignoreInstance.add(AGENT_IGNORE_FILE_NAME) } else { this.rooIgnoreContent = undefined } } catch (error) { // Should never happen: reading file failed even though it exists - console.error("Unexpected error loading .rooignore:", error) + console.error(`Unexpected error loading ${AGENT_IGNORE_FILE_NAME}:`, error) } } @@ -85,7 +85,7 @@ export class RooIgnoreController { * @returns true if file is accessible, false if ignored */ validateAccess(filePath: string): boolean { - // Always allow access if .rooignore does not exist + // Always allow access if .pearai-agent-ignore does not exist if (!this.rooIgnoreContent) { return true } @@ -109,7 +109,7 @@ export class RooIgnoreController { * @returns path of file that is being accessed if it is being accessed, undefined if command is allowed */ validateCommand(command: string): string | undefined { - // Always allow if no .rooignore exists + // Always allow if no .pearai-agent-ignore exists if (!this.rooIgnoreContent) { return undefined } @@ -188,14 +188,14 @@ export class RooIgnoreController { } /** - * Get formatted instructions about the .rooignore file for the LLM - * @returns Formatted instructions or undefined if .rooignore doesn't exist + * Get formatted instructions about the .pearai-agent-ignore file for the LLM + * @returns Formatted instructions or undefined if .pearai-agent-ignore doesn't exist */ getInstructions(): string | undefined { if (!this.rooIgnoreContent) { return undefined } - return `# .rooignore\n\n(The following is provided by a root-level .rooignore file where the user has specified files and directories that should not be accessed. When using list_files, you'll notice a ${LOCK_TEXT_SYMBOL} next to files that are blocked. Attempting to access the file's contents e.g. through read_file will result in an error.)\n\n${this.rooIgnoreContent}\n.rooignore` + return `# ${AGENT_IGNORE_FILE_NAME}\n\n(The following is provided by a root-level ${AGENT_IGNORE_FILE_NAME} file where the user has specified files and directories that should not be accessed. When using list_files, you'll notice a ${LOCK_TEXT_SYMBOL} next to files that are blocked. Attempting to access the file's contents e.g. through read_file will result in an error.)\n\n${this.rooIgnoreContent}\n${AGENT_IGNORE_FILE_NAME}` } } diff --git a/src/core/ignore/__tests__/RooIgnoreController.security.test.ts b/src/core/ignore/__tests__/RooIgnoreController.security.test.ts index c71c1fcdb6f..91aca076e40 100644 --- a/src/core/ignore/__tests__/RooIgnoreController.security.test.ts +++ b/src/core/ignore/__tests__/RooIgnoreController.security.test.ts @@ -41,7 +41,7 @@ describe("RooIgnoreController Security Tests", () => { mockFileExists = fileExistsAtPath as jest.MockedFunction mockReadFile = fs.readFile as jest.MockedFunction - // By default, setup .rooignore to exist with some patterns + // By default, setup .pearai-agent-ignore to exist with some patterns mockFileExists.mockResolvedValue(true) mockReadFile.mockResolvedValue("node_modules\n.git\nsecrets/**\n*.log\nprivate/") diff --git a/src/core/prompts/__tests__/custom-system-prompt.test.ts b/src/core/prompts/__tests__/custom-system-prompt.test.ts index 977ab051a00..acaeca61a4c 100644 --- a/src/core/prompts/__tests__/custom-system-prompt.test.ts +++ b/src/core/prompts/__tests__/custom-system-prompt.test.ts @@ -3,6 +3,7 @@ import { defaultModeSlug, modes } from "../../../shared/modes" import * as vscode from "vscode" import * as fs from "fs/promises" import { toPosix } from "./utils" +import { AGENT_RULES_DIR } from "../../../shared/constants" // Mock the fs/promises module jest.mock("fs/promises", () => ({ @@ -90,7 +91,7 @@ describe("File-Based Custom System Prompt", () => { const fileCustomSystemPrompt = "Custom system prompt from file" // When called with utf-8 encoding, return a string mockedFs.readFile.mockImplementation((filePath, options) => { - if (toPosix(filePath).includes(`.roo/system-prompt-${defaultModeSlug}`) && options === "utf-8") { + if (toPosix(filePath).includes(`${AGENT_RULES_DIR}/system-prompt-${defaultModeSlug}`) && options === "utf-8") { return Promise.resolve(fileCustomSystemPrompt) } return Promise.reject({ code: "ENOENT" }) @@ -125,7 +126,7 @@ describe("File-Based Custom System Prompt", () => { // Mock the readFile to return content from a file const fileCustomSystemPrompt = "Custom system prompt from file" mockedFs.readFile.mockImplementation((filePath, options) => { - if (toPosix(filePath).includes(`.roo/system-prompt-${defaultModeSlug}`) && options === "utf-8") { + if (toPosix(filePath).includes(`${AGENT_RULES_DIR}/system-prompt-${defaultModeSlug}`) && options === "utf-8") { return Promise.resolve(fileCustomSystemPrompt) } return Promise.reject({ code: "ENOENT" }) diff --git a/src/core/prompts/__tests__/responses-rooignore.test.ts b/src/core/prompts/__tests__/responses-rooignore.test.ts index 46f1bec438a..518f07e4e20 100644 --- a/src/core/prompts/__tests__/responses-rooignore.test.ts +++ b/src/core/prompts/__tests__/responses-rooignore.test.ts @@ -50,9 +50,9 @@ describe("RooIgnore Response Formatting", () => { const errorMessage = formatResponse.rooIgnoreError("secrets/api-keys.json") // Verify error message format - expect(errorMessage).toContain("Access to secrets/api-keys.json is blocked by the .rooignore file settings") + expect(errorMessage).toContain("Access to secrets/api-keys.json is blocked by the .pearai-agent-ignore file settings") expect(errorMessage).toContain("continue in the task without using this file") - expect(errorMessage).toContain("ask the user to update the .rooignore file") + expect(errorMessage).toContain("ask the user to update the .pearai-agent-ignore file") }) /** @@ -207,7 +207,7 @@ describe("RooIgnore Response Formatting", () => { /** * Tests the instructions format */ - it("should format .rooignore instructions for the LLM", async () => { + it("should format .pearai-agent-ignore instructions for the LLM", async () => { // Create controller const controller = new RooIgnoreController(TEST_CWD) await controller.initialize() @@ -216,7 +216,7 @@ describe("RooIgnore Response Formatting", () => { const instructions = controller.getInstructions() // Verify format and content - expect(instructions).toContain("# .rooignore") + expect(instructions).toContain("# .pearai-agent-ignore") expect(instructions).toContain(LOCK_TEXT_SYMBOL) expect(instructions).toContain("node_modules") expect(instructions).toContain(".git") @@ -231,11 +231,11 @@ describe("RooIgnore Response Formatting", () => { /** * Tests null/undefined case */ - it("should return undefined when no .rooignore exists", async () => { - // Set up no .rooignore + it("should return undefined when no .pearai-agent-ignore exists", async () => { + // Set up no .pearai-agent-ignore mockFileExists.mockResolvedValue(false) - // Create controller without .rooignore + // Create controller without .pearai-agent-ignore const controller = new RooIgnoreController(TEST_CWD) await controller.initialize() diff --git a/src/core/prompts/instructions/create-mode.ts b/src/core/prompts/instructions/create-mode.ts index 598e2fccbf4..ad02f6b6ab5 100644 --- a/src/core/prompts/instructions/create-mode.ts +++ b/src/core/prompts/instructions/create-mode.ts @@ -2,6 +2,7 @@ import * as path from "path" import * as vscode from "vscode" import { GlobalFileNames } from "../../../shared/globalFileNames" +import { AGENT_MODES_FILE_NAME } from "../../../shared/constants" export async function createModeInstructions(context: vscode.ExtensionContext | undefined): Promise { if (!context) throw new Error("Missing VSCode Extension Context") @@ -12,12 +13,12 @@ export async function createModeInstructions(context: vscode.ExtensionContext | return ` Custom modes can be configured in two ways: 1. Globally via '${customModesPath}' (created automatically on startup) - 2. Per-workspace via '.roomodes' in the workspace root directory + 2. Per-workspace via '${AGENT_MODES_FILE_NAME}' in the workspace root directory -When modes with the same slug exist in both files, the workspace-specific .roomodes version takes precedence. This allows projects to override global modes or define project-specific modes. +When modes with the same slug exist in both files, the workspace-specific ${AGENT_MODES_FILE_NAME} version takes precedence. This allows projects to override global modes or define project-specific modes. -If asked to create a project mode, create it in .roomodes in the workspace root. If asked to create a global mode, use the global custom modes file. +If asked to create a project mode, create it in ${AGENT_MODES_FILE_NAME} in the workspace root. If asked to create a global mode, use the global custom modes file. - The following fields are required and must not be empty: * slug: A valid slug (lowercase letters, numbers, and hyphens). Must be unique, and shorter is better. diff --git a/src/core/prompts/responses.ts b/src/core/prompts/responses.ts index 314387171af..9c82a848804 100644 --- a/src/core/prompts/responses.ts +++ b/src/core/prompts/responses.ts @@ -2,6 +2,7 @@ import { Anthropic } from "@anthropic-ai/sdk" import * as path from "path" import * as diff from "diff" import { RooIgnoreController, LOCK_TEXT_SYMBOL } from "../ignore/RooIgnoreController" +import { AGENT_IGNORE_FILE_NAME } from "../../shared/constants" export const formatResponse = { toolDenied: () => `The user denied this operation.`, @@ -15,7 +16,7 @@ export const formatResponse = { toolError: (error?: string) => `The tool execution failed with the following error:\n\n${error}\n`, rooIgnoreError: (path: string) => - `Access to ${path} is blocked by the .rooignore file settings. You must try to continue in the task without using this file, or ask the user to update the .rooignore file.`, + `Access to ${path} is blocked by the ${AGENT_IGNORE_FILE_NAME} file settings. You must try to continue in the task without using this file, or ask the user to update the ${AGENT_IGNORE_FILE_NAME} file.`, noToolsUsed: () => `[ERROR] You did not use a tool in your previous response! Please retry with a tool use. diff --git a/src/core/prompts/sections/__tests__/custom-instructions.test.ts b/src/core/prompts/sections/__tests__/custom-instructions.test.ts index e243526d210..5a4ef4cbfcd 100644 --- a/src/core/prompts/sections/__tests__/custom-instructions.test.ts +++ b/src/core/prompts/sections/__tests__/custom-instructions.test.ts @@ -42,7 +42,7 @@ describe("loadRuleFiles", () => { }) it("should read and trim file content", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockResolvedValue(" content with spaces ") const result = await loadRuleFiles("/fake/path") @@ -51,7 +51,7 @@ describe("loadRuleFiles", () => { }) it("should handle ENOENT error", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "ENOENT" }) const result = await loadRuleFiles("/fake/path") @@ -59,7 +59,7 @@ describe("loadRuleFiles", () => { }) it("should handle EISDIR error", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "EISDIR" }) const result = await loadRuleFiles("/fake/path") @@ -67,7 +67,7 @@ describe("loadRuleFiles", () => { }) it("should throw on unexpected errors", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) const error = new Error("Permission denied") as NodeJS.ErrnoException error.code = "EPERM" @@ -79,7 +79,7 @@ describe("loadRuleFiles", () => { }) it("should not combine content from multiple rule files when they exist", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockImplementation((filePath: PathLike) => { if (filePath.toString().endsWith(".roorules")) { @@ -96,7 +96,7 @@ describe("loadRuleFiles", () => { }) it("should handle when no rule files exist", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "ENOENT" }) @@ -105,7 +105,7 @@ describe("loadRuleFiles", () => { }) it("should skip directories with same name as rule files", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockImplementation((filePath: PathLike) => { if (filePath.toString().endsWith(".roorules")) { @@ -121,16 +121,16 @@ describe("loadRuleFiles", () => { expect(result).toBe("") }) - it("should use .roo/rules/ directory when it exists and has files", async () => { - // Simulate .roo/rules directory exists + it("should use .pearai-agent/rules/ directory when it exists and has files", async () => { + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) // Simulate listing files readdirMock.mockResolvedValueOnce([ - { name: "file1.txt", isFile: () => true, isSymbolicLink: () => false, parentPath: "/fake/path/.roo/rules" }, - { name: "file2.txt", isFile: () => true, isSymbolicLink: () => false, parentPath: "/fake/path/.roo/rules" }, + { name: "file1.txt", isFile: () => true, isSymbolicLink: () => false, parentPath: "/fake/path/.pearai-agent/rules" }, + { name: "file2.txt", isFile: () => true, isSymbolicLink: () => false, parentPath: "/fake/path/.pearai-agent/rules" }, ] as any) statMock.mockImplementation( @@ -141,31 +141,31 @@ describe("loadRuleFiles", () => { ) readFileMock.mockImplementation((filePath: PathLike) => { - if (filePath.toString() === "/fake/path/.roo/rules/file1.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/file1.txt") { return Promise.resolve("content of file1") } - if (filePath.toString() === "/fake/path/.roo/rules/file2.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/file2.txt") { return Promise.resolve("content of file2") } return Promise.reject({ code: "ENOENT" }) }) const result = await loadRuleFiles("/fake/path") - expect(result).toContain("# Rules from /fake/path/.roo/rules/file1.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/file1.txt:") expect(result).toContain("content of file1") - expect(result).toContain("# Rules from /fake/path/.roo/rules/file2.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/file2.txt:") expect(result).toContain("content of file2") // We expect both checks because our new implementation checks the files again for validation - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules/file1.txt") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules/file2.txt") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/file1.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/file2.txt", "utf-8") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/file1.txt") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/file2.txt") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/file1.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/file2.txt", "utf-8") }) - it("should fall back to .roorules when .roo/rules/ is empty", async () => { - // Simulate .roo/rules directory exists + it("should fall back to .roorules when .pearai-agent/rules/ is empty", async () => { + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) @@ -186,7 +186,7 @@ describe("loadRuleFiles", () => { }) it("should handle errors when reading directory", async () => { - // Simulate .roo/rules directory exists + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) @@ -206,8 +206,8 @@ describe("loadRuleFiles", () => { expect(result).toBe("\n# Rules from .roorules:\nroo rules content\n") }) - it("should read files from nested subdirectories in .roo/rules/", async () => { - // Simulate .roo/rules directory exists + it("should read files from nested subdirectories in .pearai-agent/rules/", async () => { + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) @@ -219,28 +219,28 @@ describe("loadRuleFiles", () => { isFile: () => false, isSymbolicLink: () => false, isDirectory: () => true, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, { name: "root.txt", isFile: () => true, isSymbolicLink: () => false, isDirectory: () => false, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, { name: "nested1.txt", isFile: () => true, isSymbolicLink: () => false, isDirectory: () => false, - parentPath: "/fake/path/.roo/rules/subdir", + parentPath: "/fake/path/.pearai-agent/rules/subdir", }, { name: "nested2.txt", isFile: () => true, isSymbolicLink: () => false, isDirectory: () => false, - parentPath: "/fake/path/.roo/rules/subdir/subdir2", + parentPath: "/fake/path/.pearai-agent/rules/subdir/subdir2", }, ] as any) @@ -259,13 +259,13 @@ describe("loadRuleFiles", () => { readFileMock.mockImplementation((filePath: PathLike) => { const path = filePath.toString() - if (path === "/fake/path/.roo/rules/root.txt") { + if (path === "/fake/path/.pearai-agent/rules/root.txt") { return Promise.resolve("root file content") } - if (path === "/fake/path/.roo/rules/subdir/nested1.txt") { + if (path === "/fake/path/.pearai-agent/rules/subdir/nested1.txt") { return Promise.resolve("nested file 1 content") } - if (path === "/fake/path/.roo/rules/subdir/subdir2/nested2.txt") { + if (path === "/fake/path/.pearai-agent/rules/subdir/subdir2/nested2.txt") { return Promise.resolve("nested file 2 content") } return Promise.reject({ code: "ENOENT" }) @@ -274,24 +274,24 @@ describe("loadRuleFiles", () => { const result = await loadRuleFiles("/fake/path") // Check root file content - expect(result).toContain("# Rules from /fake/path/.roo/rules/root.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/root.txt:") expect(result).toContain("root file content") // Check nested files content - expect(result).toContain("# Rules from /fake/path/.roo/rules/subdir/nested1.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/subdir/nested1.txt:") expect(result).toContain("nested file 1 content") - expect(result).toContain("# Rules from /fake/path/.roo/rules/subdir/subdir2/nested2.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/subdir/subdir2/nested2.txt:") expect(result).toContain("nested file 2 content") // Verify correct paths were checked - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules/root.txt") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules/subdir/nested1.txt") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules/subdir/subdir2/nested2.txt") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/root.txt") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/subdir/nested1.txt") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/subdir/subdir2/nested2.txt") // Verify files were read with correct paths - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/root.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/subdir/nested1.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/subdir/subdir2/nested2.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/root.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/subdir/nested1.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/subdir/subdir2/nested2.txt", "utf-8") }) }) @@ -301,7 +301,7 @@ describe("addCustomInstructions", () => { }) it("should combine all instruction types when provided", async () => { - // Simulate no .roo/rules-test-mode directory + // Simulate no .pearai-agent/rules-test-mode directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockResolvedValue("mode specific rules") @@ -323,7 +323,7 @@ describe("addCustomInstructions", () => { }) it("should return empty string when no instructions provided", async () => { - // Simulate no .roo/rules directory + // Simulate no .pearai-agent/rules directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "ENOENT" }) @@ -333,7 +333,7 @@ describe("addCustomInstructions", () => { }) it("should handle missing mode-specific rules file", async () => { - // Simulate no .roo/rules-test-mode directory + // Simulate no .pearai-agent/rules-test-mode directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "ENOENT" }) @@ -351,7 +351,7 @@ describe("addCustomInstructions", () => { }) it("should handle unknown language codes properly", async () => { - // Simulate no .roo/rules-test-mode directory + // Simulate no .pearai-agent/rules-test-mode directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockRejectedValue({ code: "ENOENT" }) @@ -370,7 +370,7 @@ describe("addCustomInstructions", () => { }) it("should throw on unexpected errors", async () => { - // Simulate no .roo/rules-test-mode directory + // Simulate no .pearai-agent/rules-test-mode directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) const error = new Error("Permission denied") as NodeJS.ErrnoException @@ -383,7 +383,7 @@ describe("addCustomInstructions", () => { }) it("should skip mode-specific rule files that are directories", async () => { - // Simulate no .roo/rules-test-mode directory + // Simulate no .pearai-agent/rules-test-mode directory statMock.mockRejectedValueOnce({ code: "ENOENT" }) readFileMock.mockImplementation((filePath: PathLike) => { @@ -405,8 +405,8 @@ describe("addCustomInstructions", () => { expect(result).not.toContain("Rules from .clinerules-test-mode") }) - it("should use .roo/rules-test-mode/ directory when it exists and has files", async () => { - // Simulate .roo/rules-test-mode directory exists + it("should use .pearai-agent/rules-test-mode/ directory when it exists and has files", async () => { + // Simulate .pearai-agent/rules-test-mode directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) @@ -417,13 +417,13 @@ describe("addCustomInstructions", () => { name: "rule1.txt", isFile: () => true, isSymbolicLink: () => false, - parentPath: "/fake/path/.roo/rules-test-mode", + parentPath: "/fake/path/.pearai-agent/rules-test-mode", }, { name: "rule2.txt", isFile: () => true, isSymbolicLink: () => false, - parentPath: "/fake/path/.roo/rules-test-mode", + parentPath: "/fake/path/.pearai-agent/rules-test-mode", }, ] as any) @@ -435,10 +435,10 @@ describe("addCustomInstructions", () => { ) readFileMock.mockImplementation((filePath: PathLike) => { - if (filePath.toString() === "/fake/path/.roo/rules-test-mode/rule1.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules-test-mode/rule1.txt") { return Promise.resolve("mode specific rule 1") } - if (filePath.toString() === "/fake/path/.roo/rules-test-mode/rule2.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules-test-mode/rule2.txt") { return Promise.resolve("mode specific rule 2") } return Promise.reject({ code: "ENOENT" }) @@ -452,21 +452,21 @@ describe("addCustomInstructions", () => { { language: "es" }, ) - expect(result).toContain("# Rules from /fake/path/.roo/rules-test-mode") - expect(result).toContain("# Rules from /fake/path/.roo/rules-test-mode/rule1.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules-test-mode") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules-test-mode/rule1.txt:") expect(result).toContain("mode specific rule 1") - expect(result).toContain("# Rules from /fake/path/.roo/rules-test-mode/rule2.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules-test-mode/rule2.txt:") expect(result).toContain("mode specific rule 2") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules-test-mode") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules-test-mode/rule1.txt") - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules-test-mode/rule2.txt") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules-test-mode/rule1.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules-test-mode/rule2.txt", "utf-8") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules-test-mode") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules-test-mode/rule1.txt") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules-test-mode/rule2.txt") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules-test-mode/rule1.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules-test-mode/rule2.txt", "utf-8") }) - it("should fall back to .roorules-test-mode when .roo/rules-test-mode/ does not exist", async () => { - // Simulate .roo/rules-test-mode directory does not exist + it("should fall back to .roorules-test-mode when .pearai-agent/rules-test-mode/ does not exist", async () => { + // Simulate .pearai-agent/rules-test-mode directory does not exist statMock.mockRejectedValueOnce({ code: "ENOENT" }) // Simulate .roorules-test-mode exists @@ -487,8 +487,8 @@ describe("addCustomInstructions", () => { expect(result).toContain("Rules from .roorules-test-mode:\nmode specific rules from file") }) - it("should fall back to .clinerules-test-mode when .roo/rules-test-mode/ and .roorules-test-mode do not exist", async () => { - // Simulate .roo/rules-test-mode directory does not exist + it("should fall back to .clinerules-test-mode when .pearai-agent/rules-test-mode/ and .roorules-test-mode do not exist", async () => { + // Simulate .pearai-agent/rules-test-mode directory does not exist statMock.mockRejectedValueOnce({ code: "ENOENT" }) // Simulate file reading @@ -512,12 +512,12 @@ describe("addCustomInstructions", () => { expect(result).toContain("Rules from .clinerules-test-mode:\nmode specific rules from cline file") }) - it("should correctly format content from directories when using .roo/rules-test-mode/", async () => { + it("should correctly format content from directories when using .pearai-agent/rules-test-mode/", async () => { // Need to reset mockImplementation first to avoid interference from previous tests statMock.mockReset() readFileMock.mockReset() - // Simulate .roo/rules-test-mode directory exists + // Simulate .pearai-agent/rules-test-mode directory exists statMock.mockImplementationOnce(() => Promise.resolve({ isDirectory: jest.fn().mockReturnValue(true), @@ -526,7 +526,7 @@ describe("addCustomInstructions", () => { // Simulate directory has files readdirMock.mockResolvedValueOnce([ - { name: "rule1.txt", isFile: () => true, parentPath: "/fake/path/.roo/rules-test-mode" }, + { name: "rule1.txt", isFile: () => true, parentPath: "/fake/path/.pearai-agent/rules-test-mode" }, ] as any) readFileMock.mockReset() @@ -534,7 +534,7 @@ describe("addCustomInstructions", () => { let statCallCount = 0 statMock.mockImplementation((filePath) => { statCallCount++ - if (filePath === "/fake/path/.roo/rules-test-mode/rule1.txt") { + if (filePath === "/fake/path/.pearai-agent/rules-test-mode/rule1.txt") { return Promise.resolve({ isFile: jest.fn().mockReturnValue(true), isDirectory: jest.fn().mockReturnValue(false), @@ -547,7 +547,7 @@ describe("addCustomInstructions", () => { }) readFileMock.mockImplementation((filePath: PathLike) => { - if (filePath.toString() === "/fake/path/.roo/rules-test-mode/rule1.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules-test-mode/rule1.txt") { return Promise.resolve("mode specific rule content") } return Promise.reject({ code: "ENOENT" }) @@ -560,8 +560,8 @@ describe("addCustomInstructions", () => { "test-mode", ) - expect(result).toContain("# Rules from /fake/path/.roo/rules-test-mode") - expect(result).toContain("# Rules from /fake/path/.roo/rules-test-mode/rule1.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules-test-mode") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules-test-mode/rule1.txt:") expect(result).toContain("mode specific rule content") expect(statCallCount).toBeGreaterThan(0) @@ -589,7 +589,7 @@ describe("Directory existence checks", () => { await loadRuleFiles("/fake/path") // Verify stat was called to check directory existence - expect(statMock).toHaveBeenCalledWith("/fake/path/.roo/rules") + expect(statMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules") }) it("should handle when directory does not exist", async () => { @@ -609,7 +609,7 @@ describe("Directory existence checks", () => { // Indirectly test readTextFilesFromDirectory and formatDirectoryContent through loadRuleFiles describe("Rules directory reading", () => { it("should follow symbolic links in the rules directory", async () => { - // Simulate .roo/rules directory exists + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) @@ -621,29 +621,29 @@ describe("Rules directory reading", () => { name: "regular.txt", isFile: () => true, isSymbolicLink: () => false, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, { name: "link.txt", isFile: () => false, isSymbolicLink: () => true, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, { name: "link_dir", isFile: () => false, isSymbolicLink: () => true, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, { name: "nested_link.txt", isFile: () => false, isSymbolicLink: () => true, - parentPath: "/fake/path/.roo/rules", + parentPath: "/fake/path/.pearai-agent/rules", }, ] as any) .mockResolvedValueOnce([ - { name: "subdir_link.txt", isFile: () => true, parentPath: "/fake/path/.roo/rules/symlink-target-dir" }, + { name: "subdir_link.txt", isFile: () => true, parentPath: "/fake/path/.pearai-agent/rules/symlink-target-dir" }, ] as any) // Simulate readlink response @@ -657,7 +657,7 @@ describe("Rules directory reading", () => { statMock.mockReset() statMock.mockImplementation((path: string) => { // For directory check - if (path === "/fake/path/.roo/rules" || path.endsWith("dir")) { + if (path === "/fake/path/.pearai-agent/rules" || path.endsWith("dir")) { return Promise.resolve({ isDirectory: jest.fn().mockReturnValue(true), isFile: jest.fn().mockReturnValue(false), @@ -682,16 +682,16 @@ describe("Rules directory reading", () => { // Simulate file content reading readFileMock.mockImplementation((filePath: PathLike) => { - if (filePath.toString() === "/fake/path/.roo/rules/regular.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/regular.txt") { return Promise.resolve("regular file content") } - if (filePath.toString() === "/fake/path/.roo/rules/../symlink-target.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/../symlink-target.txt") { return Promise.resolve("symlink target content") } - if (filePath.toString() === "/fake/path/.roo/rules/symlink-target-dir/subdir_link.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/symlink-target-dir/subdir_link.txt") { return Promise.resolve("regular file content under symlink target dir") } - if (filePath.toString() === "/fake/path/.roo/rules/../nested-symlink-target.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/../nested-symlink-target.txt") { return Promise.resolve("nested symlink target content") } return Promise.reject({ code: "ENOENT" }) @@ -700,47 +700,47 @@ describe("Rules directory reading", () => { const result = await loadRuleFiles("/fake/path") // Verify both regular file and symlink target content are included - expect(result).toContain("# Rules from /fake/path/.roo/rules/regular.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/regular.txt:") expect(result).toContain("regular file content") - expect(result).toContain("# Rules from /fake/path/.roo/rules/../symlink-target.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/../symlink-target.txt:") expect(result).toContain("symlink target content") - expect(result).toContain("# Rules from /fake/path/.roo/rules/symlink-target-dir/subdir_link.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/symlink-target-dir/subdir_link.txt:") expect(result).toContain("regular file content under symlink target dir") - expect(result).toContain("# Rules from /fake/path/.roo/rules/../nested-symlink-target.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/../nested-symlink-target.txt:") expect(result).toContain("nested symlink target content") // Verify readlink was called with the symlink path - expect(readlinkMock).toHaveBeenCalledWith("/fake/path/.roo/rules/link.txt") - expect(readlinkMock).toHaveBeenCalledWith("/fake/path/.roo/rules/link_dir") + expect(readlinkMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/link.txt") + expect(readlinkMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/link_dir") // Verify both files were read - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/regular.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/../symlink-target.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/symlink-target-dir/subdir_link.txt", "utf-8") - expect(readFileMock).toHaveBeenCalledWith("/fake/path/.roo/rules/../nested-symlink-target.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/regular.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/../symlink-target.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/symlink-target-dir/subdir_link.txt", "utf-8") + expect(readFileMock).toHaveBeenCalledWith("/fake/path/.pearai-agent/rules/../nested-symlink-target.txt", "utf-8") }) beforeEach(() => { jest.clearAllMocks() }) it("should correctly format multiple files from directory", async () => { - // Simulate .roo/rules directory exists + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) // Simulate listing files readdirMock.mockResolvedValueOnce([ - { name: "file1.txt", isFile: () => true, parentPath: "/fake/path/.roo/rules" }, - { name: "file2.txt", isFile: () => true, parentPath: "/fake/path/.roo/rules" }, - { name: "file3.txt", isFile: () => true, parentPath: "/fake/path/.roo/rules" }, + { name: "file1.txt", isFile: () => true, parentPath: "/fake/path/.pearai-agent/rules" }, + { name: "file2.txt", isFile: () => true, parentPath: "/fake/path/.pearai-agent/rules" }, + { name: "file3.txt", isFile: () => true, parentPath: "/fake/path/.pearai-agent/rules" }, ] as any) statMock.mockImplementation((path) => { expect([ - "/fake/path/.roo/rules/file1.txt", - "/fake/path/.roo/rules/file2.txt", - "/fake/path/.roo/rules/file3.txt", + "/fake/path/.pearai-agent/rules/file1.txt", + "/fake/path/.pearai-agent/rules/file2.txt", + "/fake/path/.pearai-agent/rules/file3.txt", ]).toContain(path) return Promise.resolve({ @@ -749,13 +749,13 @@ describe("Rules directory reading", () => { }) readFileMock.mockImplementation((filePath: PathLike) => { - if (filePath.toString() === "/fake/path/.roo/rules/file1.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/file1.txt") { return Promise.resolve("content of file1") } - if (filePath.toString() === "/fake/path/.roo/rules/file2.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/file2.txt") { return Promise.resolve("content of file2") } - if (filePath.toString() === "/fake/path/.roo/rules/file3.txt") { + if (filePath.toString() === "/fake/path/.pearai-agent/rules/file3.txt") { return Promise.resolve("content of file3") } return Promise.reject({ code: "ENOENT" }) @@ -763,16 +763,16 @@ describe("Rules directory reading", () => { const result = await loadRuleFiles("/fake/path") - expect(result).toContain("# Rules from /fake/path/.roo/rules/file1.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/file1.txt:") expect(result).toContain("content of file1") - expect(result).toContain("# Rules from /fake/path/.roo/rules/file2.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/file2.txt:") expect(result).toContain("content of file2") - expect(result).toContain("# Rules from /fake/path/.roo/rules/file3.txt:") + expect(result).toContain("# Rules from /fake/path/.pearai-agent/rules/file3.txt:") expect(result).toContain("content of file3") }) it("should handle empty file list gracefully", async () => { - // Simulate .roo/rules directory exists + // Simulate .pearai-agent/rules directory exists statMock.mockResolvedValueOnce({ isDirectory: jest.fn().mockReturnValue(true), } as any) diff --git a/src/core/prompts/sections/__tests__/custom-system-prompt.test.ts b/src/core/prompts/sections/__tests__/custom-system-prompt.test.ts index 9fc538860ae..b1ae557bd4c 100644 --- a/src/core/prompts/sections/__tests__/custom-system-prompt.test.ts +++ b/src/core/prompts/sections/__tests__/custom-system-prompt.test.ts @@ -2,6 +2,7 @@ import path from "path" import { readFile } from "fs/promises" import { Mode } from "../../../../shared/modes" // Adjusted import path import { loadSystemPromptFile, PromptVariables } from "../custom-system-prompt" +import { AGENT_RULES_DIR } from "../../../../shared/constants" // Mock the fs/promises module jest.mock("fs/promises") @@ -17,7 +18,7 @@ describe("loadSystemPromptFile", () => { const mockCwd = "/mock/cwd" const mockMode: Mode = "test" // Use Mode type, e.g., 'test' // Corrected expected file path format - const expectedFilePath = path.join(mockCwd, ".roo", `system-prompt-${mockMode}`) + const expectedFilePath = path.join(mockCwd, AGENT_RULES_DIR, `system-prompt-${mockMode}`) beforeEach(() => { // Clear mocks before each test diff --git a/src/core/prompts/sections/custom-instructions.ts b/src/core/prompts/sections/custom-instructions.ts index cf1aea24ff4..4f09ce7452c 100644 --- a/src/core/prompts/sections/custom-instructions.ts +++ b/src/core/prompts/sections/custom-instructions.ts @@ -3,6 +3,7 @@ import path from "path" import { LANGUAGES, isLanguage } from "../../../shared/language" import { Dirent } from "fs" +import { AGENT_RULES_DIR } from "../../../shared/constants" /** * Safely read a file and return its trimmed content @@ -156,8 +157,8 @@ function formatDirectoryContent(dirPath: string, files: Array<{ filename: string * Load rule files from the specified directory */ export async function loadRuleFiles(cwd: string): Promise { - // Check for .roo/rules/ directory - const rooRulesDir = path.join(cwd, ".roo", "rules") + // Check for .pearai-agent/rules/ directory + const rooRulesDir = path.join(cwd, AGENT_RULES_DIR, "rules") if (await directoryExists(rooRulesDir)) { const files = await readTextFilesFromDirectory(rooRulesDir) if (files.length > 0) { @@ -192,8 +193,8 @@ export async function addCustomInstructions( let usedRuleFile = "" if (mode) { - // Check for .roo/rules-${mode}/ directory - const modeRulesDir = path.join(cwd, ".roo", `rules-${mode}`) + // Check for .pearai-agent/rules-${mode}/ directory + const modeRulesDir = path.join(cwd, AGENT_RULES_DIR, `rules-${mode}`) if (await directoryExists(modeRulesDir)) { const files = await readTextFilesFromDirectory(modeRulesDir) if (files.length > 0) { @@ -241,7 +242,7 @@ export async function addCustomInstructions( // Add mode-specific rules first if they exist if (modeRuleContent && modeRuleContent.trim()) { - if (usedRuleFile.includes(path.join(".roo", `rules-${mode}`))) { + if (usedRuleFile.includes(path.join(AGENT_RULES_DIR, `rules-${mode}`))) { rules.push(modeRuleContent.trim()) } else { rules.push(`# Rules from ${usedRuleFile}:\n${modeRuleContent}`) diff --git a/src/core/prompts/sections/custom-system-prompt.ts b/src/core/prompts/sections/custom-system-prompt.ts index f401000bb55..8a0c746ffeb 100644 --- a/src/core/prompts/sections/custom-system-prompt.ts +++ b/src/core/prompts/sections/custom-system-prompt.ts @@ -2,6 +2,7 @@ import fs from "fs/promises" import path from "path" import { Mode } from "../../../shared/modes" import { fileExistsAtPath } from "../../../utils/fs" +import { AGENT_RULES_DIR } from "../../../shared/constants" export type PromptVariables = { workspace?: string @@ -46,11 +47,11 @@ async function safeReadFile(filePath: string): Promise { * Get the path to a system prompt file for a specific mode */ export function getSystemPromptFilePath(cwd: string, mode: Mode): string { - return path.join(cwd, ".roo", `system-prompt-${mode}`) + return path.join(cwd, AGENT_RULES_DIR, `system-prompt-${mode}`) } /** - * Loads custom system prompt from a file at .roo/system-prompt-[mode slug] + * Loads custom system prompt from a file at .pearai-agent/system-prompt-[mode slug] * If the file doesn't exist, returns an empty string */ export async function loadSystemPromptFile(cwd: string, mode: Mode, variables: PromptVariables): Promise { @@ -64,10 +65,10 @@ export async function loadSystemPromptFile(cwd: string, mode: Mode, variables: P } /** - * Ensures the .roo directory exists, creating it if necessary + * Ensures the .pearai-agent directory exists, creating it if necessary */ export async function ensureRooDirectory(cwd: string): Promise { - const rooDir = path.join(cwd, ".roo") + const rooDir = path.join(cwd, AGENT_RULES_DIR) // Check if directory already exists if (await fileExistsAtPath(rooDir)) { diff --git a/src/core/webview/__tests__/ClineProvider.test.ts b/src/core/webview/__tests__/ClineProvider.test.ts index 2942bc43b11..344c9672186 100644 --- a/src/core/webview/__tests__/ClineProvider.test.ts +++ b/src/core/webview/__tests__/ClineProvider.test.ts @@ -10,6 +10,7 @@ import { setTtsEnabled } from "../../../utils/tts" import { defaultModeSlug } from "../../../shared/modes" import { experimentDefault } from "../../../shared/experiments" import { ContextProxy } from "../../config/ContextProxy" +import { AGENT_RULES_DIR } from "../../../shared/constants" // Mock setup must come before imports jest.mock("../../prompts/sections/custom-instructions") @@ -1980,7 +1981,7 @@ describe("Project MCP Settings", () => { // Verify directory was created expect(fs.mkdir).toHaveBeenCalledWith( - expect.stringContaining(".roo"), + expect.stringContaining(AGENT_RULES_DIR), expect.objectContaining({ recursive: true }), ) @@ -2023,7 +2024,7 @@ describe("Project MCP Settings", () => { // Verify error message was shown expect(vscode.window.showErrorMessage).toHaveBeenCalledWith( - expect.stringContaining("Failed to create or open .roo/mcp.json"), + expect.stringContaining(`Failed to create or open ${AGENT_RULES_DIR}/mcp.json`), ) }) }) diff --git a/src/core/webview/webviewMessageHandler.ts b/src/core/webview/webviewMessageHandler.ts index 7c4beabd570..003e2523a0c 100644 --- a/src/core/webview/webviewMessageHandler.ts +++ b/src/core/webview/webviewMessageHandler.ts @@ -39,6 +39,7 @@ import { GlobalState } from "../../schemas" import { MultiSearchReplaceDiffStrategy } from "../diff/strategies/multi-search-replace" import { getModels } from "../../api/providers/fetchers/cache" import { getpearAIExports } from "../../activate/registerPearListener" +import { AGENT_RULES_DIR } from "../../shared/constants" export const webviewMessageHandler = async (provider: ClineProvider, message: WebviewMessage) => { // Utility functions provided for concise get/update of global state via contextProxy API. @@ -398,7 +399,7 @@ export const webviewMessageHandler = async (provider: ClineProvider, message: We } const workspaceFolder = vscode.workspace.workspaceFolders[0] - const rooDir = path.join(workspaceFolder.uri.fsPath, ".roo") + const rooDir = path.join(workspaceFolder.uri.fsPath, AGENT_RULES_DIR) const mcpPath = path.join(rooDir, "mcp.json") try { diff --git a/src/exports/types.ts b/src/exports/types.ts index e964fdbe46c..c449b349e86 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -2,215 +2,175 @@ // Do not edit it directly. type ProviderSettings = { - apiProvider?: - | ( - | "anthropic" - | "glama" - | "openrouter" - | "bedrock" - | "vertex" - | "openai" - | "ollama" - | "vscode-lm" - | "lmstudio" - | "gemini" - | "openai-native" - | "mistral" - | "deepseek" - | "unbound" - | "requesty" - | "human-relay" - | "fake-ai" - | "pearai" - | "xai" - ) - | undefined - apiModelId?: string | undefined - apiKey?: string | undefined - anthropicBaseUrl?: string | undefined - anthropicUseAuthToken?: boolean | undefined - glamaModelId?: string | undefined - glamaApiKey?: string | undefined - openRouterApiKey?: string | undefined - openRouterModelId?: string | undefined - openRouterBaseUrl?: string | undefined - openRouterSpecificProvider?: string | undefined - openRouterUseMiddleOutTransform?: boolean | undefined - awsAccessKey?: string | undefined - awsSecretKey?: string | undefined - awsSessionToken?: string | undefined - awsRegion?: string | undefined - awsUseCrossRegionInference?: boolean | undefined - awsUsePromptCache?: boolean | undefined - awspromptCacheId?: string | undefined - awsProfile?: string | undefined - awsUseProfile?: boolean | undefined - awsCustomArn?: string | undefined - vertexKeyFile?: string | undefined - vertexJsonCredentials?: string | undefined - vertexProjectId?: string | undefined - vertexRegion?: string | undefined - openAiBaseUrl?: string | undefined - openAiApiKey?: string | undefined - openAiLegacyFormat?: boolean | undefined - openAiR1FormatEnabled?: boolean | undefined - openAiModelId?: string | undefined - openAiCustomModelInfo?: - | ({ - maxTokens?: (number | null) | undefined - maxThinkingTokens?: (number | null) | undefined - contextWindow: number - supportsImages?: boolean | undefined - supportsComputerUse?: boolean | undefined - supportsPromptCache: boolean - isPromptCacheOptional?: boolean | undefined - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - description?: string | undefined - reasoningEffort?: ("low" | "medium" | "high") | undefined - thinking?: boolean | undefined - minTokensPerCachePoint?: number | undefined - maxCachePoints?: number | undefined - cachableFields?: string[] | undefined - underlyingModel?: string | undefined - tiers?: - | { - contextWindow: number - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - }[] - | undefined - } | null) - | undefined - openAiUseAzure?: boolean | undefined - azureApiVersion?: string | undefined - openAiStreamingEnabled?: boolean | undefined - enableReasoningEffort?: boolean | undefined - openAiHostHeader?: string | undefined - openAiHeaders?: - | { - [x: string]: string - } - | undefined - ollamaModelId?: string | undefined - ollamaBaseUrl?: string | undefined - vsCodeLmModelSelector?: - | { - vendor?: string | undefined - family?: string | undefined - version?: string | undefined - id?: string | undefined - } - | undefined - lmStudioModelId?: string | undefined - lmStudioBaseUrl?: string | undefined - lmStudioDraftModelId?: string | undefined - lmStudioSpeculativeDecodingEnabled?: boolean | undefined - geminiApiKey?: string | undefined - googleGeminiBaseUrl?: string | undefined - openAiNativeApiKey?: string | undefined - openAiNativeBaseUrl?: string | undefined - mistralApiKey?: string | undefined - mistralCodestralUrl?: string | undefined - deepSeekBaseUrl?: string | undefined - deepSeekApiKey?: string | undefined - unboundApiKey?: string | undefined - unboundModelId?: string | undefined - requestyApiKey?: string | undefined - requestyModelId?: string | undefined - xaiApiKey?: string | undefined - modelMaxTokens?: number | undefined - modelMaxThinkingTokens?: number | undefined - includeMaxTokens?: boolean | undefined - reasoningEffort?: ("low" | "medium" | "high") | undefined - promptCachingEnabled?: boolean | undefined - diffEnabled?: boolean | undefined - fuzzyMatchThreshold?: number | undefined - modelTemperature?: (number | null) | undefined - rateLimitSeconds?: number | undefined - fakeAi?: unknown | undefined - pearaiBaseUrl?: string | undefined - pearaiModelId?: string | undefined - pearaiApiKey?: string | undefined - pearaiModelInfo?: - | ({ - maxTokens?: (number | null) | undefined - maxThinkingTokens?: (number | null) | undefined - contextWindow: number - supportsImages?: boolean | undefined - supportsComputerUse?: boolean | undefined - supportsPromptCache: boolean - isPromptCacheOptional?: boolean | undefined - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - description?: string | undefined - reasoningEffort?: ("low" | "medium" | "high") | undefined - thinking?: boolean | undefined - minTokensPerCachePoint?: number | undefined - maxCachePoints?: number | undefined - cachableFields?: string[] | undefined - underlyingModel?: string | undefined - tiers?: - | { - contextWindow: number - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - }[] - | undefined - } | null) - | undefined - pearaiAgentModels?: - | { - models: { - [x: string]: { - maxTokens?: (number | null) | undefined - maxThinkingTokens?: (number | null) | undefined - contextWindow: number - supportsImages?: boolean | undefined - supportsComputerUse?: boolean | undefined - supportsPromptCache: boolean - isPromptCacheOptional?: boolean | undefined - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - description?: string | undefined - reasoningEffort?: ("low" | "medium" | "high") | undefined - thinking?: boolean | undefined - minTokensPerCachePoint?: number | undefined - maxCachePoints?: number | undefined - cachableFields?: string[] | undefined - underlyingModel?: string | undefined - tiers?: - | { - contextWindow: number - inputPrice?: number | undefined - outputPrice?: number | undefined - cacheWritesPrice?: number | undefined - cacheReadsPrice?: number | undefined - }[] - | undefined - } - } - defaultModelId?: string | undefined - } - | undefined - creatorModeConfig?: - | { - creatorMode?: boolean | undefined - newProjectType?: string | undefined - newProjectPath?: string | undefined - } - | undefined -} + apiProvider?: ("anthropic" | "glama" | "openrouter" | "bedrock" | "vertex" | "openai" | "ollama" | "vscode-lm" | "lmstudio" | "gemini" | "openai-native" | "mistral" | "deepseek" | "unbound" | "requesty" | "human-relay" | "fake-ai" | "pearai" | "xai") | undefined; + apiModelId?: string | undefined; + apiKey?: string | undefined; + anthropicBaseUrl?: string | undefined; + anthropicUseAuthToken?: boolean | undefined; + glamaModelId?: string | undefined; + glamaApiKey?: string | undefined; + openRouterApiKey?: string | undefined; + openRouterModelId?: string | undefined; + openRouterBaseUrl?: string | undefined; + openRouterSpecificProvider?: string | undefined; + openRouterUseMiddleOutTransform?: boolean | undefined; + awsAccessKey?: string | undefined; + awsSecretKey?: string | undefined; + awsSessionToken?: string | undefined; + awsRegion?: string | undefined; + awsUseCrossRegionInference?: boolean | undefined; + awsUsePromptCache?: boolean | undefined; + awspromptCacheId?: string | undefined; + awsProfile?: string | undefined; + awsUseProfile?: boolean | undefined; + awsCustomArn?: string | undefined; + vertexKeyFile?: string | undefined; + vertexJsonCredentials?: string | undefined; + vertexProjectId?: string | undefined; + vertexRegion?: string | undefined; + openAiBaseUrl?: string | undefined; + openAiApiKey?: string | undefined; + openAiLegacyFormat?: boolean | undefined; + openAiR1FormatEnabled?: boolean | undefined; + openAiModelId?: string | undefined; + openAiCustomModelInfo?: ({ + maxTokens?: (number | null) | undefined; + maxThinkingTokens?: (number | null) | undefined; + contextWindow: number; + supportsImages?: boolean | undefined; + supportsComputerUse?: boolean | undefined; + supportsPromptCache: boolean; + isPromptCacheOptional?: boolean | undefined; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + description?: string | undefined; + reasoningEffort?: ("low" | "medium" | "high") | undefined; + thinking?: boolean | undefined; + minTokensPerCachePoint?: number | undefined; + maxCachePoints?: number | undefined; + cachableFields?: string[] | undefined; + underlyingModel?: string | undefined; + tiers?: { + contextWindow: number; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + }[] | undefined; + } | null) | undefined; + openAiUseAzure?: boolean | undefined; + azureApiVersion?: string | undefined; + openAiStreamingEnabled?: boolean | undefined; + enableReasoningEffort?: boolean | undefined; + openAiHostHeader?: string | undefined; + openAiHeaders?: { + [x: string]: string; + } | undefined; + ollamaModelId?: string | undefined; + ollamaBaseUrl?: string | undefined; + vsCodeLmModelSelector?: { + vendor?: string | undefined; + family?: string | undefined; + version?: string | undefined; + id?: string | undefined; + } | undefined; + lmStudioModelId?: string | undefined; + lmStudioBaseUrl?: string | undefined; + lmStudioDraftModelId?: string | undefined; + lmStudioSpeculativeDecodingEnabled?: boolean | undefined; + geminiApiKey?: string | undefined; + googleGeminiBaseUrl?: string | undefined; + openAiNativeApiKey?: string | undefined; + openAiNativeBaseUrl?: string | undefined; + mistralApiKey?: string | undefined; + mistralCodestralUrl?: string | undefined; + deepSeekBaseUrl?: string | undefined; + deepSeekApiKey?: string | undefined; + unboundApiKey?: string | undefined; + unboundModelId?: string | undefined; + requestyApiKey?: string | undefined; + requestyModelId?: string | undefined; + xaiApiKey?: string | undefined; + modelMaxTokens?: number | undefined; + modelMaxThinkingTokens?: number | undefined; + includeMaxTokens?: boolean | undefined; + reasoningEffort?: ("low" | "medium" | "high") | undefined; + promptCachingEnabled?: boolean | undefined; + diffEnabled?: boolean | undefined; + fuzzyMatchThreshold?: number | undefined; + modelTemperature?: (number | null) | undefined; + rateLimitSeconds?: number | undefined; + fakeAi?: unknown | undefined; + pearaiBaseUrl?: string | undefined; + pearaiModelId?: string | undefined; + pearaiApiKey?: string | undefined; + pearaiModelInfo?: ({ + maxTokens?: (number | null) | undefined; + maxThinkingTokens?: (number | null) | undefined; + contextWindow: number; + supportsImages?: boolean | undefined; + supportsComputerUse?: boolean | undefined; + supportsPromptCache: boolean; + isPromptCacheOptional?: boolean | undefined; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + description?: string | undefined; + reasoningEffort?: ("low" | "medium" | "high") | undefined; + thinking?: boolean | undefined; + minTokensPerCachePoint?: number | undefined; + maxCachePoints?: number | undefined; + cachableFields?: string[] | undefined; + underlyingModel?: string | undefined; + tiers?: { + contextWindow: number; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + }[] | undefined; + } | null) | undefined; + pearaiAgentModels?: { + models: { + [x: string]: { + maxTokens?: (number | null) | undefined; + maxThinkingTokens?: (number | null) | undefined; + contextWindow: number; + supportsImages?: boolean | undefined; + supportsComputerUse?: boolean | undefined; + supportsPromptCache: boolean; + isPromptCacheOptional?: boolean | undefined; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + description?: string | undefined; + reasoningEffort?: ("low" | "medium" | "high") | undefined; + thinking?: boolean | undefined; + minTokensPerCachePoint?: number | undefined; + maxCachePoints?: number | undefined; + cachableFields?: string[] | undefined; + underlyingModel?: string | undefined; + tiers?: { + contextWindow: number; + inputPrice?: number | undefined; + outputPrice?: number | undefined; + cacheWritesPrice?: number | undefined; + cacheReadsPrice?: number | undefined; + }[] | undefined; + }; + }; + defaultModelId?: string | undefined; + } | undefined; + creatorModeConfig?: { + creatorMode?: boolean | undefined; + newProjectType?: string | undefined; + newProjectPath?: string | undefined; + } | undefined; +}; export type { ProviderSettings } @@ -392,207 +352,123 @@ type GlobalSettings = { export type { GlobalSettings } type ClineMessage = { - ts: number - type: "ask" | "say" - ask?: - | ( - | "followup" - | "command" - | "command_output" - | "completion_result" - | "tool" - | "api_req_failed" - | "resume_task" - | "resume_completed_task" - | "mistake_limit_reached" - | "browser_action_launch" - | "use_mcp_server" - ) - | undefined - say?: - | ( - | "error" - | "api_req_started" - | "api_req_finished" - | "api_req_retried" - | "api_req_retry_delayed" - | "api_req_deleted" - | "text" - | "reasoning" - | "completion_result" - | "user_feedback" - | "user_feedback_diff" - | "command_output" - | "shell_integration_warning" - | "browser_action" - | "browser_action_result" - | "mcp_server_request_started" - | "mcp_server_response" - | "subtask_result" - | "checkpoint_saved" - | "rooignore_error" - | "diff_error" - ) - | undefined - text?: string | undefined - images?: string[] | undefined - partial?: boolean | undefined - reasoning?: string | undefined - conversationHistoryIndex?: number | undefined - checkpoint?: - | { - [x: string]: unknown - } - | undefined - progressStatus?: - | { - id?: string | undefined - icon?: string | undefined - text?: string | undefined - } - | undefined -} + ts: number; + type: "ask" | "say"; + ask?: ("followup" | "command" | "command_output" | "completion_result" | "tool" | "api_req_failed" | "resume_task" | "resume_completed_task" | "mistake_limit_reached" | "browser_action_launch" | "use_mcp_server") | undefined; + say?: ("error" | "api_req_started" | "api_req_finished" | "api_req_retried" | "api_req_retry_delayed" | "api_req_deleted" | "text" | "reasoning" | "completion_result" | "user_feedback" | "user_feedback_diff" | "command_output" | "shell_integration_warning" | "browser_action" | "browser_action_result" | "mcp_server_request_started" | "mcp_server_response" | "subtask_result" | "checkpoint_saved" | "rooignore_error" | "diff_error") | undefined; + text?: string | undefined; + images?: string[] | undefined; + partial?: boolean | undefined; + reasoning?: string | undefined; + conversationHistoryIndex?: number | undefined; + checkpoint?: { + [x: string]: unknown; + } | undefined; + progressStatus?: { + id?: string | undefined; + icon?: string | undefined; + text?: string | undefined; + } | undefined; +}; export type { ClineMessage } type TokenUsage = { - totalTokensIn: number - totalTokensOut: number - totalCacheWrites?: number | undefined - totalCacheReads?: number | undefined - totalCost: number - contextTokens: number -} + totalTokensIn: number; + totalTokensOut: number; + totalCacheWrites?: number | undefined; + totalCacheReads?: number | undefined; + totalCost: number; + contextTokens: number; +}; export type { TokenUsage } type RooCodeEvents = { - message: [ - { - taskId: string - action: "created" | "updated" - message: { - ts: number - type: "ask" | "say" - ask?: - | ( - | "followup" - | "command" - | "command_output" - | "completion_result" - | "tool" - | "api_req_failed" - | "resume_task" - | "resume_completed_task" - | "mistake_limit_reached" - | "browser_action_launch" - | "use_mcp_server" - ) - | undefined - say?: - | ( - | "error" - | "api_req_started" - | "api_req_finished" - | "api_req_retried" - | "api_req_retry_delayed" - | "api_req_deleted" - | "text" - | "reasoning" - | "completion_result" - | "user_feedback" - | "user_feedback_diff" - | "command_output" - | "shell_integration_warning" - | "browser_action" - | "browser_action_result" - | "mcp_server_request_started" - | "mcp_server_response" - | "subtask_result" - | "checkpoint_saved" - | "rooignore_error" - | "diff_error" - ) - | undefined - text?: string | undefined - images?: string[] | undefined - partial?: boolean | undefined - reasoning?: string | undefined - conversationHistoryIndex?: number | undefined - checkpoint?: - | { - [x: string]: unknown - } - | undefined - progressStatus?: - | { - id?: string | undefined - icon?: string | undefined - text?: string | undefined - } - | undefined - } - }, - ] - taskCreated: [string] - taskStarted: [string] - taskModeSwitched: [string, string] - taskPaused: [string] - taskUnpaused: [string] - taskAskResponded: [string] - taskAborted: [string] - taskSpawned: [string, string] - taskCompleted: [ - string, - { - totalTokensIn: number - totalTokensOut: number - totalCacheWrites?: number | undefined - totalCacheReads?: number | undefined - totalCost: number - contextTokens: number - }, - { - [x: string]: { - attempts: number - failures: number - } - }, - ] - taskTokenUsageUpdated: [ - string, - { - totalTokensIn: number - totalTokensOut: number - totalCacheWrites?: number | undefined - totalCacheReads?: number | undefined - totalCost: number - contextTokens: number - }, - ] - taskToolFailed: [ - string, - ( - | "execute_command" - | "read_file" - | "write_to_file" - | "apply_diff" - | "insert_content" - | "search_and_replace" - | "search_files" - | "list_files" - | "list_code_definition_names" - | "browser_action" - | "use_mcp_tool" - | "access_mcp_resource" - | "ask_followup_question" - | "attempt_completion" - | "switch_mode" - | "new_task" - | "fetch_instructions" - ), - string, - ] -} + message: [ + { + taskId: string; + action: "created" | "updated"; + message: { + ts: number; + type: "ask" | "say"; + ask?: ("followup" | "command" | "command_output" | "completion_result" | "tool" | "api_req_failed" | "resume_task" | "resume_completed_task" | "mistake_limit_reached" | "browser_action_launch" | "use_mcp_server") | undefined; + say?: ("error" | "api_req_started" | "api_req_finished" | "api_req_retried" | "api_req_retry_delayed" | "api_req_deleted" | "text" | "reasoning" | "completion_result" | "user_feedback" | "user_feedback_diff" | "command_output" | "shell_integration_warning" | "browser_action" | "browser_action_result" | "mcp_server_request_started" | "mcp_server_response" | "subtask_result" | "checkpoint_saved" | "rooignore_error" | "diff_error") | undefined; + text?: string | undefined; + images?: string[] | undefined; + partial?: boolean | undefined; + reasoning?: string | undefined; + conversationHistoryIndex?: number | undefined; + checkpoint?: { + [x: string]: unknown; + } | undefined; + progressStatus?: { + id?: string | undefined; + icon?: string | undefined; + text?: string | undefined; + } | undefined; + }; + } + ]; + taskCreated: [ + string + ]; + taskStarted: [ + string + ]; + taskModeSwitched: [ + string, + string + ]; + taskPaused: [ + string + ]; + taskUnpaused: [ + string + ]; + taskAskResponded: [ + string + ]; + taskAborted: [ + string + ]; + taskSpawned: [ + string, + string + ]; + taskCompleted: [ + string, + { + totalTokensIn: number; + totalTokensOut: number; + totalCacheWrites?: number | undefined; + totalCacheReads?: number | undefined; + totalCost: number; + contextTokens: number; + }, + { + [x: string]: { + attempts: number; + failures: number; + }; + } + ]; + taskTokenUsageUpdated: [ + string, + { + totalTokensIn: number; + totalTokensOut: number; + totalCacheWrites?: number | undefined; + totalCacheReads?: number | undefined; + totalCost: number; + contextTokens: number; + } + ]; + taskToolFailed: [ + string, + "execute_command" | "read_file" | "write_to_file" | "apply_diff" | "insert_content" | "search_and_replace" | "search_files" | "list_files" | "list_code_definition_names" | "browser_action" | "use_mcp_tool" | "access_mcp_resource" | "ask_followup_question" | "attempt_completion" | "switch_mode" | "new_task" | "fetch_instructions", + string + ]; +}; -export type { RooCodeEvents } +export type { RooCodeEvents } \ No newline at end of file diff --git a/src/i18n/locales/ca/common.json b/src/i18n/locales/ca/common.json index 673d73687ea..3f9cd4bdb83 100644 --- a/src/i18n/locales/ca/common.json +++ b/src/i18n/locales/ca/common.json @@ -49,7 +49,7 @@ "list_api_config": "Ha fallat l'obtenció de la llista de configuracions de l'API", "update_server_timeout": "Ha fallat l'actualització del temps d'espera del servidor", "failed_update_project_mcp": "Ha fallat l'actualització dels servidors MCP del projecte", - "create_mcp_json": "Ha fallat la creació o obertura de .roo/mcp.json: {{error}}", + "create_mcp_json": "Ha fallat la creació o obertura de .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "El servidor de desenvolupament local no està executant-se, l'HMR no funcionarà. Si us plau, executa 'npm run dev' abans de llançar l'extensió per habilitar l'HMR.", "retrieve_current_mode": "Error en recuperar el mode actual de l'estat.", "failed_delete_repo": "Ha fallat l'eliminació del repositori o branca associada: {{error}}", diff --git a/src/i18n/locales/de/common.json b/src/i18n/locales/de/common.json index cc62749a8d0..efee4e28623 100644 --- a/src/i18n/locales/de/common.json +++ b/src/i18n/locales/de/common.json @@ -45,7 +45,7 @@ "list_api_config": "Fehler beim Abrufen der API-Konfigurationsliste", "update_server_timeout": "Fehler beim Aktualisieren des Server-Timeouts", "failed_update_project_mcp": "Fehler beim Aktualisieren der Projekt-MCP-Server", - "create_mcp_json": "Fehler beim Erstellen oder Öffnen von .roo/mcp.json: {{error}}", + "create_mcp_json": "Fehler beim Erstellen oder Öffnen von .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Der lokale Entwicklungsserver läuft nicht, HMR wird nicht funktionieren. Bitte führen Sie 'npm run dev' vor dem Start der Erweiterung aus, um HMR zu aktivieren.", "retrieve_current_mode": "Fehler beim Abrufen des aktuellen Modus aus dem Zustand.", "failed_delete_repo": "Fehler beim Löschen des zugehörigen Shadow-Repositorys oder -Zweigs: {{error}}", diff --git a/src/i18n/locales/en/common.json b/src/i18n/locales/en/common.json index b06f5e8091e..89b1b292fb6 100644 --- a/src/i18n/locales/en/common.json +++ b/src/i18n/locales/en/common.json @@ -44,7 +44,7 @@ "delete_api_config": "Failed to delete api configuration", "list_api_config": "Failed to get list api configuration", "update_server_timeout": "Failed to update server timeout", - "create_mcp_json": "Failed to create or open .roo/mcp.json: {{error}}", + "create_mcp_json": "Failed to create or open .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Local development server is not running, HMR will not work. Please run 'npm run dev' before launching the extension to enable HMR.", "retrieve_current_mode": "Error: failed to retrieve current mode from state.", "failed_delete_repo": "Failed to delete associated shadow repository or branch: {{error}}", diff --git a/src/i18n/locales/es/common.json b/src/i18n/locales/es/common.json index 25affcb4581..4a9b82e0be9 100644 --- a/src/i18n/locales/es/common.json +++ b/src/i18n/locales/es/common.json @@ -45,7 +45,7 @@ "list_api_config": "Error al obtener la lista de configuraciones de API", "update_server_timeout": "Error al actualizar el tiempo de espera del servidor", "failed_update_project_mcp": "Error al actualizar los servidores MCP del proyecto", - "create_mcp_json": "Error al crear o abrir .roo/mcp.json: {{error}}", + "create_mcp_json": "Error al crear o abrir .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "El servidor de desarrollo local no está en ejecución, HMR no funcionará. Por favor, ejecuta 'npm run dev' antes de lanzar la extensión para habilitar HMR.", "retrieve_current_mode": "Error al recuperar el modo actual del estado.", "failed_delete_repo": "Error al eliminar el repositorio o rama asociada: {{error}}", diff --git a/src/i18n/locales/fr/common.json b/src/i18n/locales/fr/common.json index d4ed08c1911..55e172100ee 100644 --- a/src/i18n/locales/fr/common.json +++ b/src/i18n/locales/fr/common.json @@ -45,7 +45,7 @@ "list_api_config": "Erreur lors de l'obtention de la liste des configurations API", "update_server_timeout": "Erreur lors de la mise à jour du délai d'attente du serveur", "failed_update_project_mcp": "Échec de la mise à jour des serveurs MCP du projet", - "create_mcp_json": "Échec de la création ou de l'ouverture de .roo/mcp.json : {{error}}", + "create_mcp_json": "Échec de la création ou de l'ouverture de .pearai-agent/mcp.json : {{error}}", "hmr_not_running": "Le serveur de développement local n'est pas en cours d'exécution, HMR ne fonctionnera pas. Veuillez exécuter 'npm run dev' avant de lancer l'extension pour activer l'HMR.", "retrieve_current_mode": "Erreur lors de la récupération du mode actuel à partir du state.", "failed_delete_repo": "Échec de la suppression du repo fantôme ou de la branche associée : {{error}}", diff --git a/src/i18n/locales/hi/common.json b/src/i18n/locales/hi/common.json index 8c244009d18..e4f3a51ebb8 100644 --- a/src/i18n/locales/hi/common.json +++ b/src/i18n/locales/hi/common.json @@ -45,7 +45,7 @@ "list_api_config": "API कॉन्फ़िगरेशन की सूची प्राप्त करने में विफल", "update_server_timeout": "सर्वर टाइमआउट अपडेट करने में विफल", "failed_update_project_mcp": "प्रोजेक्ट MCP सर्वर अपडेट करने में विफल", - "create_mcp_json": ".roo/mcp.json बनाने या खोलने में विफल: {{error}}", + "create_mcp_json": ".pearai-agent/mcp.json बनाने या खोलने में विफल: {{error}}", "hmr_not_running": "स्थानीय विकास सर्वर चल नहीं रहा है, HMR काम नहीं करेगा। कृपया HMR सक्षम करने के लिए एक्सटेंशन लॉन्च करने से पहले 'npm run dev' चलाएँ।", "retrieve_current_mode": "स्टेट से वर्तमान मोड प्राप्त करने में त्रुटि।", "failed_delete_repo": "संबंधित शैडो रिपॉजिटरी या ब्रांच हटाने में विफल: {{error}}", diff --git a/src/i18n/locales/it/common.json b/src/i18n/locales/it/common.json index 2c9879186f2..94dda7ea3f1 100644 --- a/src/i18n/locales/it/common.json +++ b/src/i18n/locales/it/common.json @@ -45,7 +45,7 @@ "list_api_config": "Errore durante l'ottenimento dell'elenco delle configurazioni API", "update_server_timeout": "Errore durante l'aggiornamento del timeout del server", "failed_update_project_mcp": "Errore durante l'aggiornamento dei server MCP del progetto", - "create_mcp_json": "Impossibile creare o aprire .roo/mcp.json: {{error}}", + "create_mcp_json": "Impossibile creare o aprire .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Il server di sviluppo locale non è in esecuzione, l'HMR non funzionerà. Esegui 'npm run dev' prima di avviare l'estensione per abilitare l'HMR.", "retrieve_current_mode": "Errore durante il recupero della modalità corrente dallo stato.", "failed_delete_repo": "Impossibile eliminare il repository o il ramo associato: {{error}}", diff --git a/src/i18n/locales/ja/common.json b/src/i18n/locales/ja/common.json index a2b283bd83e..dc6a9da9299 100644 --- a/src/i18n/locales/ja/common.json +++ b/src/i18n/locales/ja/common.json @@ -45,7 +45,7 @@ "list_api_config": "API設定リストの取得に失敗しました", "update_server_timeout": "サーバータイムアウトの更新に失敗しました", "failed_update_project_mcp": "プロジェクトMCPサーバーの更新に失敗しました", - "create_mcp_json": ".roo/mcp.jsonの作成または開くことに失敗しました:{{error}}", + "create_mcp_json": ".pearai-agent/mcp.jsonの作成または開くことに失敗しました:{{error}}", "hmr_not_running": "ローカル開発サーバーが実行されていないため、HMRは機能しません。HMRを有効にするには、拡張機能を起動する前に'npm run dev'を実行してください。", "retrieve_current_mode": "現在のモードを状態から取得する際にエラーが発生しました。", "failed_delete_repo": "関連するシャドウリポジトリまたはブランチの削除に失敗しました:{{error}}", diff --git a/src/i18n/locales/ko/common.json b/src/i18n/locales/ko/common.json index 9700d80f0e0..8e1ba132f44 100644 --- a/src/i18n/locales/ko/common.json +++ b/src/i18n/locales/ko/common.json @@ -45,7 +45,7 @@ "list_api_config": "API 구성 목록 가져오기에 실패했습니다", "update_server_timeout": "서버 타임아웃 업데이트에 실패했습니다", "failed_update_project_mcp": "프로젝트 MCP 서버 업데이트에 실패했습니다", - "create_mcp_json": ".roo/mcp.json 생성 또는 열기 실패: {{error}}", + "create_mcp_json": ".pearai-agent/mcp.json 생성 또는 열기 실패: {{error}}", "hmr_not_running": "로컬 개발 서버가 실행되고 있지 않아 HMR이 작동하지 않습니다. HMR을 활성화하려면 확장 프로그램을 실행하기 전에 'npm run dev'를 실행하세요.", "retrieve_current_mode": "상태에서 현재 모드를 검색하는 데 오류가 발생했습니다.", "failed_delete_repo": "관련 shadow 저장소 또는 브랜치 삭제 실패: {{error}}", diff --git a/src/i18n/locales/pl/common.json b/src/i18n/locales/pl/common.json index bcb345346d8..dbc459ad581 100644 --- a/src/i18n/locales/pl/common.json +++ b/src/i18n/locales/pl/common.json @@ -45,7 +45,7 @@ "list_api_config": "Nie udało się pobrać listy konfiguracji API", "update_server_timeout": "Nie udało się zaktualizować limitu czasu serwera", "failed_update_project_mcp": "Nie udało się zaktualizować serwerów MCP projektu", - "create_mcp_json": "Nie udało się utworzyć lub otworzyć .roo/mcp.json: {{error}}", + "create_mcp_json": "Nie udało się utworzyć lub otworzyć .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Lokalny serwer deweloperski nie jest uruchomiony, HMR nie będzie działać. Uruchom 'npm run dev' przed uruchomieniem rozszerzenia, aby włączyć HMR.", "retrieve_current_mode": "Błąd podczas pobierania bieżącego trybu ze stanu.", "failed_delete_repo": "Nie udało się usunąć powiązanego repozytorium lub gałęzi pomocniczej: {{error}}", diff --git a/src/i18n/locales/pt-BR/common.json b/src/i18n/locales/pt-BR/common.json index e2ade21da2d..0de62c10a54 100644 --- a/src/i18n/locales/pt-BR/common.json +++ b/src/i18n/locales/pt-BR/common.json @@ -49,7 +49,7 @@ "list_api_config": "Falha ao obter a lista de configurações da API", "update_server_timeout": "Falha ao atualizar o tempo limite do servidor", "failed_update_project_mcp": "Falha ao atualizar os servidores MCP do projeto", - "create_mcp_json": "Falha ao criar ou abrir .roo/mcp.json: {{error}}", + "create_mcp_json": "Falha ao criar ou abrir .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "O servidor de desenvolvimento local não está em execução, o HMR não funcionará. Por favor, execute 'npm run dev' antes de iniciar a extensão para habilitar o HMR.", "retrieve_current_mode": "Erro ao recuperar o modo atual do estado.", "failed_delete_repo": "Falha ao excluir o repositório ou ramificação associada: {{error}}", diff --git a/src/i18n/locales/ru/common.json b/src/i18n/locales/ru/common.json index 9f2ee4d9e87..f9f3a87b2d0 100644 --- a/src/i18n/locales/ru/common.json +++ b/src/i18n/locales/ru/common.json @@ -44,7 +44,7 @@ "delete_api_config": "Не удалось удалить конфигурацию API", "list_api_config": "Не удалось получить список конфигураций API", "update_server_timeout": "Не удалось обновить таймаут сервера", - "create_mcp_json": "Не удалось создать или открыть .roo/mcp.json: {{error}}", + "create_mcp_json": "Не удалось создать или открыть .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Локальный сервер разработки не запущен, HMR не будет работать. Пожалуйста, запустите 'npm run dev' перед запуском расширения для включения HMR.", "retrieve_current_mode": "Ошибка: не удалось получить текущий режим из состояния.", "failed_delete_repo": "Не удалось удалить связанный теневой репозиторий или ветку: {{error}}", diff --git a/src/i18n/locales/tr/common.json b/src/i18n/locales/tr/common.json index 9991cf0f825..0b3045166c5 100644 --- a/src/i18n/locales/tr/common.json +++ b/src/i18n/locales/tr/common.json @@ -45,7 +45,7 @@ "list_api_config": "API yapılandırma listesi alınamadı", "update_server_timeout": "Sunucu zaman aşımı güncellenemedi", "failed_update_project_mcp": "Proje MCP sunucuları güncellenemedi", - "create_mcp_json": ".roo/mcp.json oluşturulamadı veya açılamadı: {{error}}", + "create_mcp_json": ".pearai-agent/mcp.json oluşturulamadı veya açılamadı: {{error}}", "hmr_not_running": "Yerel geliştirme sunucusu çalışmıyor, HMR çalışmayacak. HMR'yi etkinleştirmek için uzantıyı başlatmadan önce lütfen 'npm run dev' komutunu çalıştırın.", "retrieve_current_mode": "Mevcut mod durumdan alınırken hata oluştu.", "failed_delete_repo": "İlişkili gölge depo veya dal silinemedi: {{error}}", diff --git a/src/i18n/locales/vi/common.json b/src/i18n/locales/vi/common.json index 613c62c8b3e..1375111ed95 100644 --- a/src/i18n/locales/vi/common.json +++ b/src/i18n/locales/vi/common.json @@ -45,7 +45,7 @@ "list_api_config": "Không thể lấy danh sách cấu hình API", "update_server_timeout": "Không thể cập nhật thời gian chờ máy chủ", "failed_update_project_mcp": "Không thể cập nhật máy chủ MCP của dự án", - "create_mcp_json": "Không thể tạo hoặc mở .roo/mcp.json: {{error}}", + "create_mcp_json": "Không thể tạo hoặc mở .pearai-agent/mcp.json: {{error}}", "hmr_not_running": "Máy chủ phát triển cục bộ không chạy, HMR sẽ không hoạt động. Vui lòng chạy 'npm run dev' trước khi khởi chạy tiện ích mở rộng để bật HMR.", "retrieve_current_mode": "Lỗi không thể truy xuất chế độ hiện tại từ trạng thái.", "failed_delete_repo": "Không thể xóa kho lưu trữ hoặc nhánh liên quan: {{error}}", diff --git a/src/i18n/locales/zh-CN/common.json b/src/i18n/locales/zh-CN/common.json index 9e4512c584d..66e84d55e07 100644 --- a/src/i18n/locales/zh-CN/common.json +++ b/src/i18n/locales/zh-CN/common.json @@ -45,7 +45,7 @@ "list_api_config": "获取API配置列表失败", "update_server_timeout": "更新服务器超时设置失败", "failed_update_project_mcp": "更新项目MCP服务器失败", - "create_mcp_json": "创建或打开 .roo/mcp.json 失败:{{error}}", + "create_mcp_json": "创建或打开 .pearai-agent/mcp.json 失败:{{error}}", "hmr_not_running": "本地开发服务器未运行,HMR将不起作用。请在启动扩展前运行'npm run dev'以启用HMR。", "retrieve_current_mode": "从状态中检索当前模式失败。", "failed_delete_repo": "删除关联的影子仓库或分支失败:{{error}}", diff --git a/src/i18n/locales/zh-TW/common.json b/src/i18n/locales/zh-TW/common.json index 1d12b862907..61f01c30622 100644 --- a/src/i18n/locales/zh-TW/common.json +++ b/src/i18n/locales/zh-TW/common.json @@ -45,7 +45,7 @@ "list_api_config": "取得 API 設定列表失敗", "update_server_timeout": "更新伺服器超時設定失敗", "failed_update_project_mcp": "更新專案 MCP 伺服器失敗", - "create_mcp_json": "建立或開啟 .roo/mcp.json 失敗:{{error}}", + "create_mcp_json": "建立或開啟 .pearai-agent/mcp.json 失敗:{{error}}", "hmr_not_running": "本機開發伺服器沒有執行,HMR 將不起作用。請在啟動擴充套件前執行'npm run dev'以啟用 HMR。", "retrieve_current_mode": "從狀態中檢索目前模式失敗。", "failed_delete_repo": "刪除關聯的影子倉庫或分支失敗:{{error}}", diff --git a/src/services/mcp/McpHub.ts b/src/services/mcp/McpHub.ts index e19dc849dd3..bb6ab004b3a 100644 --- a/src/services/mcp/McpHub.ts +++ b/src/services/mcp/McpHub.ts @@ -32,6 +32,7 @@ import { fileExistsAtPath } from "../../utils/fs" import { arePathsEqual } from "../../utils/path" import { injectEnv } from "../../utils/config" import { PEARAI_URL } from "../../shared/pearaiApi" +import { AGENT_RULES_DIR } from "../../shared/constants" export type McpConnection = { server: McpServer @@ -498,7 +499,7 @@ export class McpHub { } const workspaceFolder = vscode.workspace.workspaceFolders[0] - const projectMcpDir = path.join(workspaceFolder.uri.fsPath, ".roo") + const projectMcpDir = path.join(workspaceFolder.uri.fsPath, AGENT_RULES_DIR) const projectMcpPath = path.join(projectMcpDir, "mcp.json") try { diff --git a/src/shared/ExtensionMessage.ts b/src/shared/ExtensionMessage.ts index cbd03f0723d..e6f0c1297c8 100644 --- a/src/shared/ExtensionMessage.ts +++ b/src/shared/ExtensionMessage.ts @@ -183,7 +183,7 @@ export type ExtensionState = Pick< enableCheckpoints: boolean maxOpenTabsContext: number // Maximum number of VSCode open tabs to include in context (0-500) maxWorkspaceFiles: number // Maximum number of files to include in current working directory details (0-500) - showRooIgnoredFiles: boolean // Whether to show .rooignore'd files in listings + showRooIgnoredFiles: boolean // Whether to show .pearai-agent-ignore'd files in listings maxReadFileLine: number // Maximum number of lines to read from a file before truncating experiments: Record // Map of experiment IDs to their enabled state diff --git a/src/shared/constants.ts b/src/shared/constants.ts new file mode 100644 index 00000000000..ad3b74bf628 --- /dev/null +++ b/src/shared/constants.ts @@ -0,0 +1,5 @@ +export const AGENT_RULES_DIR = ".pearai-agent" + +export const AGENT_IGNORE_FILE_NAME = ".pearai-agent-ignore" + +export const AGENT_MODES_FILE_NAME = ".pearai-agent-modes" diff --git a/src/shared/pearaiApi.ts b/src/shared/pearaiApi.ts index 0d110218aa3..c0a5e4d3656 100644 --- a/src/shared/pearaiApi.ts +++ b/src/shared/pearaiApi.ts @@ -1,8 +1,8 @@ // CHANGE AS NEEDED FOR DEVELOPMENT // PROD: -export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" +// export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" // DEV: -// export const PEARAI_URL = "http://localhost:8000/integrations/cline" +export const PEARAI_URL = "http://localhost:8000/integrations/cline" import { anthropicModels, diff --git a/src/utils/path.ts b/src/utils/path.ts index a58d6301725..296665d907d 100644 --- a/src/utils/path.ts +++ b/src/utils/path.ts @@ -2,6 +2,7 @@ import * as path from "path" import os from "os" import * as vscode from "vscode" + /* The Node.js 'path' module resolves and normalizes paths differently depending on the platform: - On Windows, it uses backslashes (\) as the default path separator. diff --git a/webview-ui/src/components/prompts/PromptsView.tsx b/webview-ui/src/components/prompts/PromptsView.tsx index dcf819b2869..5d17dd04a60 100644 --- a/webview-ui/src/components/prompts/PromptsView.tsx +++ b/webview-ui/src/components/prompts/PromptsView.tsx @@ -29,6 +29,7 @@ import { Tab, TabContent, TabHeader } from "../common/Tab" import i18next from "i18next" import { useAppTranslation } from "@src/i18n/TranslationContext" import { Trans } from "react-i18next" +import { AGENT_MODES_FILE_NAME, AGENT_RULES_DIR } from "@roo/shared/constants" // Get all available groups that should show in prompts view const availableGroups = (Object.keys(TOOL_GROUPS) as ToolGroup[]).filter((group) => !TOOL_GROUPS[group].alwaysAvailable) @@ -459,7 +460,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { e.preventDefault() // Prevent blur vscode.postMessage({ type: "openFile", - text: "./.roomodes", + text: `./${AGENT_MODES_FILE_NAME}`, values: { create: true, content: JSON.stringify({ customModes: [] }, null, 2), @@ -819,7 +820,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { // Open or create an empty file vscode.postMessage({ type: "openFile", - text: `./.roo/rules-${currentMode.slug}/rules.md`, + text: `./${AGENT_RULES_DIR}/rules-${currentMode.slug}/rules.md`, values: { create: true, content: "", @@ -901,7 +902,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { vscode.postMessage({ type: "openFile", - text: `./.roo/system-prompt-${currentMode.slug}`, + text: `./${AGENT_RULES_DIR}/system-prompt-${currentMode.slug}`, values: { create: true, content: "", @@ -956,7 +957,7 @@ const PromptsView = ({ onDone }: PromptsViewProps) => { onClick={() => vscode.postMessage({ type: "openFile", - text: "./.roo/rules/rules.md", + text: `./${AGENT_RULES_DIR}/rules/rules.md`, values: { create: true, content: "", diff --git a/webview-ui/src/components/settings/ContextManagementSettings.tsx b/webview-ui/src/components/settings/ContextManagementSettings.tsx index 0f24316a12e..91f7d6913b8 100644 --- a/webview-ui/src/components/settings/ContextManagementSettings.tsx +++ b/webview-ui/src/components/settings/ContextManagementSettings.tsx @@ -84,11 +84,11 @@ export const ContextManagementSettings = ({ onChange={(e: any) => setCachedStateField("showRooIgnoredFiles", e.target.checked)} data-testid="show-rooignored-files-checkbox">
- {t("settings:contextManagement.rooignore.description")} + {t("settings:contextManagement.pearai-agent-ignore.description")}
diff --git a/webview-ui/src/components/settings/__tests__/ContextManagementSettings.test.tsx b/webview-ui/src/components/settings/__tests__/ContextManagementSettings.test.tsx index 955ce619369..2de704d9fff 100644 --- a/webview-ui/src/components/settings/__tests__/ContextManagementSettings.test.tsx +++ b/webview-ui/src/components/settings/__tests__/ContextManagementSettings.test.tsx @@ -47,7 +47,7 @@ describe("ContextManagementSettings", () => { const workspaceFilesSlider = screen.getByTestId("workspace-files-limit-slider") expect(workspaceFilesSlider).toBeInTheDocument() - // Show .rooignore'd files + // Show .pearai-agent-ignore'd files const showRooIgnoredFilesCheckbox = screen.getByTestId("show-rooignored-files-checkbox") expect(showRooIgnoredFilesCheckbox).toBeInTheDocument() expect(screen.getByTestId("show-rooignored-files-checkbox")).not.toBeChecked() diff --git a/webview-ui/src/context/ExtensionStateContext.tsx b/webview-ui/src/context/ExtensionStateContext.tsx index d0aab2d4529..6deabbd23e7 100644 --- a/webview-ui/src/context/ExtensionStateContext.tsx +++ b/webview-ui/src/context/ExtensionStateContext.tsx @@ -181,7 +181,7 @@ export const ExtensionStateContextProvider: React.FC<{ children: React.ReactNode cwd: "", browserToolEnabled: true, telemetrySetting: "unset", - showRooIgnoredFiles: true, // Default to showing .rooignore'd files with lock symbol (current behavior). + showRooIgnoredFiles: true, // Default to showing .pearai-agent-ignore'd files with lock symbol (current behavior). renderContext: "sidebar", maxReadFileLine: 500, // Default max read file line limit pinnedApiConfigs: {}, // Empty object for pinned API configs diff --git a/webview-ui/src/i18n/locales/ca/prompts.json b/webview-ui/src/i18n/locales/ca/prompts.json index d37e8629425..0a1ffc1425f 100644 --- a/webview-ui/src/i18n/locales/ca/prompts.json +++ b/webview-ui/src/i18n/locales/ca/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Crear nou mode", "editModesConfig": "Editar configuració de modes", "editGlobalModes": "Editar modes globals", - "editProjectModes": "Editar modes de projecte (.roomodes)", + "editProjectModes": "Editar modes de projecte (.pearai-agent-ignore)", "createModeHelpText": "Feu clic a + per crear un nou mode personalitzat, o simplement demaneu a Roo al xat que en creï un per a vostè!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Instruccions personalitzades específiques del mode (opcional)", "resetToDefault": "Restablir a valors predeterminats", "description": "Afegiu directrius de comportament específiques per al mode {{modeName}}.", - "loadFromFile": "Les instruccions personalitzades específiques per al mode {{mode}} també es poden carregar des de la carpeta .roo/rules-{{slug}}/ al vostre espai de treball (.roorules-{{slug}} i .clinerules-{{slug}} estan obsolets i deixaran de funcionar aviat)." + "loadFromFile": "Les instruccions personalitzades específiques per al mode {{mode}} també es poden carregar des de la carpeta .pearai-agent/rules-{{slug}}/ al vostre espai de treball (.roorules-{{slug}} i .clinerules-{{slug}} estan obsolets i deixaran de funcionar aviat)." }, "globalCustomInstructions": { "title": "Instruccions personalitzades per a tots els modes", "description": "Aquestes instruccions s'apliquen a tots els modes. Proporcionen un conjunt bàsic de comportaments que es poden millorar amb instruccions específiques de cada mode a continuació.\nSi voleu que Roo pensi i parli en un idioma diferent al de la visualització del vostre editor ({{language}}), podeu especificar-ho aquí.", - "loadFromFile": "Les instruccions també es poden carregar des de la carpeta .roo/rules/ al vostre espai de treball (.roorules i .clinerules estan obsolets i deixaran de funcionar aviat)." + "loadFromFile": "Les instruccions també es poden carregar des de la carpeta .pearai-agent/rules/ al vostre espai de treball (.roorules i .clinerules estan obsolets i deixaran de funcionar aviat)." }, "systemPrompt": { "preview": "Previsualització del prompt del sistema", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Avançat: Sobreescriure prompt del sistema", - "description": "Podeu reemplaçar completament el prompt del sistema per a aquest mode (a part de la definició de rol i instruccions personalitzades) creant un fitxer a .roo/system-prompt-{{slug}} al vostre espai de treball. Aquesta és una funcionalitat molt avançada que eludeix les salvaguardes integrades i les comprovacions de consistència (especialment al voltant de l'ús d'eines), així que aneu amb compte!" + "description": "Podeu reemplaçar completament el prompt del sistema per a aquest mode (a part de la definició de rol i instruccions personalitzades) creant un fitxer a .pearai-agent/system-prompt-{{slug}} al vostre espai de treball. Aquesta és una funcionalitat molt avançada que eludeix les salvaguardes integrades i les comprovacions de consistència (especialment al voltant de l'ús d'eines), així que aneu amb compte!" }, "createModeDialog": { "title": "Crear nou mode", @@ -122,7 +122,7 @@ "description": "Disponible a tots els espais de treball" }, "project": { - "label": "Específic del projecte (.roomodes)", + "label": "Específic del projecte (.pearai-agent-ignore)", "description": "Només disponible en aquest espai de treball, té prioritat sobre el global" } }, diff --git a/webview-ui/src/i18n/locales/ca/settings.json b/webview-ui/src/i18n/locales/ca/settings.json index badeaf63bb9..b742cfeb71c 100644 --- a/webview-ui/src/i18n/locales/ca/settings.json +++ b/webview-ui/src/i18n/locales/ca/settings.json @@ -298,9 +298,9 @@ "label": "Límit de context de fitxers de l'espai de treball", "description": "Nombre màxim de fitxers a incloure als detalls del directori de treball actual. Valors més alts proporcionen més context però augmenten l'ús de token." }, - "rooignore": { - "label": "Mostrar fitxers .rooignore en llistes i cerques", - "description": "Quan està habilitat, els fitxers que coincideixen amb els patrons a .rooignore es mostraran en llistes amb un símbol de cadenat. Quan està deshabilitat, aquests fitxers s'ocultaran completament de les llistes de fitxers i cerques." + "pearai-agent-ignore": { + "label": "Mostrar fitxers .pearai-agent-ignore en llistes i cerques", + "description": "Quan està habilitat, els fitxers que coincideixen amb els patrons a .pearai-agent-ignore es mostraran en llistes amb un símbol de cadenat. Quan està deshabilitat, aquests fitxers s'ocultaran completament de les llistes de fitxers i cerques." }, "maxReadFile": { "label": "Llindar d'auto-truncament de lectura de fitxers", diff --git a/webview-ui/src/i18n/locales/de/prompts.json b/webview-ui/src/i18n/locales/de/prompts.json index 7d0a19ec470..df67f25aee5 100644 --- a/webview-ui/src/i18n/locales/de/prompts.json +++ b/webview-ui/src/i18n/locales/de/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Neuen Modus erstellen", "editModesConfig": "Moduskonfiguration bearbeiten", "editGlobalModes": "Globale Modi bearbeiten", - "editProjectModes": "Projektmodi bearbeiten (.roomodes)", + "editProjectModes": "Projektmodi bearbeiten (.pearai-agent-ignore)", "createModeHelpText": "Klicke auf +, um einen neuen benutzerdefinierten Modus zu erstellen, oder bitte Roo einfach im Chat, einen für dich zu erstellen!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Modusspezifische benutzerdefinierte Anweisungen (optional)", "resetToDefault": "Auf Standardwerte zurücksetzen", "description": "Fügen Sie verhaltensspezifische Richtlinien für den Modus {{modeName}} hinzu.", - "loadFromFile": "Benutzerdefinierte Anweisungen für den Modus {{mode}} können auch aus dem Ordner .roo/rules-{{slug}}/ in deinem Arbeitsbereich geladen werden (.roorules-{{slug}} und .clinerules-{{slug}} sind veraltet und werden bald nicht mehr funktionieren)." + "loadFromFile": "Benutzerdefinierte Anweisungen für den Modus {{mode}} können auch aus dem Ordner .pearai-agent/rules-{{slug}}/ in deinem Arbeitsbereich geladen werden (.roorules-{{slug}} und .clinerules-{{slug}} sind veraltet und werden bald nicht mehr funktionieren)." }, "globalCustomInstructions": { "title": "Benutzerdefinierte Anweisungen für alle Modi", "description": "Diese Anweisungen gelten für alle Modi. Sie bieten einen grundlegenden Satz von Verhaltensweisen, die durch modusspezifische Anweisungen unten erweitert werden können.\nWenn du möchtest, dass Roo in einer anderen Sprache als deiner Editor-Anzeigesprache ({{language}}) denkt und spricht, kannst du das hier angeben.", - "loadFromFile": "Anweisungen können auch aus dem Ordner .roo/rules/ in deinem Arbeitsbereich geladen werden (.roorules und .clinerules sind veraltet und werden bald nicht mehr funktionieren)." + "loadFromFile": "Anweisungen können auch aus dem Ordner .pearai-agent/rules/ in deinem Arbeitsbereich geladen werden (.roorules und .clinerules sind veraltet und werden bald nicht mehr funktionieren)." }, "systemPrompt": { "preview": "System-Prompt Vorschau", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Erweitert: System-Prompt überschreiben", - "description": "Du kannst den System-Prompt für diesen Modus vollständig ersetzen (abgesehen von der Rollendefinition und benutzerdefinierten Anweisungen), indem du eine Datei unter .roo/system-prompt-{{slug}} in deinem Arbeitsbereich erstellst. Dies ist eine sehr fortgeschrittene Funktion, die eingebaute Schutzmaßnahmen und Konsistenzprüfungen umgeht (besonders bei der Werkzeugnutzung), also sei vorsichtig!" + "description": "Du kannst den System-Prompt für diesen Modus vollständig ersetzen (abgesehen von der Rollendefinition und benutzerdefinierten Anweisungen), indem du eine Datei unter .pearai-agent/system-prompt-{{slug}} in deinem Arbeitsbereich erstellst. Dies ist eine sehr fortgeschrittene Funktion, die eingebaute Schutzmaßnahmen und Konsistenzprüfungen umgeht (besonders bei der Werkzeugnutzung), also sei vorsichtig!" }, "createModeDialog": { "title": "Neuen Modus erstellen", @@ -122,7 +122,7 @@ "description": "Verfügbar in allen Arbeitsbereichen" }, "project": { - "label": "Projektspezifisch (.roomodes)", + "label": "Projektspezifisch (.pearai-agent-ignore)", "description": "Nur in diesem Arbeitsbereich verfügbar, hat Vorrang vor global" } }, diff --git a/webview-ui/src/i18n/locales/de/settings.json b/webview-ui/src/i18n/locales/de/settings.json index 901fc756174..ef31bc04a10 100644 --- a/webview-ui/src/i18n/locales/de/settings.json +++ b/webview-ui/src/i18n/locales/de/settings.json @@ -298,9 +298,9 @@ "label": "Workspace-Dateien Kontextlimit", "description": "Maximale Anzahl von Dateien, die in den Details des aktuellen Arbeitsverzeichnisses enthalten sein sollen. Höhere Werte bieten mehr Kontext, erhöhen aber den Token-Verbrauch." }, - "rooignore": { - "label": ".rooignore-Dateien in Listen und Suchen anzeigen", - "description": "Wenn aktiviert, werden Dateien, die mit Mustern in .rooignore übereinstimmen, in Listen mit einem Schlosssymbol angezeigt. Wenn deaktiviert, werden diese Dateien vollständig aus Dateilisten und Suchen ausgeblendet." + "pearai-agent-ignore": { + "label": ".pearai-agent-ignore-Dateien in Listen und Suchen anzeigen", + "description": "Wenn aktiviert, werden Dateien, die mit Mustern in .pearai-agent-ignore übereinstimmen, in Listen mit einem Schlosssymbol angezeigt. Wenn deaktiviert, werden diese Dateien vollständig aus Dateilisten und Suchen ausgeblendet." }, "maxReadFile": { "label": "Schwellenwert für automatische Dateilesekürzung", diff --git a/webview-ui/src/i18n/locales/en/prompts.json b/webview-ui/src/i18n/locales/en/prompts.json index ce567a48697..8b603c77c50 100644 --- a/webview-ui/src/i18n/locales/en/prompts.json +++ b/webview-ui/src/i18n/locales/en/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Create new mode", "editModesConfig": "Edit modes configuration", "editGlobalModes": "Edit Global Modes", - "editProjectModes": "Edit Project Modes (.roomodes)", + "editProjectModes": "Edit Project Modes (.pearai-agent-ignore)", "createModeHelpText": "Hit the + to create a new custom mode, or just ask Roo in chat to create one for you!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Mode-specific Custom Instructions (optional)", "resetToDefault": "Reset to default", "description": "Add behavioral guidelines specific to {{modeName}} mode.", - "loadFromFile": "Custom instructions specific to {{mode}} mode can also be loaded from the .roo/rules-{{slug}}/ folder in your workspace (.roorules-{{slug}} and .clinerules-{{slug}} are deprecated and will stop working soon)." + "loadFromFile": "Custom instructions specific to {{mode}} mode can also be loaded from the .pearai-agent/rules-{{slug}}/ folder in your workspace (.roorules-{{slug}} and .clinerules-{{slug}} are deprecated and will stop working soon)." }, "globalCustomInstructions": { "title": "Custom Instructions for All Modes", "description": "These instructions apply to all modes. They provide a base set of behaviors that can be enhanced by mode-specific instructions below.\nIf you would like Roo to think and speak in a different language than your editor display language ({{language}}), you can specify it here.", - "loadFromFile": "Instructions can also be loaded from the .roo/rules/ folder in your workspace (.roorules and .clinerules are deprecated and will stop working soon)." + "loadFromFile": "Instructions can also be loaded from the .pearai-agent/rules/ folder in your workspace (.roorules and .clinerules are deprecated and will stop working soon)." }, "systemPrompt": { "preview": "Preview System Prompt", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Advanced: Override System Prompt", - "description": "You can completely replace the system prompt for this mode (aside from the role definition and custom instructions) by creating a file at .roo/system-prompt-{{slug}} in your workspace. This is a very advanced feature that bypasses built-in safeguards and consistency checks (especially around tool usage), so be careful!" + "description": "You can completely replace the system prompt for this mode (aside from the role definition and custom instructions) by creating a file at .pearai-agent/system-prompt-{{slug}} in your workspace. This is a very advanced feature that bypasses built-in safeguards and consistency checks (especially around tool usage), so be careful!" }, "createModeDialog": { "title": "Create New Mode", @@ -122,7 +122,7 @@ "description": "Available in all workspaces" }, "project": { - "label": "Project-specific (.roomodes)", + "label": "Project-specific (.pearai-agent-ignore)", "description": "Only available in this workspace, takes precedence over global" } }, diff --git a/webview-ui/src/i18n/locales/en/settings.json b/webview-ui/src/i18n/locales/en/settings.json index 99e4fee600d..197937bb26e 100644 --- a/webview-ui/src/i18n/locales/en/settings.json +++ b/webview-ui/src/i18n/locales/en/settings.json @@ -298,9 +298,9 @@ "label": "Workspace files context limit", "description": "Maximum number of files to include in current working directory details. Higher values provide more context but increase token usage." }, - "rooignore": { - "label": "Show .rooignore'd files in lists and searches", - "description": "When enabled, files matching patterns in .rooignore will be shown in lists with a lock symbol. When disabled, these files will be completely hidden from file lists and searches." + "pearai-agent-ignore": { + "label": "Show .pearai-agent-ignore'd files in lists and searches", + "description": "When enabled, files matching patterns in .pearai-agent-ignore will be shown in lists with a lock symbol. When disabled, these files will be completely hidden from file lists and searches." }, "maxReadFile": { "label": "File read auto-truncate threshold", diff --git a/webview-ui/src/i18n/locales/es/prompts.json b/webview-ui/src/i18n/locales/es/prompts.json index 3c6b0526393..a34f97b0deb 100644 --- a/webview-ui/src/i18n/locales/es/prompts.json +++ b/webview-ui/src/i18n/locales/es/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Crear nuevo modo", "editModesConfig": "Editar configuración de modos", "editGlobalModes": "Editar modos globales", - "editProjectModes": "Editar modos del proyecto (.roomodes)", + "editProjectModes": "Editar modos del proyecto (.pearai-agent-ignore)", "createModeHelpText": "¡Haz clic en + para crear un nuevo modo personalizado, o simplemente pídele a Roo en el chat que te cree uno!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Instrucciones personalizadas para el modo (opcional)", "resetToDefault": "Restablecer a valores predeterminados", "description": "Agrega directrices de comportamiento específicas para el modo {{modeName}}.", - "loadFromFile": "Las instrucciones personalizadas para el modo {{mode}} también se pueden cargar desde la carpeta .roo/rules-{{slug}}/ en tu espacio de trabajo (.roorules-{{slug}} y .clinerules-{{slug}} están obsoletos y dejarán de funcionar pronto)." + "loadFromFile": "Las instrucciones personalizadas para el modo {{mode}} también se pueden cargar desde la carpeta .pearai-agent/rules-{{slug}}/ en tu espacio de trabajo (.roorules-{{slug}} y .clinerules-{{slug}} están obsoletos y dejarán de funcionar pronto)." }, "globalCustomInstructions": { "title": "Instrucciones personalizadas para todos los modos", "description": "Estas instrucciones se aplican a todos los modos. Proporcionan un conjunto base de comportamientos que pueden ser mejorados por instrucciones específicas de cada modo.\nSi quieres que Roo piense y hable en un idioma diferente al idioma de visualización de tu editor ({{language}}), puedes especificarlo aquí.", - "loadFromFile": "Las instrucciones también se pueden cargar desde la carpeta .roo/rules/ en tu espacio de trabajo (.roorules y .clinerules están obsoletos y dejarán de funcionar pronto)." + "loadFromFile": "Las instrucciones también se pueden cargar desde la carpeta .pearai-agent/rules/ en tu espacio de trabajo (.roorules y .clinerules están obsoletos y dejarán de funcionar pronto)." }, "systemPrompt": { "preview": "Vista previa de la solicitud del sistema", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Avanzado: Anular solicitud del sistema", - "description": "Puedes reemplazar completamente la solicitud del sistema para este modo (aparte de la definición de rol e instrucciones personalizadas) creando un archivo en .roo/system-prompt-{{slug}} en tu espacio de trabajo. ¡Esta es una función muy avanzada que omite las salvaguardas integradas y las verificaciones de consistencia (especialmente en torno al uso de herramientas), así que ten cuidado!" + "description": "Puedes reemplazar completamente la solicitud del sistema para este modo (aparte de la definición de rol e instrucciones personalizadas) creando un archivo en .pearai-agent/system-prompt-{{slug}} en tu espacio de trabajo. ¡Esta es una función muy avanzada que omite las salvaguardas integradas y las verificaciones de consistencia (especialmente en torno al uso de herramientas), así que ten cuidado!" }, "createModeDialog": { "title": "Crear nuevo modo", @@ -122,7 +122,7 @@ "description": "Disponible en todos los espacios de trabajo" }, "project": { - "label": "Específico del proyecto (.roomodes)", + "label": "Específico del proyecto (.pearai-agent-ignore)", "description": "Solo disponible en este espacio de trabajo, tiene prioridad sobre el global" } }, diff --git a/webview-ui/src/i18n/locales/es/settings.json b/webview-ui/src/i18n/locales/es/settings.json index 71630ef98e0..74b2b9fd0f6 100644 --- a/webview-ui/src/i18n/locales/es/settings.json +++ b/webview-ui/src/i18n/locales/es/settings.json @@ -298,9 +298,9 @@ "label": "Límite de contexto de archivos del espacio de trabajo", "description": "Número máximo de archivos a incluir en los detalles del directorio de trabajo actual. Valores más altos proporcionan más contexto pero aumentan el uso de token." }, - "rooignore": { - "label": "Mostrar archivos .rooignore en listas y búsquedas", - "description": "Cuando está habilitado, los archivos que coinciden con los patrones en .rooignore se mostrarán en listas con un símbolo de candado. Cuando está deshabilitado, estos archivos se ocultarán completamente de las listas de archivos y búsquedas." + "pearai-agent-ignore": { + "label": "Mostrar archivos .pearai-agent-ignore en listas y búsquedas", + "description": "Cuando está habilitado, los archivos que coinciden con los patrones en .pearai-agent-ignore se mostrarán en listas con un símbolo de candado. Cuando está deshabilitado, estos archivos se ocultarán completamente de las listas de archivos y búsquedas." }, "maxReadFile": { "label": "Umbral de auto-truncado de lectura de archivos", diff --git a/webview-ui/src/i18n/locales/fr/prompts.json b/webview-ui/src/i18n/locales/fr/prompts.json index b746bd83117..72b86999bc3 100644 --- a/webview-ui/src/i18n/locales/fr/prompts.json +++ b/webview-ui/src/i18n/locales/fr/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Créer un nouveau mode", "editModesConfig": "Modifier la configuration des modes", "editGlobalModes": "Modifier les modes globaux", - "editProjectModes": "Modifier les modes du projet (.roomodes)", + "editProjectModes": "Modifier les modes du projet (.pearai-agent-ignore)", "createModeHelpText": "Cliquez sur + pour créer un nouveau mode personnalisé, ou demandez simplement à Roo dans le chat de vous en créer un !" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Instructions personnalisées spécifiques au mode (optionnel)", "resetToDefault": "Réinitialiser aux valeurs par défaut", "description": "Ajoutez des directives comportementales spécifiques au mode {{modeName}}.", - "loadFromFile": "Les instructions personnalisées spécifiques au mode {{mode}} peuvent également être chargées depuis le dossier .roo/rules-{{slug}}/ dans votre espace de travail (.roorules-{{slug}} et .clinerules-{{slug}} sont obsolètes et cesseront de fonctionner bientôt)." + "loadFromFile": "Les instructions personnalisées spécifiques au mode {{mode}} peuvent également être chargées depuis le dossier .pearai-agent/rules-{{slug}}/ dans votre espace de travail (.roorules-{{slug}} et .clinerules-{{slug}} sont obsolètes et cesseront de fonctionner bientôt)." }, "globalCustomInstructions": { "title": "Instructions personnalisées pour tous les modes", "description": "Ces instructions s'appliquent à tous les modes. Elles fournissent un ensemble de comportements de base qui peuvent être améliorés par des instructions spécifiques au mode ci-dessous.\nSi vous souhaitez que Roo pense et parle dans une langue différente de celle de votre éditeur ({{language}}), vous pouvez le spécifier ici.", - "loadFromFile": "Les instructions peuvent également être chargées depuis le dossier .roo/rules/ dans votre espace de travail (.roorules et .clinerules sont obsolètes et cesseront de fonctionner bientôt)." + "loadFromFile": "Les instructions peuvent également être chargées depuis le dossier .pearai-agent/rules/ dans votre espace de travail (.roorules et .clinerules sont obsolètes et cesseront de fonctionner bientôt)." }, "systemPrompt": { "preview": "Aperçu du prompt système", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Avancé : Remplacer le prompt système", - "description": "Vous pouvez complètement remplacer le prompt système pour ce mode (en dehors de la définition du rôle et des instructions personnalisées) en créant un fichier à .roo/system-prompt-{{slug}} dans votre espace de travail. Il s'agit d'une fonctionnalité très avancée qui contourne les garanties intégrées et les vérifications de cohérence (notamment concernant l'utilisation des outils), alors soyez prudent !" + "description": "Vous pouvez complètement remplacer le prompt système pour ce mode (en dehors de la définition du rôle et des instructions personnalisées) en créant un fichier à .pearai-agent/system-prompt-{{slug}} dans votre espace de travail. Il s'agit d'une fonctionnalité très avancée qui contourne les garanties intégrées et les vérifications de cohérence (notamment concernant l'utilisation des outils), alors soyez prudent !" }, "createModeDialog": { "title": "Créer un nouveau mode", @@ -122,7 +122,7 @@ "description": "Disponible dans tous les espaces de travail" }, "project": { - "label": "Spécifique au projet (.roomodes)", + "label": "Spécifique au projet (.pearai-agent-ignore)", "description": "Disponible uniquement dans cet espace de travail, a priorité sur le global" } }, diff --git a/webview-ui/src/i18n/locales/fr/settings.json b/webview-ui/src/i18n/locales/fr/settings.json index 53122381b3a..9d0930d8108 100644 --- a/webview-ui/src/i18n/locales/fr/settings.json +++ b/webview-ui/src/i18n/locales/fr/settings.json @@ -298,9 +298,9 @@ "label": "Limite de contexte des fichiers de l'espace de travail", "description": "Nombre maximum de fichiers à inclure dans les détails du répertoire de travail actuel. Des valeurs plus élevées fournissent plus de contexte mais augmentent l'utilisation de token." }, - "rooignore": { - "label": "Afficher les fichiers .rooignore dans les listes et recherches", - "description": "Lorsque cette option est activée, les fichiers correspondant aux modèles dans .rooignore seront affichés dans les listes avec un symbole de cadenas. Lorsqu'elle est désactivée, ces fichiers seront complètement masqués des listes de fichiers et des recherches." + "pearai-agent-ignore": { + "label": "Afficher les fichiers .pearai-agent-ignore dans les listes et recherches", + "description": "Lorsque cette option est activée, les fichiers correspondant aux modèles dans .pearai-agent-ignore seront affichés dans les listes avec un symbole de cadenas. Lorsqu'elle est désactivée, ces fichiers seront complètement masqués des listes de fichiers et des recherches." }, "maxReadFile": { "label": "Seuil d'auto-troncature de lecture de fichier", diff --git a/webview-ui/src/i18n/locales/hi/prompts.json b/webview-ui/src/i18n/locales/hi/prompts.json index d5291a577c7..83092ae6a6a 100644 --- a/webview-ui/src/i18n/locales/hi/prompts.json +++ b/webview-ui/src/i18n/locales/hi/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "नया मोड बनाएँ", "editModesConfig": "मोड कॉन्फ़िगरेशन संपादित करें", "editGlobalModes": "ग्लोबल मोड्स संपादित करें", - "editProjectModes": "प्रोजेक्ट मोड्स संपादित करें (.roomodes)", + "editProjectModes": "प्रोजेक्ट मोड्स संपादित करें (.pearai-agent-ignore)", "createModeHelpText": "नया कस्टम मोड बनाने के लिए + पर क्लिक करें, या बस चैट में Roo से आपके लिए एक बनाने को कहें!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "मोड-विशिष्ट कस्टम निर्देश (वैकल्पिक)", "resetToDefault": "डिफ़ॉल्ट पर रीसेट करें", "description": "{{modeName}} मोड के लिए विशिष्ट व्यवहार दिशानिर्देश जोड़ें।", - "loadFromFile": "{{mode}} मोड के लिए विशिष्ट कस्टम निर्देश आपके वर्कस्पेस में .roo/rules-{{slug}}/ फ़ोल्डर से भी लोड किए जा सकते हैं (.roorules-{{slug}} और .clinerules-{{slug}} पुराने हो गए हैं और जल्द ही काम करना बंद कर देंगे)।" + "loadFromFile": "{{mode}} मोड के लिए विशिष्ट कस्टम निर्देश आपके वर्कस्पेस में .pearai-agent/rules-{{slug}}/ फ़ोल्डर से भी लोड किए जा सकते हैं (.roorules-{{slug}} और .clinerules-{{slug}} पुराने हो गए हैं और जल्द ही काम करना बंद कर देंगे)।" }, "globalCustomInstructions": { "title": "सभी मोड्स के लिए कस्टम निर्देश", "description": "ये निर्देश सभी मोड्स पर लागू होते हैं। वे व्यवहारों का एक आधार सेट प्रदान करते हैं जिन्हें नीचे दिए गए मोड-विशिष्ट निर्देशों द्वारा बढ़ाया जा सकता है।\nयदि आप चाहते हैं कि Roo आपके एडिटर की प्रदर्शन भाषा ({{language}}) से अलग भाषा में सोचे और बोले, तो आप यहां इसे निर्दिष्ट कर सकते हैं।", - "loadFromFile": "निर्देश आपके वर्कस्पेस में .roo/rules/ फ़ोल्डर से भी लोड किए जा सकते हैं (.roorules और .clinerules पुराने हो गए हैं और जल्द ही काम करना बंद कर देंगे)।" + "loadFromFile": "निर्देश आपके वर्कस्पेस में .pearai-agent/rules/ फ़ोल्डर से भी लोड किए जा सकते हैं (.roorules और .clinerules पुराने हो गए हैं और जल्द ही काम करना बंद कर देंगे)।" }, "systemPrompt": { "preview": "सिस्टम प्रॉम्प्ट का पूर्वावलोकन", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "उन्नत: सिस्टम प्रॉम्प्ट ओवरराइड करें", - "description": "आप अपने वर्कस्पेस में .roo/system-prompt-{{slug}} पर एक फाइल बनाकर इस मोड के लिए सिस्टम प्रॉम्प्ट को पूरी तरह से बदल सकते हैं (भूमिका परिभाषा और कस्टम निर्देशों को छोड़कर)। यह एक बहुत उन्नत सुविधा है जो अंतर्निहित सुरक्षा उपायों और सामंजस्यता जांचों को बायपास करती है (विशेष रूप से टूल उपयोग के आसपास), इसलिए सावधान रहें!" + "description": "आप अपने वर्कस्पेस में .pearai-agent/system-prompt-{{slug}} पर एक फाइल बनाकर इस मोड के लिए सिस्टम प्रॉम्प्ट को पूरी तरह से बदल सकते हैं (भूमिका परिभाषा और कस्टम निर्देशों को छोड़कर)। यह एक बहुत उन्नत सुविधा है जो अंतर्निहित सुरक्षा उपायों और सामंजस्यता जांचों को बायपास करती है (विशेष रूप से टूल उपयोग के आसपास), इसलिए सावधान रहें!" }, "createModeDialog": { "title": "नया मोड बनाएँ", @@ -122,7 +122,7 @@ "description": "सभी वर्कस्पेस में उपलब्ध" }, "project": { - "label": "प्रोजेक्ट-विशिष्ट (.roomodes)", + "label": "प्रोजेक्ट-विशिष्ट (.pearai-agent-ignore)", "description": "केवल इस वर्कस्पेस में उपलब्ध, ग्लोबल पर प्राथमिकता रखता है" } }, diff --git a/webview-ui/src/i18n/locales/hi/settings.json b/webview-ui/src/i18n/locales/hi/settings.json index 32362ae5e25..e40028cbdd8 100644 --- a/webview-ui/src/i18n/locales/hi/settings.json +++ b/webview-ui/src/i18n/locales/hi/settings.json @@ -298,9 +298,9 @@ "label": "वर्कस्पेस फाइल संदर्भ सीमा", "description": "वर्तमान कार्य निर्देशिका विवरण में शामिल करने के लिए फाइलों की अधिकतम संख्या। उच्च मान अधिक संदर्भ प्रदान करते हैं लेकिन token उपयोग बढ़ाते हैं।" }, - "rooignore": { - "label": "सूचियों और खोजों में .rooignore फाइलें दिखाएँ", - "description": "जब सक्षम होता है, .rooignore में पैटर्न से मेल खाने वाली फाइलें लॉक प्रतीक के साथ सूचियों में दिखाई जाएंगी। जब अक्षम होता है, ये फाइलें फाइल सूचियों और खोजों से पूरी तरह छिपा दी जाएंगी।" + "pearai-agent-ignore": { + "label": "सूचियों और खोजों में .pearai-agent-ignore फाइलें दिखाएँ", + "description": "जब सक्षम होता है, .pearai-agent-ignore में पैटर्न से मेल खाने वाली फाइलें लॉक प्रतीक के साथ सूचियों में दिखाई जाएंगी। जब अक्षम होता है, ये फाइलें फाइल सूचियों और खोजों से पूरी तरह छिपा दी जाएंगी।" }, "maxReadFile": { "label": "फ़ाइल पढ़ने का स्वचालित काटने की सीमा", diff --git a/webview-ui/src/i18n/locales/it/prompts.json b/webview-ui/src/i18n/locales/it/prompts.json index 81bb7534def..d9e4ce12966 100644 --- a/webview-ui/src/i18n/locales/it/prompts.json +++ b/webview-ui/src/i18n/locales/it/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Crea nuova modalità", "editModesConfig": "Modifica configurazione modalità", "editGlobalModes": "Modifica modalità globali", - "editProjectModes": "Modifica modalità di progetto (.roomodes)", + "editProjectModes": "Modifica modalità di progetto (.pearai-agent-ignore)", "createModeHelpText": "Clicca sul + per creare una nuova modalità personalizzata, o chiedi semplicemente a Roo nella chat di crearne una per te!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Istruzioni personalizzate specifiche per la modalità (opzionale)", "resetToDefault": "Ripristina predefiniti", "description": "Aggiungi linee guida comportamentali specifiche per la modalità {{modeName}}.", - "loadFromFile": "Le istruzioni personalizzate specifiche per la modalità {{mode}} possono essere caricate anche dalla cartella .roo/rules-{{slug}}/ nel tuo spazio di lavoro (.roorules-{{slug}} e .clinerules-{{slug}} sono obsoleti e smetteranno di funzionare presto)." + "loadFromFile": "Le istruzioni personalizzate specifiche per la modalità {{mode}} possono essere caricate anche dalla cartella .pearai-agent/rules-{{slug}}/ nel tuo spazio di lavoro (.roorules-{{slug}} e .clinerules-{{slug}} sono obsoleti e smetteranno di funzionare presto)." }, "globalCustomInstructions": { "title": "Istruzioni personalizzate per tutte le modalità", "description": "Queste istruzioni si applicano a tutte le modalità. Forniscono un insieme base di comportamenti che possono essere migliorati dalle istruzioni specifiche per modalità qui sotto.\nSe desideri che Roo pensi e parli in una lingua diversa dalla lingua di visualizzazione del tuo editor ({{language}}), puoi specificarlo qui.", - "loadFromFile": "Le istruzioni possono essere caricate anche dalla cartella .roo/rules/ nel tuo spazio di lavoro (.roorules e .clinerules sono obsoleti e smetteranno di funzionare presto)." + "loadFromFile": "Le istruzioni possono essere caricate anche dalla cartella .pearai-agent/rules/ nel tuo spazio di lavoro (.roorules e .clinerules sono obsoleti e smetteranno di funzionare presto)." }, "systemPrompt": { "preview": "Anteprima prompt di sistema", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Avanzato: Sovrascrivi prompt di sistema", - "description": "Puoi sostituire completamente il prompt di sistema per questa modalità (a parte la definizione del ruolo e le istruzioni personalizzate) creando un file in .roo/system-prompt-{{slug}} nel tuo spazio di lavoro. Questa è una funzionalità molto avanzata che bypassa le protezioni integrate e i controlli di coerenza (specialmente riguardo all'uso degli strumenti), quindi fai attenzione!" + "description": "Puoi sostituire completamente il prompt di sistema per questa modalità (a parte la definizione del ruolo e le istruzioni personalizzate) creando un file in .pearai-agent/system-prompt-{{slug}} nel tuo spazio di lavoro. Questa è una funzionalità molto avanzata che bypassa le protezioni integrate e i controlli di coerenza (specialmente riguardo all'uso degli strumenti), quindi fai attenzione!" }, "createModeDialog": { "title": "Crea nuova modalità", @@ -122,7 +122,7 @@ "description": "Disponibile in tutti gli spazi di lavoro" }, "project": { - "label": "Specifico del progetto (.roomodes)", + "label": "Specifico del progetto (.pearai-agent-ignore)", "description": "Disponibile solo in questo spazio di lavoro, ha la precedenza sul globale" } }, diff --git a/webview-ui/src/i18n/locales/it/settings.json b/webview-ui/src/i18n/locales/it/settings.json index a697e547efa..941c3beb481 100644 --- a/webview-ui/src/i18n/locales/it/settings.json +++ b/webview-ui/src/i18n/locales/it/settings.json @@ -298,9 +298,9 @@ "label": "Limite contesto file area di lavoro", "description": "Numero massimo di file da includere nei dettagli della directory di lavoro corrente. Valori più alti forniscono più contesto ma aumentano l'utilizzo di token." }, - "rooignore": { - "label": "Mostra file .rooignore negli elenchi e nelle ricerche", - "description": "Quando abilitato, i file che corrispondono ai pattern in .rooignore verranno mostrati negli elenchi con un simbolo di blocco. Quando disabilitato, questi file saranno completamente nascosti dagli elenchi di file e dalle ricerche." + "pearai-agent-ignore": { + "label": "Mostra file .pearai-agent-ignore negli elenchi e nelle ricerche", + "description": "Quando abilitato, i file che corrispondono ai pattern in .pearai-agent-ignore verranno mostrati negli elenchi con un simbolo di blocco. Quando disabilitato, questi file saranno completamente nascosti dagli elenchi di file e dalle ricerche." }, "maxReadFile": { "label": "Soglia di auto-troncamento lettura file", diff --git a/webview-ui/src/i18n/locales/ja/prompts.json b/webview-ui/src/i18n/locales/ja/prompts.json index 16f30a2ebc5..48c2a030d02 100644 --- a/webview-ui/src/i18n/locales/ja/prompts.json +++ b/webview-ui/src/i18n/locales/ja/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "新しいモードを作成", "editModesConfig": "モード設定を編集", "editGlobalModes": "グローバルモードを編集", - "editProjectModes": "プロジェクトモードを編集 (.roomodes)", + "editProjectModes": "プロジェクトモードを編集 (.pearai-agent-ignore)", "createModeHelpText": "+ をクリックして新しいカスタムモードを作成するか、チャットで Roo に作成を依頼してください!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "モード固有のカスタム指示(オプション)", "resetToDefault": "デフォルトにリセット", "description": "{{modeName}}モードに特化した行動ガイドラインを追加します。", - "loadFromFile": "{{mode}}モード固有のカスタム指示は、ワークスペースの.roo/rules-{{slug}}/フォルダからも読み込めます(.roorules-{{slug}}と.clinerules-{{slug}}は非推奨であり、まもなく機能しなくなります)。" + "loadFromFile": "{{mode}}モード固有のカスタム指示は、ワークスペースの.pearai-agent/rules-{{slug}}/フォルダからも読み込めます(.roorules-{{slug}}と.clinerules-{{slug}}は非推奨であり、まもなく機能しなくなります)。" }, "globalCustomInstructions": { "title": "すべてのモードのカスタム指示", "description": "これらの指示はすべてのモードに適用されます。モード固有の指示で強化できる基本的な動作セットを提供します。\nRooにエディタの表示言語({{language}})とは異なる言語で考えたり話したりさせたい場合は、ここで指定できます。", - "loadFromFile": "指示はワークスペースの.roo/rules/フォルダからも読み込めます(.roorules と .clinerules は非推奨であり、まもなく機能しなくなります)。" + "loadFromFile": "指示はワークスペースの.pearai-agent/rules/フォルダからも読み込めます(.roorules と .clinerules は非推奨であり、まもなく機能しなくなります)。" }, "systemPrompt": { "preview": "システムプロンプトのプレビュー", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "詳細設定:システムプロンプトの上書き", - "description": "ワークスペースの.roo/system-prompt-{{slug}}にファイルを作成することで、このモードのシステムプロンプト(役割定義とカスタム指示以外)を完全に置き換えることができます。これは組み込みの安全対策と一貫性チェック(特にツールの使用に関して)をバイパスする非常に高度な機能なので、注意して使用してください!" + "description": "ワークスペースの.pearai-agent/system-prompt-{{slug}}にファイルを作成することで、このモードのシステムプロンプト(役割定義とカスタム指示以外)を完全に置き換えることができます。これは組み込みの安全対策と一貫性チェック(特にツールの使用に関して)をバイパスする非常に高度な機能なので、注意して使用してください!" }, "createModeDialog": { "title": "新しいモードを作成", @@ -122,7 +122,7 @@ "description": "すべてのワークスペースで利用可能" }, "project": { - "label": "プロジェクト固有 (.roomodes)", + "label": "プロジェクト固有 (.pearai-agent-ignore)", "description": "このワークスペースでのみ使用可能、グローバルよりも優先" } }, diff --git a/webview-ui/src/i18n/locales/ja/settings.json b/webview-ui/src/i18n/locales/ja/settings.json index 25b77e1eecb..e28c0f65a93 100644 --- a/webview-ui/src/i18n/locales/ja/settings.json +++ b/webview-ui/src/i18n/locales/ja/settings.json @@ -298,7 +298,7 @@ "label": "ワークスペースファイルコンテキスト制限", "description": "現在の作業ディレクトリの詳細に含めるファイルの最大数。高い値はより多くのコンテキストを提供しますが、token使用量が増加します。" }, - "rooignore": { + "pearai-agent-ignore": { "label": "リストと検索で.rooignoreファイルを表示", "description": "有効にすると、.rooignoreのパターンに一致するファイルがロックシンボル付きでリストに表示されます。無効にすると、これらのファイルはファイルリストや検索から完全に非表示になります。" }, diff --git a/webview-ui/src/i18n/locales/ko/prompts.json b/webview-ui/src/i18n/locales/ko/prompts.json index 5942105f055..3c20d6f7cdb 100644 --- a/webview-ui/src/i18n/locales/ko/prompts.json +++ b/webview-ui/src/i18n/locales/ko/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "새 모드 만들기", "editModesConfig": "모드 구성 편집", "editGlobalModes": "전역 모드 편집", - "editProjectModes": "프로젝트 모드 편집 (.roomodes)", + "editProjectModes": "프로젝트 모드 편집 (.pearai-agent-ignore)", "createModeHelpText": "새 커스텀 모드를 만들려면 + 버튼을 클릭하거나, 채팅에서 Roo에게 만들어달라고 요청하세요!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "모드별 사용자 지정 지침 (선택 사항)", "resetToDefault": "기본값으로 재설정", "description": "{{modeName}} 모드에 대한 특정 행동 지침을 추가하세요.", - "loadFromFile": "{{mode}} 모드에 대한 사용자 지정 지침은 작업 공간의 .roo/rules-{{slug}}/ 폴더에서도 로드할 수 있습니다(.roorules-{{slug}}와 .clinerules-{{slug}}는 더 이상 사용되지 않으며 곧 작동을 중단합니다)." + "loadFromFile": "{{mode}} 모드에 대한 사용자 지정 지침은 작업 공간의 .pearai-agent/rules-{{slug}}/ 폴더에서도 로드할 수 있습니다(.roorules-{{slug}}와 .clinerules-{{slug}}는 더 이상 사용되지 않으며 곧 작동을 중단합니다)." }, "globalCustomInstructions": { "title": "모든 모드에 대한 사용자 지정 지침", "description": "이 지침은 모든 모드에 적용됩니다. 아래의 모드별 지침으로 향상될 수 있는 기본 동작 세트를 제공합니다.\nRoo가 에디터 표시 언어({{language}})와 다른 언어로 생각하고 말하기를 원하시면, 여기에 지정할 수 있습니다.", - "loadFromFile": "지침은 작업 공간의 .roo/rules/ 폴더에서도 로드할 수 있습니다(.roorules와 .clinerules는 더 이상 사용되지 않으며 곧 작동을 중단합니다)." + "loadFromFile": "지침은 작업 공간의 .pearai-agent/rules/ 폴더에서도 로드할 수 있습니다(.roorules와 .clinerules는 더 이상 사용되지 않으며 곧 작동을 중단합니다)." }, "systemPrompt": { "preview": "시스템 프롬프트 미리보기", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "고급: 시스템 프롬프트 재정의", - "description": "작업 공간의 .roo/system-prompt-{{slug}}에 파일을 생성하여 이 모드의 시스템 프롬프트(역할 정의 및 사용자 지정 지침 제외)를 완전히 대체할 수 있습니다. 이는 내장된 안전 장치와 일관성 검사(특히 도구 사용 관련)를 우회하는 매우 고급 기능이므로 주의하세요!" + "description": "작업 공간의 .pearai-agent/system-prompt-{{slug}}에 파일을 생성하여 이 모드의 시스템 프롬프트(역할 정의 및 사용자 지정 지침 제외)를 완전히 대체할 수 있습니다. 이는 내장된 안전 장치와 일관성 검사(특히 도구 사용 관련)를 우회하는 매우 고급 기능이므로 주의하세요!" }, "createModeDialog": { "title": "새 모드 만들기", @@ -122,7 +122,7 @@ "description": "모든 작업 공간에서 사용 가능" }, "project": { - "label": "프로젝트별 (.roomodes)", + "label": "프로젝트별 (.pearai-agent-ignore)", "description": "이 작업 공간에서만 사용 가능, 전역보다 우선" } }, diff --git a/webview-ui/src/i18n/locales/ko/settings.json b/webview-ui/src/i18n/locales/ko/settings.json index 9c6e9df01b4..8f35891bb26 100644 --- a/webview-ui/src/i18n/locales/ko/settings.json +++ b/webview-ui/src/i18n/locales/ko/settings.json @@ -298,8 +298,8 @@ "label": "작업 공간 파일 컨텍스트 제한", "description": "현재 작업 디렉토리 세부 정보에 포함할 파일의 최대 수. 높은 값은 더 많은 컨텍스트를 제공하지만 token 사용량이 증가합니다." }, - "rooignore": { - "label": "목록 및 검색에서 .rooignore 파일 표시", + "pearai-agent-ignore": { + "label": "목록 및 검색에서 .pearai-agent-ignore 파일 표시", "description": "활성화되면 .rooignore의 패턴과 일치하는 파일이 잠금 기호와 함께 목록에 표시됩니다. 비활성화되면 이러한 파일은 파일 목록 및 검색에서 완전히 숨겨집니다." }, "maxReadFile": { diff --git a/webview-ui/src/i18n/locales/pl/prompts.json b/webview-ui/src/i18n/locales/pl/prompts.json index ef8a5ffe083..2782e91a4f9 100644 --- a/webview-ui/src/i18n/locales/pl/prompts.json +++ b/webview-ui/src/i18n/locales/pl/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Utwórz nowy tryb", "editModesConfig": "Edytuj konfigurację trybów", "editGlobalModes": "Edytuj tryby globalne", - "editProjectModes": "Edytuj tryby projektu (.roomodes)", + "editProjectModes": "Edytuj tryby projektu (.pearai-agent-ignore)", "createModeHelpText": "Kliknij +, aby utworzyć nowy niestandardowy tryb, lub po prostu poproś Roo w czacie, aby utworzył go dla Ciebie!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Niestandardowe instrukcje dla trybu (opcjonalne)", "resetToDefault": "Przywróć domyślne", "description": "Dodaj wytyczne dotyczące zachowania specyficzne dla trybu {{modeName}}.", - "loadFromFile": "Niestandardowe instrukcje dla trybu {{modeName}} mogą być również ładowane z folderu .roo/rules-{{modeSlug}}/ w Twoim obszarze roboczym (.roorules-{{modeSlug}} i .clinerules-{{modeSlug}} są przestarzałe i wkrótce przestaną działać)." + "loadFromFile": "Niestandardowe instrukcje dla trybu {{modeName}} mogą być również ładowane z folderu .pearai-agent/rules-{{modeSlug}}/ w Twoim obszarze roboczym (.roorules-{{modeSlug}} i .clinerules-{{modeSlug}} są przestarzałe i wkrótce przestaną działać)." }, "globalCustomInstructions": { "title": "Niestandardowe instrukcje dla wszystkich trybów", "description": "Te instrukcje dotyczą wszystkich trybów. Zapewniają podstawowy zestaw zachowań, które mogą być rozszerzone przez instrukcje specyficzne dla trybów poniżej.\nJeśli chcesz, aby Roo myślał i mówił w języku innym niż język wyświetlania Twojego edytora ({{language}}), możesz to określić tutaj.", - "loadFromFile": "Instrukcje mogą być również ładowane z folderu .roo/rules/ w Twoim obszarze roboczym (.roorules i .clinerules są przestarzałe i wkrótce przestaną działać)." + "loadFromFile": "Instrukcje mogą być również ładowane z folderu .pearai-agent/rules/ w Twoim obszarze roboczym (.roorules i .clinerules są przestarzałe i wkrótce przestaną działać)." }, "systemPrompt": { "preview": "Podgląd podpowiedzi systemowej", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Zaawansowane: Zastąp podpowiedź systemową", - "description": "Możesz całkowicie zastąpić podpowiedź systemową dla tego trybu (oprócz definicji roli i niestandardowych instrukcji) poprzez utworzenie pliku w .roo/system-prompt-{{modeSlug}} w swoim obszarze roboczym. Jest to bardzo zaawansowana funkcja, która omija wbudowane zabezpieczenia i kontrole spójności (szczególnie wokół używania narzędzi), więc bądź ostrożny!" + "description": "Możesz całkowicie zastąpić podpowiedź systemową dla tego trybu (oprócz definicji roli i niestandardowych instrukcji) poprzez utworzenie pliku w .pearai-agent/system-prompt-{{modeSlug}} w swoim obszarze roboczym. Jest to bardzo zaawansowana funkcja, która omija wbudowane zabezpieczenia i kontrole spójności (szczególnie wokół używania narzędzi), więc bądź ostrożny!" }, "createModeDialog": { "title": "Utwórz nowy tryb", @@ -122,7 +122,7 @@ "description": "Dostępny we wszystkich obszarach roboczych" }, "project": { - "label": "Specyficzny dla projektu (.roomodes)", + "label": "Specyficzny dla projektu (.pearai-agent-ignore)", "description": "Dostępny tylko w tym obszarze roboczym, ma pierwszeństwo przed globalnym" } }, diff --git a/webview-ui/src/i18n/locales/pl/settings.json b/webview-ui/src/i18n/locales/pl/settings.json index b54ea4f8970..8cc780dd7ca 100644 --- a/webview-ui/src/i18n/locales/pl/settings.json +++ b/webview-ui/src/i18n/locales/pl/settings.json @@ -298,9 +298,9 @@ "label": "Limit kontekstu plików obszaru roboczego", "description": "Maksymalna liczba plików do uwzględnienia w szczegółach bieżącego katalogu roboczego. Wyższe wartości zapewniają więcej kontekstu, ale zwiększają zużycie token." }, - "rooignore": { - "label": "Pokaż pliki .rooignore na listach i w wyszukiwaniach", - "description": "Gdy włączone, pliki pasujące do wzorców w .rooignore będą pokazywane na listach z symbolem kłódki. Gdy wyłączone, te pliki będą całkowicie ukryte z list plików i wyszukiwań." + "pearai-agent-ignore": { + "label": "Pokaż pliki .pearai-agent-ignore na listach i w wyszukiwaniach", + "description": "Gdy włączone, pliki pasujące do wzorców w .pearai-agent-ignore będą pokazywane na listach z symbolem kłódki. Gdy wyłączone, te pliki będą całkowicie ukryte z list plików i wyszukiwań." }, "maxReadFile": { "label": "Próg automatycznego skracania odczytu pliku", diff --git a/webview-ui/src/i18n/locales/pt-BR/prompts.json b/webview-ui/src/i18n/locales/pt-BR/prompts.json index f255b91a27d..b18b0fa0a70 100644 --- a/webview-ui/src/i18n/locales/pt-BR/prompts.json +++ b/webview-ui/src/i18n/locales/pt-BR/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Criar novo modo", "editModesConfig": "Editar configuração de modos", "editGlobalModes": "Editar modos globais", - "editProjectModes": "Editar modos do projeto (.roomodes)", + "editProjectModes": "Editar modos do projeto (.pearai-agent-ignore)", "createModeHelpText": "Clique em + para criar um novo modo personalizado, ou simplesmente peça ao Roo no chat para criar um para você!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Instruções personalizadas específicas do modo (opcional)", "resetToDefault": "Restaurar para padrão", "description": "Adicione diretrizes comportamentais específicas para o modo {{modeName}}.", - "loadFromFile": "Instruções personalizadas específicas para o modo {{modeName}} também podem ser carregadas da pasta .roo/rules-{{modeSlug}}/ no seu espaço de trabalho (.roorules-{{modeSlug}} e .clinerules-{{modeSlug}} estão obsoletos e deixarão de funcionar em breve)." + "loadFromFile": "Instruções personalizadas específicas para o modo {{modeName}} também podem ser carregadas da pasta .pearai-agent/rules-{{modeSlug}}/ no seu espaço de trabalho (.roorules-{{modeSlug}} e .clinerules-{{modeSlug}} estão obsoletos e deixarão de funcionar em breve)." }, "globalCustomInstructions": { "title": "Instruções personalizadas para todos os modos", "description": "Estas instruções se aplicam a todos os modos. Elas fornecem um conjunto base de comportamentos que podem ser aprimorados por instruções específicas do modo abaixo.\nSe você desejar que o Roo pense e fale em um idioma diferente do idioma de exibição do seu editor ({{language}}), você pode especificá-lo aqui.", - "loadFromFile": "As instruções também podem ser carregadas da pasta .roo/rules/ no seu espaço de trabalho (.roorules e .clinerules estão obsoletos e deixarão de funcionar em breve)." + "loadFromFile": "As instruções também podem ser carregadas da pasta .pearai-agent/rules/ no seu espaço de trabalho (.roorules e .clinerules estão obsoletos e deixarão de funcionar em breve)." }, "systemPrompt": { "preview": "Visualizar prompt do sistema", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Avançado: Substituir prompt do sistema", - "description": "Você pode substituir completamente o prompt do sistema para este modo (além da definição de função e instruções personalizadas) criando um arquivo em .roo/system-prompt-{{modeSlug}} no seu espaço de trabalho. Esta é uma funcionalidade muito avançada que contorna as salvaguardas integradas e verificações de consistência (especialmente em torno do uso de ferramentas), então tenha cuidado!" + "description": "Você pode substituir completamente o prompt do sistema para este modo (além da definição de função e instruções personalizadas) criando um arquivo em .pearai-agent/system-prompt-{{modeSlug}} no seu espaço de trabalho. Esta é uma funcionalidade muito avançada que contorna as salvaguardas integradas e verificações de consistência (especialmente em torno do uso de ferramentas), então tenha cuidado!" }, "createModeDialog": { "title": "Criar novo modo", @@ -122,7 +122,7 @@ "description": "Disponível em todos os espaços de trabalho" }, "project": { - "label": "Específico do projeto (.roomodes)", + "label": "Específico do projeto (.pearai-agent-ignore)", "description": "Disponível apenas neste espaço de trabalho, tem precedência sobre o global" } }, diff --git a/webview-ui/src/i18n/locales/pt-BR/settings.json b/webview-ui/src/i18n/locales/pt-BR/settings.json index 25a7d932f18..b6e0e6e491d 100644 --- a/webview-ui/src/i18n/locales/pt-BR/settings.json +++ b/webview-ui/src/i18n/locales/pt-BR/settings.json @@ -298,9 +298,9 @@ "label": "Limite de contexto de arquivos do espaço de trabalho", "description": "Número máximo de arquivos a incluir nos detalhes do diretório de trabalho atual. Valores mais altos fornecem mais contexto, mas aumentam o uso de token." }, - "rooignore": { - "label": "Mostrar arquivos .rooignore em listas e pesquisas", - "description": "Quando ativado, os arquivos que correspondem aos padrões em .rooignore serão mostrados em listas com um símbolo de cadeado. Quando desativado, esses arquivos serão completamente ocultos das listas de arquivos e pesquisas." + "pearai-agent-ignore": { + "label": "Mostrar arquivos .pearai-agent-ignore em listas e pesquisas", + "description": "Quando ativado, os arquivos que correspondem aos padrões em .pearai-agent-ignore serão mostrados em listas com um símbolo de cadeado. Quando desativado, esses arquivos serão completamente ocultos das listas de arquivos e pesquisas." }, "maxReadFile": { "label": "Limite de auto-truncamento de leitura de arquivo", diff --git a/webview-ui/src/i18n/locales/ru/prompts.json b/webview-ui/src/i18n/locales/ru/prompts.json index 0ff448bedbd..86058aca833 100644 --- a/webview-ui/src/i18n/locales/ru/prompts.json +++ b/webview-ui/src/i18n/locales/ru/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Создать новый режим", "editModesConfig": "Редактировать конфигурацию режимов", "editGlobalModes": "Редактировать глобальные режимы", - "editProjectModes": "Редактировать режимы проекта (.roomodes)", + "editProjectModes": "Редактировать режимы проекта (.pearai-agent-ignore)", "createModeHelpText": "Нажмите +, чтобы создать новый пользовательский режим, или просто попросите Roo в чате создать его для вас!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Пользовательские инструкции для режима (необязательно)", "resetToDefault": "Сбросить по умолчанию", "description": "Добавьте рекомендации по поведению, специфичные для режима {{modeName}}.", - "loadFromFile": "Пользовательские инструкции для режима {{mode}} также можно загрузить из папки .roo/rules-{{slug}}/ в вашем рабочем пространстве (.roorules-{{slug}} и .clinerules-{{slug}} устарели и скоро перестанут работать)." + "loadFromFile": "Пользовательские инструкции для режима {{mode}} также можно загрузить из папки .pearai-agent/rules-{{slug}}/ в вашем рабочем пространстве (.roorules-{{slug}} и .clinerules-{{slug}} устарели и скоро перестанут работать)." }, "globalCustomInstructions": { "title": "Пользовательские инструкции для всех режимов", "description": "Эти инструкции применяются ко всем режимам. Они задают базовое поведение, которое можно расширить с помощью инструкций ниже.\nЕсли вы хотите, чтобы Roo думал и говорил на другом языке, отличном от языка редактора ({{language}}), укажите это здесь.", - "loadFromFile": "Инструкции также можно загрузить из папки .roo/rules/ в вашем рабочем пространстве (.roorules и .clinerules устарели и скоро перестанут работать)." + "loadFromFile": "Инструкции также можно загрузить из папки .pearai-agent/rules/ в вашем рабочем пространстве (.roorules и .clinerules устарели и скоро перестанут работать)." }, "systemPrompt": { "preview": "Предпросмотр системного промпта", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Дополнительно: переопределить системный промпт", - "description": "Вы можете полностью заменить системный промпт для этого режима (кроме определения роли и пользовательских инструкций), создав файл .roo/system-prompt-{{slug}} в вашем рабочем пространстве. Это продвинутая функция, которая обходит встроенные ограничения и проверки (особенно для инструментов), поэтому будьте осторожны!" + "description": "Вы можете полностью заменить системный промпт для этого режима (кроме определения роли и пользовательских инструкций), создав файл .pearai-agent/system-prompt-{{slug}} в вашем рабочем пространстве. Это продвинутая функция, которая обходит встроенные ограничения и проверки (особенно для инструментов), поэтому будьте осторожны!" }, "createModeDialog": { "title": "Создать новый режим", @@ -122,7 +122,7 @@ "description": "Доступно во всех рабочих пространствах" }, "project": { - "label": "Для проекта (.roomodes)", + "label": "Для проекта (.pearai-agent-ignore)", "description": "Доступно только в этом рабочем пространстве, имеет приоритет над глобальными" } }, diff --git a/webview-ui/src/i18n/locales/ru/settings.json b/webview-ui/src/i18n/locales/ru/settings.json index caab30c872a..6f39c47d154 100644 --- a/webview-ui/src/i18n/locales/ru/settings.json +++ b/webview-ui/src/i18n/locales/ru/settings.json @@ -298,9 +298,9 @@ "label": "Лимит контекста файлов рабочей области", "description": "Максимальное количество файлов, включаемых в детали текущей рабочей директории. Большее значение даёт больше контекста, но увеличивает расход токенов." }, - "rooignore": { - "label": "Показывать .rooignore-файлы в списках и поиске", - "description": "Если включено, файлы, совпадающие с шаблонами в .rooignore, будут отображаться в списках с символом замка. Если выключено, такие файлы полностью скрываются из списков и поиска." + "pearai-agent-ignore": { + "label": "Показывать .pearai-agent-ignore-файлы в списках и поиске", + "description": "Если включено, файлы, совпадающие с шаблонами в .pearai-agent-ignore, будут отображаться в списках с символом замка. Если выключено, такие файлы полностью скрываются из списков и поиска." }, "maxReadFile": { "label": "Порог автообрезки при чтении файла", diff --git a/webview-ui/src/i18n/locales/tr/prompts.json b/webview-ui/src/i18n/locales/tr/prompts.json index 8d7c7b9305a..1e505dc07de 100644 --- a/webview-ui/src/i18n/locales/tr/prompts.json +++ b/webview-ui/src/i18n/locales/tr/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Yeni mod oluştur", "editModesConfig": "Mod yapılandırmasını düzenle", "editGlobalModes": "Global modları düzenle", - "editProjectModes": "Proje modlarını düzenle (.roomodes)", + "editProjectModes": "Proje modlarını düzenle (.pearai-agent-ignore)", "createModeHelpText": "Yeni bir özel mod oluşturmak için + düğmesine tıklayın veya sohbette Roo'dan sizin için bir tane oluşturmasını isteyin!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Moda özgü özel talimatlar (isteğe bağlı)", "resetToDefault": "Varsayılana sıfırla", "description": "{{modeName}} modu için özel davranış yönergeleri ekleyin.", - "loadFromFile": "{{mode}} moduna özgü özel talimatlar ayrıca çalışma alanınızdaki .roo/rules-{{slug}}/ klasöründen yüklenebilir (.roorules-{{slug}} ve .clinerules-{{slug}} kullanımdan kaldırılmıştır ve yakında çalışmayı durduracaklardır)." + "loadFromFile": "{{mode}} moduna özgü özel talimatlar ayrıca çalışma alanınızdaki .pearai-agent/rules-{{slug}}/ klasöründen yüklenebilir (.roorules-{{slug}} ve .clinerules-{{slug}} kullanımdan kaldırılmıştır ve yakında çalışmayı durduracaklardır)." }, "globalCustomInstructions": { "title": "Tüm Modlar için Özel Talimatlar", "description": "Bu talimatlar tüm modlara uygulanır. Aşağıdaki moda özgü talimatlarla geliştirilebilen temel davranış seti sağlarlar.\nRoo'nun editörünüzün görüntüleme dilinden ({{language}}) farklı bir dilde düşünmesini ve konuşmasını istiyorsanız, burada belirtebilirsiniz.", - "loadFromFile": "Talimatlar ayrıca çalışma alanınızdaki .roo/rules/ klasöründen de yüklenebilir (.roorules ve .clinerules kullanımdan kaldırılmıştır ve yakında çalışmayı durduracaklardır)." + "loadFromFile": "Talimatlar ayrıca çalışma alanınızdaki .pearai-agent/rules/ klasöründen de yüklenebilir (.roorules ve .clinerules kullanımdan kaldırılmıştır ve yakında çalışmayı durduracaklardır)." }, "systemPrompt": { "preview": "Sistem promptunu önizle", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Gelişmiş: Sistem Promptunu Geçersiz Kıl", - "description": "Çalışma alanınızda .roo/system-prompt-{{slug}} adresinde bir dosya oluşturarak bu mod için sistem istemini tamamen değiştirebilirsiniz (rol tanımı ve özel talimatlar hariç). Bu, yerleşik güvenlik önlemlerini ve tutarlılık kontrollerini (özellikle araç kullanımıyla ilgili) aşan çok gelişmiş bir özelliktir, bu yüzden dikkatli olun!" + "description": "Çalışma alanınızda .pearai-agent/system-prompt-{{slug}} adresinde bir dosya oluşturarak bu mod için sistem istemini tamamen değiştirebilirsiniz (rol tanımı ve özel talimatlar hariç). Bu, yerleşik güvenlik önlemlerini ve tutarlılık kontrollerini (özellikle araç kullanımıyla ilgili) aşan çok gelişmiş bir özelliktir, bu yüzden dikkatli olun!" }, "createModeDialog": { "title": "Yeni Mod Oluştur", @@ -122,7 +122,7 @@ "description": "Tüm çalışma alanlarında kullanılabilir" }, "project": { - "label": "Projeye özgü (.roomodes)", + "label": "Projeye özgü (.pearai-agent-ignore)", "description": "Yalnızca bu çalışma alanında kullanılabilir, globale göre önceliklidir" } }, diff --git a/webview-ui/src/i18n/locales/tr/settings.json b/webview-ui/src/i18n/locales/tr/settings.json index 0e98d02cea3..9ed3f29db08 100644 --- a/webview-ui/src/i18n/locales/tr/settings.json +++ b/webview-ui/src/i18n/locales/tr/settings.json @@ -298,9 +298,9 @@ "label": "Çalışma alanı dosyaları bağlam sınırı", "description": "Mevcut çalışma dizini ayrıntılarına dahil edilecek maksimum dosya sayısı. Daha yüksek değerler daha fazla bağlam sağlar ancak token kullanımını artırır." }, - "rooignore": { - "label": "Listelerde ve aramalarda .rooignore dosyalarını göster", - "description": "Etkinleştirildiğinde, .rooignore'daki desenlerle eşleşen dosyalar kilit sembolü ile listelerde gösterilecektir. Devre dışı bırakıldığında, bu dosyalar dosya listelerinden ve aramalardan tamamen gizlenecektir." + "pearai-agent-ignore": { + "label": "Listelerde ve aramalarda .pearai-agent-ignore dosyalarını göster", + "description": "Etkinleştirildiğinde, .pearai-agent-ignore'daki desenlerle eşleşen dosyalar kilit sembolü ile listelerde gösterilecektir. Devre dışı bırakıldığında, bu dosyalar dosya listelerinden ve aramalardan tamamen gizlenecektir." }, "maxReadFile": { "label": "Dosya okuma otomatik kısaltma eşiği", diff --git a/webview-ui/src/i18n/locales/vi/prompts.json b/webview-ui/src/i18n/locales/vi/prompts.json index 4b62d3718e6..5583a8757e0 100644 --- a/webview-ui/src/i18n/locales/vi/prompts.json +++ b/webview-ui/src/i18n/locales/vi/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "Tạo chế độ mới", "editModesConfig": "Chỉnh sửa cấu hình chế độ", "editGlobalModes": "Chỉnh sửa chế độ toàn cục", - "editProjectModes": "Chỉnh sửa chế độ dự án (.roomodes)", + "editProjectModes": "Chỉnh sửa chế độ dự án (.pearai-agent-ignore)", "createModeHelpText": "Nhấn + để tạo chế độ tùy chỉnh mới, hoặc chỉ cần yêu cầu Roo trong chat tạo một chế độ cho bạn!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "Hướng dẫn tùy chỉnh dành riêng cho chế độ (tùy chọn)", "resetToDefault": "Đặt lại về mặc định", "description": "Thêm hướng dẫn hành vi dành riêng cho chế độ {{modeName}}.", - "loadFromFile": "Hướng dẫn tùy chỉnh dành riêng cho chế độ {{modeName}} cũng có thể được tải từ thư mục .roo/rules-{{modeSlug}}/ trong không gian làm việc của bạn (.roorules-{{modeSlug}} và .clinerules-{{modeSlug}} đã lỗi thời và sẽ sớm ngừng hoạt động)." + "loadFromFile": "Hướng dẫn tùy chỉnh dành riêng cho chế độ {{modeName}} cũng có thể được tải từ thư mục .pearai-agent/rules-{{modeSlug}}/ trong không gian làm việc của bạn (.roorules-{{modeSlug}} và .clinerules-{{modeSlug}} đã lỗi thời và sẽ sớm ngừng hoạt động)." }, "globalCustomInstructions": { "title": "Hướng dẫn tùy chỉnh cho tất cả các chế độ", "description": "Những hướng dẫn này áp dụng cho tất cả các chế độ. Chúng cung cấp một bộ hành vi cơ bản có thể được nâng cao bởi hướng dẫn dành riêng cho chế độ bên dưới.\nNếu bạn muốn Roo suy nghĩ và nói bằng ngôn ngữ khác với ngôn ngữ hiển thị trình soạn thảo của bạn ({{language}}), bạn có thể chỉ định ở đây.", - "loadFromFile": "Hướng dẫn cũng có thể được tải từ thư mục .roo/rules/ trong không gian làm việc của bạn (.roorules và .clinerules đã lỗi thời và sẽ sớm ngừng hoạt động)." + "loadFromFile": "Hướng dẫn cũng có thể được tải từ thư mục .pearai-agent/rules/ trong không gian làm việc của bạn (.roorules và .clinerules đã lỗi thời và sẽ sớm ngừng hoạt động)." }, "systemPrompt": { "preview": "Xem trước lời nhắc hệ thống", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "Nâng cao: Ghi đè lời nhắc hệ thống", - "description": "Bạn có thể hoàn toàn thay thế lời nhắc hệ thống cho chế độ này (ngoài định nghĩa vai trò và hướng dẫn tùy chỉnh) bằng cách tạo một tệp tại .roo/system-prompt-{{modeSlug}} trong không gian làm việc của bạn. Đây là một tính năng rất nâng cao bỏ qua các biện pháp bảo vệ và kiểm tra nhất quán tích hợp sẵn (đặc biệt là xung quanh việc sử dụng công cụ), vì vậy hãy cẩn thận!" + "description": "Bạn có thể hoàn toàn thay thế lời nhắc hệ thống cho chế độ này (ngoài định nghĩa vai trò và hướng dẫn tùy chỉnh) bằng cách tạo một tệp tại .pearai-agent/system-prompt-{{modeSlug}} trong không gian làm việc của bạn. Đây là một tính năng rất nâng cao bỏ qua các biện pháp bảo vệ và kiểm tra nhất quán tích hợp sẵn (đặc biệt là xung quanh việc sử dụng công cụ), vì vậy hãy cẩn thận!" }, "createModeDialog": { "title": "Tạo chế độ mới", @@ -122,7 +122,7 @@ "description": "Có sẵn trong tất cả các không gian làm việc" }, "project": { - "label": "Dành riêng cho dự án (.roomodes)", + "label": "Dành riêng cho dự án (.pearai-agent-ignore)", "description": "Chỉ có sẵn trong không gian làm việc này, được ưu tiên hơn toàn cục" } }, diff --git a/webview-ui/src/i18n/locales/vi/settings.json b/webview-ui/src/i18n/locales/vi/settings.json index 28af4b9ea11..e536476f6c7 100644 --- a/webview-ui/src/i18n/locales/vi/settings.json +++ b/webview-ui/src/i18n/locales/vi/settings.json @@ -298,9 +298,9 @@ "label": "Giới hạn ngữ cảnh tệp workspace", "description": "Số lượng tệp tối đa để đưa vào chi tiết thư mục làm việc hiện tại. Giá trị cao hơn cung cấp nhiều ngữ cảnh hơn nhưng tăng sử dụng token." }, - "rooignore": { - "label": "Hiển thị tệp .rooignore trong danh sách và tìm kiếm", - "description": "Khi được bật, các tệp khớp với mẫu trong .rooignore sẽ được hiển thị trong danh sách với biểu tượng khóa. Khi bị tắt, các tệp này sẽ hoàn toàn bị ẩn khỏi danh sách tệp và tìm kiếm." + "pearai-agent-ignore": { + "label": "Hiển thị tệp .pearai-agent-ignore trong danh sách và tìm kiếm", + "description": "Khi được bật, các tệp khớp với mẫu trong .pearai-agent-ignore sẽ được hiển thị trong danh sách với biểu tượng khóa. Khi bị tắt, các tệp này sẽ hoàn toàn bị ẩn khỏi danh sách tệp và tìm kiếm." }, "maxReadFile": { "label": "Ngưỡng tự động cắt ngắn khi đọc tệp", diff --git a/webview-ui/src/i18n/locales/zh-CN/prompts.json b/webview-ui/src/i18n/locales/zh-CN/prompts.json index 2980bd66997..9c8dbb504d0 100644 --- a/webview-ui/src/i18n/locales/zh-CN/prompts.json +++ b/webview-ui/src/i18n/locales/zh-CN/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "新建模式", "editModesConfig": "模式设置", "editGlobalModes": "修改全局模式", - "editProjectModes": "编辑项目模式 (.roomodes)", + "editProjectModes": "编辑项目模式 (.pearai-agent-ignore)", "createModeHelpText": "点击 + 创建模式,或在对话时让Roo创建一个新模式。" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "模式专属规则(可选)", "resetToDefault": "重置为默认值", "description": "{{modeName}}模式的专属规则", - "loadFromFile": "支持从.roo/rules-{{slug}}/目录读取配置(.roorules-{{slug}}和.clinerules-{{slug}}已弃用并将很快停止工作)。" + "loadFromFile": "支持从.pearai-agent/rules-{{slug}}/目录读取配置(.roorules-{{slug}}和.clinerules-{{slug}}已弃用并将很快停止工作)。" }, "globalCustomInstructions": { "title": "所有模式的自定义指令", "description": "所有模式通用规则\n当前语言:{{language}}", - "loadFromFile": "支持从.roo/rules/目录读取全局配置(.roorules和.clinerules已弃用并将很快停止工作)。" + "loadFromFile": "支持从.pearai-agent/rules/目录读取全局配置(.roorules和.clinerules已弃用并将很快停止工作)。" }, "systemPrompt": { "preview": "预览系统提示词", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "高级:覆盖系统提示词", - "description": "您可以通过在工作区创建文件 .roo/system-prompt-{{slug}},完全替换此模式的系统提示(角色定义和自定义指令除外)。这是一个非常高级的功能,会绕过内置的安全措施和一致性检查(尤其是与工具使用相关的部分),请谨慎操作!" + "description": "您可以通过在工作区创建文件 .pearai-agent/system-prompt-{{slug}},完全替换此模式的系统提示(角色定义和自定义指令除外)。这是一个非常高级的功能,会绕过内置的安全措施和一致性检查(尤其是与工具使用相关的部分),请谨慎操作!" }, "createModeDialog": { "title": "创建新模式", @@ -122,7 +122,7 @@ "description": "全局可用" }, "project": { - "label": "项目特定 (.roomodes)", + "label": "项目特定 (.pearai-agent-ignore)", "description": "仅当前项目有效" } }, diff --git a/webview-ui/src/i18n/locales/zh-CN/settings.json b/webview-ui/src/i18n/locales/zh-CN/settings.json index 2d684f34366..e0482f7b335 100644 --- a/webview-ui/src/i18n/locales/zh-CN/settings.json +++ b/webview-ui/src/i18n/locales/zh-CN/settings.json @@ -298,9 +298,9 @@ "label": "工作区文件限制", "description": "允许纳入上下文的最大文件数(值越大消耗token越多)" }, - "rooignore": { - "label": "在列表和搜索中显示 .rooignore 文件", - "description": "启用后,与 .rooignore 中模式匹配的文件将在列表中显示锁定符号。禁用时,这些文件将从文件列表和搜索中完全隐藏。" + "pearai-agent-ignore": { + "label": "在列表和搜索中显示 .pearai-agent-ignore 文件", + "description": "启用后,与 .pearai-agent-ignore 中模式匹配的文件将在列表中显示锁定符号。禁用时,这些文件将从文件列表和搜索中完全隐藏。" }, "maxReadFile": { "label": "文件读取自动截断阈值", diff --git a/webview-ui/src/i18n/locales/zh-TW/prompts.json b/webview-ui/src/i18n/locales/zh-TW/prompts.json index 9b99707cf67..876175b83fd 100644 --- a/webview-ui/src/i18n/locales/zh-TW/prompts.json +++ b/webview-ui/src/i18n/locales/zh-TW/prompts.json @@ -6,7 +6,7 @@ "createNewMode": "建立新模式", "editModesConfig": "編輯模式設定", "editGlobalModes": "編輯全域模式", - "editProjectModes": "編輯專案模式 (.roomodes)", + "editProjectModes": "編輯專案模式 (.pearai-agent-ignore)", "createModeHelpText": "點選 + 建立新的自訂模式,或者在聊天中直接請 Roo 為您建立!" }, "apiConfiguration": { @@ -37,12 +37,12 @@ "title": "模式專屬自訂指令(選用)", "resetToDefault": "重設為預設值", "description": "為 {{modeName}} 模式新增專屬的行為指南。", - "loadFromFile": "{{mode}} 模式的自訂指令也可以從工作區的 .roo/rules-{{slug}}/ 資料夾載入(.roorules-{{slug}} 和 .clinerules-{{slug}} 已棄用並將很快停止運作)。" + "loadFromFile": "{{mode}} 模式的自訂指令也可以從工作區的 .pearai-agent/rules-{{slug}}/ 資料夾載入(.roorules-{{slug}} 和 .clinerules-{{slug}} 已棄用並將很快停止運作)。" }, "globalCustomInstructions": { "title": "所有模式的自訂指令", "description": "這些指令適用於所有模式。它們提供了一組基本行為,可以透過下方的模式專屬自訂指令來強化。\n如果您希望 Roo 使用與編輯器顯示語言 ({{language}}) 不同的語言來思考和對話,您可以在這裡指定。", - "loadFromFile": "指令也可以從工作區的 .roo/rules/ 資料夾載入(.roorules 和 .clinerules 已棄用並將很快停止運作)。" + "loadFromFile": "指令也可以從工作區的 .pearai-agent/rules/ 資料夾載入(.roorules 和 .clinerules 已棄用並將很快停止運作)。" }, "systemPrompt": { "preview": "預覽系統提示詞", @@ -101,7 +101,7 @@ }, "advancedSystemPrompt": { "title": "進階:覆寫系統提示詞", - "description": "您可以透過在工作區建立檔案 .roo/system-prompt-{{slug}} 來完全替換此模式的系統提示詞(角色定義和自訂指令除外)。這是一個非常進階的功能,會繞過內建的安全措施和一致性檢查(尤其是與工具使用相關的檢查),請謹慎使用!" + "description": "您可以透過在工作區建立檔案 .pearai-agent/system-prompt-{{slug}} 來完全替換此模式的系統提示詞(角色定義和自訂指令除外)。這是一個非常進階的功能,會繞過內建的安全措施和一致性檢查(尤其是與工具使用相關的檢查),請謹慎使用!" }, "createModeDialog": { "title": "建立新模式", @@ -122,7 +122,7 @@ "description": "在所有工作區可用" }, "project": { - "label": "專案特定 (.roomodes)", + "label": "專案特定 (.pearai-agent-ignore)", "description": "僅在此工作區可用,優先於全域模式" } }, diff --git a/webview-ui/src/i18n/locales/zh-TW/settings.json b/webview-ui/src/i18n/locales/zh-TW/settings.json index 32b9f709769..cce91229045 100644 --- a/webview-ui/src/i18n/locales/zh-TW/settings.json +++ b/webview-ui/src/i18n/locales/zh-TW/settings.json @@ -298,9 +298,9 @@ "label": "工作區檔案的上下文限制", "description": "目前工作目錄中最多包含多少個檔案。數值越高提供的上下文越多,但 token 用量也會增加。" }, - "rooignore": { - "label": "在列表和搜尋中顯示被 .rooignore 排除的檔案", - "description": "啟用後,符合 .rooignore 規則的檔案會在列表中顯示並標示鎖定圖示。停用後,這些檔案將完全從檔案列表和搜尋結果中隱藏。" + "pearai-agent-ignore": { + "label": "在列表和搜尋中顯示被 .pearai-agent-ignore 排除的檔案", + "description": "啟用後,符合 .pearai-agent-ignore 規則的檔案會在列表中顯示並標示鎖定圖示。停用後,這些檔案將完全從檔案列表和搜尋結果中隱藏。" }, "maxReadFile": { "label": "檔案讀取自動截斷閾值", From 1898b2c3c7c39adb82f77502850d4c73c959e799 Mon Sep 17 00:00:00 2001 From: Himanshu Date: Mon, 12 May 2025 23:15:36 +0530 Subject: [PATCH 66/80] rename roo rules (#80) * rename .roo -> .pearai-agent * pearai-agent-ignore * pearai-agent-modes --- src/exports/types.ts | 684 +++++++++++++++++++++++++------------------ 1 file changed, 404 insertions(+), 280 deletions(-) diff --git a/src/exports/types.ts b/src/exports/types.ts index c449b349e86..e964fdbe46c 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -2,175 +2,215 @@ // Do not edit it directly. type ProviderSettings = { - apiProvider?: ("anthropic" | "glama" | "openrouter" | "bedrock" | "vertex" | "openai" | "ollama" | "vscode-lm" | "lmstudio" | "gemini" | "openai-native" | "mistral" | "deepseek" | "unbound" | "requesty" | "human-relay" | "fake-ai" | "pearai" | "xai") | undefined; - apiModelId?: string | undefined; - apiKey?: string | undefined; - anthropicBaseUrl?: string | undefined; - anthropicUseAuthToken?: boolean | undefined; - glamaModelId?: string | undefined; - glamaApiKey?: string | undefined; - openRouterApiKey?: string | undefined; - openRouterModelId?: string | undefined; - openRouterBaseUrl?: string | undefined; - openRouterSpecificProvider?: string | undefined; - openRouterUseMiddleOutTransform?: boolean | undefined; - awsAccessKey?: string | undefined; - awsSecretKey?: string | undefined; - awsSessionToken?: string | undefined; - awsRegion?: string | undefined; - awsUseCrossRegionInference?: boolean | undefined; - awsUsePromptCache?: boolean | undefined; - awspromptCacheId?: string | undefined; - awsProfile?: string | undefined; - awsUseProfile?: boolean | undefined; - awsCustomArn?: string | undefined; - vertexKeyFile?: string | undefined; - vertexJsonCredentials?: string | undefined; - vertexProjectId?: string | undefined; - vertexRegion?: string | undefined; - openAiBaseUrl?: string | undefined; - openAiApiKey?: string | undefined; - openAiLegacyFormat?: boolean | undefined; - openAiR1FormatEnabled?: boolean | undefined; - openAiModelId?: string | undefined; - openAiCustomModelInfo?: ({ - maxTokens?: (number | null) | undefined; - maxThinkingTokens?: (number | null) | undefined; - contextWindow: number; - supportsImages?: boolean | undefined; - supportsComputerUse?: boolean | undefined; - supportsPromptCache: boolean; - isPromptCacheOptional?: boolean | undefined; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - description?: string | undefined; - reasoningEffort?: ("low" | "medium" | "high") | undefined; - thinking?: boolean | undefined; - minTokensPerCachePoint?: number | undefined; - maxCachePoints?: number | undefined; - cachableFields?: string[] | undefined; - underlyingModel?: string | undefined; - tiers?: { - contextWindow: number; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - }[] | undefined; - } | null) | undefined; - openAiUseAzure?: boolean | undefined; - azureApiVersion?: string | undefined; - openAiStreamingEnabled?: boolean | undefined; - enableReasoningEffort?: boolean | undefined; - openAiHostHeader?: string | undefined; - openAiHeaders?: { - [x: string]: string; - } | undefined; - ollamaModelId?: string | undefined; - ollamaBaseUrl?: string | undefined; - vsCodeLmModelSelector?: { - vendor?: string | undefined; - family?: string | undefined; - version?: string | undefined; - id?: string | undefined; - } | undefined; - lmStudioModelId?: string | undefined; - lmStudioBaseUrl?: string | undefined; - lmStudioDraftModelId?: string | undefined; - lmStudioSpeculativeDecodingEnabled?: boolean | undefined; - geminiApiKey?: string | undefined; - googleGeminiBaseUrl?: string | undefined; - openAiNativeApiKey?: string | undefined; - openAiNativeBaseUrl?: string | undefined; - mistralApiKey?: string | undefined; - mistralCodestralUrl?: string | undefined; - deepSeekBaseUrl?: string | undefined; - deepSeekApiKey?: string | undefined; - unboundApiKey?: string | undefined; - unboundModelId?: string | undefined; - requestyApiKey?: string | undefined; - requestyModelId?: string | undefined; - xaiApiKey?: string | undefined; - modelMaxTokens?: number | undefined; - modelMaxThinkingTokens?: number | undefined; - includeMaxTokens?: boolean | undefined; - reasoningEffort?: ("low" | "medium" | "high") | undefined; - promptCachingEnabled?: boolean | undefined; - diffEnabled?: boolean | undefined; - fuzzyMatchThreshold?: number | undefined; - modelTemperature?: (number | null) | undefined; - rateLimitSeconds?: number | undefined; - fakeAi?: unknown | undefined; - pearaiBaseUrl?: string | undefined; - pearaiModelId?: string | undefined; - pearaiApiKey?: string | undefined; - pearaiModelInfo?: ({ - maxTokens?: (number | null) | undefined; - maxThinkingTokens?: (number | null) | undefined; - contextWindow: number; - supportsImages?: boolean | undefined; - supportsComputerUse?: boolean | undefined; - supportsPromptCache: boolean; - isPromptCacheOptional?: boolean | undefined; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - description?: string | undefined; - reasoningEffort?: ("low" | "medium" | "high") | undefined; - thinking?: boolean | undefined; - minTokensPerCachePoint?: number | undefined; - maxCachePoints?: number | undefined; - cachableFields?: string[] | undefined; - underlyingModel?: string | undefined; - tiers?: { - contextWindow: number; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - }[] | undefined; - } | null) | undefined; - pearaiAgentModels?: { - models: { - [x: string]: { - maxTokens?: (number | null) | undefined; - maxThinkingTokens?: (number | null) | undefined; - contextWindow: number; - supportsImages?: boolean | undefined; - supportsComputerUse?: boolean | undefined; - supportsPromptCache: boolean; - isPromptCacheOptional?: boolean | undefined; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - description?: string | undefined; - reasoningEffort?: ("low" | "medium" | "high") | undefined; - thinking?: boolean | undefined; - minTokensPerCachePoint?: number | undefined; - maxCachePoints?: number | undefined; - cachableFields?: string[] | undefined; - underlyingModel?: string | undefined; - tiers?: { - contextWindow: number; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - }[] | undefined; - }; - }; - defaultModelId?: string | undefined; - } | undefined; - creatorModeConfig?: { - creatorMode?: boolean | undefined; - newProjectType?: string | undefined; - newProjectPath?: string | undefined; - } | undefined; -}; + apiProvider?: + | ( + | "anthropic" + | "glama" + | "openrouter" + | "bedrock" + | "vertex" + | "openai" + | "ollama" + | "vscode-lm" + | "lmstudio" + | "gemini" + | "openai-native" + | "mistral" + | "deepseek" + | "unbound" + | "requesty" + | "human-relay" + | "fake-ai" + | "pearai" + | "xai" + ) + | undefined + apiModelId?: string | undefined + apiKey?: string | undefined + anthropicBaseUrl?: string | undefined + anthropicUseAuthToken?: boolean | undefined + glamaModelId?: string | undefined + glamaApiKey?: string | undefined + openRouterApiKey?: string | undefined + openRouterModelId?: string | undefined + openRouterBaseUrl?: string | undefined + openRouterSpecificProvider?: string | undefined + openRouterUseMiddleOutTransform?: boolean | undefined + awsAccessKey?: string | undefined + awsSecretKey?: string | undefined + awsSessionToken?: string | undefined + awsRegion?: string | undefined + awsUseCrossRegionInference?: boolean | undefined + awsUsePromptCache?: boolean | undefined + awspromptCacheId?: string | undefined + awsProfile?: string | undefined + awsUseProfile?: boolean | undefined + awsCustomArn?: string | undefined + vertexKeyFile?: string | undefined + vertexJsonCredentials?: string | undefined + vertexProjectId?: string | undefined + vertexRegion?: string | undefined + openAiBaseUrl?: string | undefined + openAiApiKey?: string | undefined + openAiLegacyFormat?: boolean | undefined + openAiR1FormatEnabled?: boolean | undefined + openAiModelId?: string | undefined + openAiCustomModelInfo?: + | ({ + maxTokens?: (number | null) | undefined + maxThinkingTokens?: (number | null) | undefined + contextWindow: number + supportsImages?: boolean | undefined + supportsComputerUse?: boolean | undefined + supportsPromptCache: boolean + isPromptCacheOptional?: boolean | undefined + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + description?: string | undefined + reasoningEffort?: ("low" | "medium" | "high") | undefined + thinking?: boolean | undefined + minTokensPerCachePoint?: number | undefined + maxCachePoints?: number | undefined + cachableFields?: string[] | undefined + underlyingModel?: string | undefined + tiers?: + | { + contextWindow: number + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + }[] + | undefined + } | null) + | undefined + openAiUseAzure?: boolean | undefined + azureApiVersion?: string | undefined + openAiStreamingEnabled?: boolean | undefined + enableReasoningEffort?: boolean | undefined + openAiHostHeader?: string | undefined + openAiHeaders?: + | { + [x: string]: string + } + | undefined + ollamaModelId?: string | undefined + ollamaBaseUrl?: string | undefined + vsCodeLmModelSelector?: + | { + vendor?: string | undefined + family?: string | undefined + version?: string | undefined + id?: string | undefined + } + | undefined + lmStudioModelId?: string | undefined + lmStudioBaseUrl?: string | undefined + lmStudioDraftModelId?: string | undefined + lmStudioSpeculativeDecodingEnabled?: boolean | undefined + geminiApiKey?: string | undefined + googleGeminiBaseUrl?: string | undefined + openAiNativeApiKey?: string | undefined + openAiNativeBaseUrl?: string | undefined + mistralApiKey?: string | undefined + mistralCodestralUrl?: string | undefined + deepSeekBaseUrl?: string | undefined + deepSeekApiKey?: string | undefined + unboundApiKey?: string | undefined + unboundModelId?: string | undefined + requestyApiKey?: string | undefined + requestyModelId?: string | undefined + xaiApiKey?: string | undefined + modelMaxTokens?: number | undefined + modelMaxThinkingTokens?: number | undefined + includeMaxTokens?: boolean | undefined + reasoningEffort?: ("low" | "medium" | "high") | undefined + promptCachingEnabled?: boolean | undefined + diffEnabled?: boolean | undefined + fuzzyMatchThreshold?: number | undefined + modelTemperature?: (number | null) | undefined + rateLimitSeconds?: number | undefined + fakeAi?: unknown | undefined + pearaiBaseUrl?: string | undefined + pearaiModelId?: string | undefined + pearaiApiKey?: string | undefined + pearaiModelInfo?: + | ({ + maxTokens?: (number | null) | undefined + maxThinkingTokens?: (number | null) | undefined + contextWindow: number + supportsImages?: boolean | undefined + supportsComputerUse?: boolean | undefined + supportsPromptCache: boolean + isPromptCacheOptional?: boolean | undefined + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + description?: string | undefined + reasoningEffort?: ("low" | "medium" | "high") | undefined + thinking?: boolean | undefined + minTokensPerCachePoint?: number | undefined + maxCachePoints?: number | undefined + cachableFields?: string[] | undefined + underlyingModel?: string | undefined + tiers?: + | { + contextWindow: number + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + }[] + | undefined + } | null) + | undefined + pearaiAgentModels?: + | { + models: { + [x: string]: { + maxTokens?: (number | null) | undefined + maxThinkingTokens?: (number | null) | undefined + contextWindow: number + supportsImages?: boolean | undefined + supportsComputerUse?: boolean | undefined + supportsPromptCache: boolean + isPromptCacheOptional?: boolean | undefined + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + description?: string | undefined + reasoningEffort?: ("low" | "medium" | "high") | undefined + thinking?: boolean | undefined + minTokensPerCachePoint?: number | undefined + maxCachePoints?: number | undefined + cachableFields?: string[] | undefined + underlyingModel?: string | undefined + tiers?: + | { + contextWindow: number + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + }[] + | undefined + } + } + defaultModelId?: string | undefined + } + | undefined + creatorModeConfig?: + | { + creatorMode?: boolean | undefined + newProjectType?: string | undefined + newProjectPath?: string | undefined + } + | undefined +} export type { ProviderSettings } @@ -352,123 +392,207 @@ type GlobalSettings = { export type { GlobalSettings } type ClineMessage = { - ts: number; - type: "ask" | "say"; - ask?: ("followup" | "command" | "command_output" | "completion_result" | "tool" | "api_req_failed" | "resume_task" | "resume_completed_task" | "mistake_limit_reached" | "browser_action_launch" | "use_mcp_server") | undefined; - say?: ("error" | "api_req_started" | "api_req_finished" | "api_req_retried" | "api_req_retry_delayed" | "api_req_deleted" | "text" | "reasoning" | "completion_result" | "user_feedback" | "user_feedback_diff" | "command_output" | "shell_integration_warning" | "browser_action" | "browser_action_result" | "mcp_server_request_started" | "mcp_server_response" | "subtask_result" | "checkpoint_saved" | "rooignore_error" | "diff_error") | undefined; - text?: string | undefined; - images?: string[] | undefined; - partial?: boolean | undefined; - reasoning?: string | undefined; - conversationHistoryIndex?: number | undefined; - checkpoint?: { - [x: string]: unknown; - } | undefined; - progressStatus?: { - id?: string | undefined; - icon?: string | undefined; - text?: string | undefined; - } | undefined; -}; + ts: number + type: "ask" | "say" + ask?: + | ( + | "followup" + | "command" + | "command_output" + | "completion_result" + | "tool" + | "api_req_failed" + | "resume_task" + | "resume_completed_task" + | "mistake_limit_reached" + | "browser_action_launch" + | "use_mcp_server" + ) + | undefined + say?: + | ( + | "error" + | "api_req_started" + | "api_req_finished" + | "api_req_retried" + | "api_req_retry_delayed" + | "api_req_deleted" + | "text" + | "reasoning" + | "completion_result" + | "user_feedback" + | "user_feedback_diff" + | "command_output" + | "shell_integration_warning" + | "browser_action" + | "browser_action_result" + | "mcp_server_request_started" + | "mcp_server_response" + | "subtask_result" + | "checkpoint_saved" + | "rooignore_error" + | "diff_error" + ) + | undefined + text?: string | undefined + images?: string[] | undefined + partial?: boolean | undefined + reasoning?: string | undefined + conversationHistoryIndex?: number | undefined + checkpoint?: + | { + [x: string]: unknown + } + | undefined + progressStatus?: + | { + id?: string | undefined + icon?: string | undefined + text?: string | undefined + } + | undefined +} export type { ClineMessage } type TokenUsage = { - totalTokensIn: number; - totalTokensOut: number; - totalCacheWrites?: number | undefined; - totalCacheReads?: number | undefined; - totalCost: number; - contextTokens: number; -}; + totalTokensIn: number + totalTokensOut: number + totalCacheWrites?: number | undefined + totalCacheReads?: number | undefined + totalCost: number + contextTokens: number +} export type { TokenUsage } type RooCodeEvents = { - message: [ - { - taskId: string; - action: "created" | "updated"; - message: { - ts: number; - type: "ask" | "say"; - ask?: ("followup" | "command" | "command_output" | "completion_result" | "tool" | "api_req_failed" | "resume_task" | "resume_completed_task" | "mistake_limit_reached" | "browser_action_launch" | "use_mcp_server") | undefined; - say?: ("error" | "api_req_started" | "api_req_finished" | "api_req_retried" | "api_req_retry_delayed" | "api_req_deleted" | "text" | "reasoning" | "completion_result" | "user_feedback" | "user_feedback_diff" | "command_output" | "shell_integration_warning" | "browser_action" | "browser_action_result" | "mcp_server_request_started" | "mcp_server_response" | "subtask_result" | "checkpoint_saved" | "rooignore_error" | "diff_error") | undefined; - text?: string | undefined; - images?: string[] | undefined; - partial?: boolean | undefined; - reasoning?: string | undefined; - conversationHistoryIndex?: number | undefined; - checkpoint?: { - [x: string]: unknown; - } | undefined; - progressStatus?: { - id?: string | undefined; - icon?: string | undefined; - text?: string | undefined; - } | undefined; - }; - } - ]; - taskCreated: [ - string - ]; - taskStarted: [ - string - ]; - taskModeSwitched: [ - string, - string - ]; - taskPaused: [ - string - ]; - taskUnpaused: [ - string - ]; - taskAskResponded: [ - string - ]; - taskAborted: [ - string - ]; - taskSpawned: [ - string, - string - ]; - taskCompleted: [ - string, - { - totalTokensIn: number; - totalTokensOut: number; - totalCacheWrites?: number | undefined; - totalCacheReads?: number | undefined; - totalCost: number; - contextTokens: number; - }, - { - [x: string]: { - attempts: number; - failures: number; - }; - } - ]; - taskTokenUsageUpdated: [ - string, - { - totalTokensIn: number; - totalTokensOut: number; - totalCacheWrites?: number | undefined; - totalCacheReads?: number | undefined; - totalCost: number; - contextTokens: number; - } - ]; - taskToolFailed: [ - string, - "execute_command" | "read_file" | "write_to_file" | "apply_diff" | "insert_content" | "search_and_replace" | "search_files" | "list_files" | "list_code_definition_names" | "browser_action" | "use_mcp_tool" | "access_mcp_resource" | "ask_followup_question" | "attempt_completion" | "switch_mode" | "new_task" | "fetch_instructions", - string - ]; -}; + message: [ + { + taskId: string + action: "created" | "updated" + message: { + ts: number + type: "ask" | "say" + ask?: + | ( + | "followup" + | "command" + | "command_output" + | "completion_result" + | "tool" + | "api_req_failed" + | "resume_task" + | "resume_completed_task" + | "mistake_limit_reached" + | "browser_action_launch" + | "use_mcp_server" + ) + | undefined + say?: + | ( + | "error" + | "api_req_started" + | "api_req_finished" + | "api_req_retried" + | "api_req_retry_delayed" + | "api_req_deleted" + | "text" + | "reasoning" + | "completion_result" + | "user_feedback" + | "user_feedback_diff" + | "command_output" + | "shell_integration_warning" + | "browser_action" + | "browser_action_result" + | "mcp_server_request_started" + | "mcp_server_response" + | "subtask_result" + | "checkpoint_saved" + | "rooignore_error" + | "diff_error" + ) + | undefined + text?: string | undefined + images?: string[] | undefined + partial?: boolean | undefined + reasoning?: string | undefined + conversationHistoryIndex?: number | undefined + checkpoint?: + | { + [x: string]: unknown + } + | undefined + progressStatus?: + | { + id?: string | undefined + icon?: string | undefined + text?: string | undefined + } + | undefined + } + }, + ] + taskCreated: [string] + taskStarted: [string] + taskModeSwitched: [string, string] + taskPaused: [string] + taskUnpaused: [string] + taskAskResponded: [string] + taskAborted: [string] + taskSpawned: [string, string] + taskCompleted: [ + string, + { + totalTokensIn: number + totalTokensOut: number + totalCacheWrites?: number | undefined + totalCacheReads?: number | undefined + totalCost: number + contextTokens: number + }, + { + [x: string]: { + attempts: number + failures: number + } + }, + ] + taskTokenUsageUpdated: [ + string, + { + totalTokensIn: number + totalTokensOut: number + totalCacheWrites?: number | undefined + totalCacheReads?: number | undefined + totalCost: number + contextTokens: number + }, + ] + taskToolFailed: [ + string, + ( + | "execute_command" + | "read_file" + | "write_to_file" + | "apply_diff" + | "insert_content" + | "search_and_replace" + | "search_files" + | "list_files" + | "list_code_definition_names" + | "browser_action" + | "use_mcp_tool" + | "access_mcp_resource" + | "ask_followup_question" + | "attempt_completion" + | "switch_mode" + | "new_task" + | "fetch_instructions" + ), + string, + ] +} -export type { RooCodeEvents } \ No newline at end of file +export type { RooCodeEvents } From 20c294b602ba8c6ac3bfafa15e76733b33ddf00e Mon Sep 17 00:00:00 2001 From: James Arnott Date: Mon, 12 May 2025 19:06:42 +0100 Subject: [PATCH 67/80] fix: new task --- src/core/Cline.ts | 11 +++++++---- src/core/tools/newTaskTool.ts | 9 +++++++-- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/core/Cline.ts b/src/core/Cline.ts index 153306cf4df..3020f16c0fe 100644 --- a/src/core/Cline.ts +++ b/src/core/Cline.ts @@ -245,8 +245,13 @@ export class Cline extends EventEmitter { console.error("Failed to initialize RooIgnoreController:", error) }) - this.apiConfiguration = apiConfiguration - this.api = buildApiHandler(apiConfiguration) + this.creatorModeConfig = creatorModeConfig ?? historyItem?.creatorModeConfig ?? { creatorMode: false } + + this.apiConfiguration = { + ...apiConfiguration, + creatorModeConfig: this.creatorModeConfig + } + this.api = buildApiHandler(this.apiConfiguration) this.promptCacheKey = crypto.randomUUID() this.urlContentFetcher = new UrlContentFetcher(provider.context) @@ -260,8 +265,6 @@ export class Cline extends EventEmitter { this.diffViewProvider = new DiffViewProvider(this.cwd) this.enableCheckpoints = enableCheckpoints - this.creatorModeConfig = creatorModeConfig ?? historyItem?.creatorModeConfig ?? { creatorMode: false } - this.rootTask = rootTask this.parentTask = parentTask this.taskNumber = taskNumber diff --git a/src/core/tools/newTaskTool.ts b/src/core/tools/newTaskTool.ts index f2e9e178e44..7b6030eee35 100644 --- a/src/core/tools/newTaskTool.ts +++ b/src/core/tools/newTaskTool.ts @@ -78,8 +78,13 @@ export async function newTaskTool( // Delay to allow mode change to take effect before next tool is executed. await delay(500) - // Pass the creator mode config from the parent task to ensure creator mode is preserved - const newCline = await provider.initClineWithTask(message, undefined, cline, {}, cline.creatorModeConfig) + const newCline = await provider.initClineWithTask( + message, + undefined, + cline, + {}, + cline.creatorModeConfig + ) cline.emit("taskSpawned", newCline.taskId) pushToolResult(`Successfully created new task in ${targetMode.name} mode with message: ${message}`) From cd2e60ad5c8f6c7edb23d4ee0985b50a5ede1efe Mon Sep 17 00:00:00 2001 From: nang-dev Date: Mon, 12 May 2025 16:19:23 -0400 Subject: [PATCH 68/80] Use prod link --- src/shared/pearaiApi.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/shared/pearaiApi.ts b/src/shared/pearaiApi.ts index c0a5e4d3656..0d110218aa3 100644 --- a/src/shared/pearaiApi.ts +++ b/src/shared/pearaiApi.ts @@ -1,8 +1,8 @@ // CHANGE AS NEEDED FOR DEVELOPMENT // PROD: -// export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" +export const PEARAI_URL = "https://server.trypear.ai/pearai-server-api2/integrations/cline" // DEV: -export const PEARAI_URL = "http://localhost:8000/integrations/cline" +// export const PEARAI_URL = "http://localhost:8000/integrations/cline" import { anthropicModels, From f34eaf3f35af399945421e098f0f449daabfa26c Mon Sep 17 00:00:00 2001 From: James Arnott Date: Mon, 12 May 2025 22:35:13 +0100 Subject: [PATCH 69/80] fix: only switch modes to webapp when we are making a webapp --- src/activate/registerPearListener.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index 230134429c9..f40be03b73c 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -52,7 +52,7 @@ export const registerPearListener = async (provider: ClineProvider) => { await new Promise((resolve) => setTimeout(resolve, 3000)) // * This does actually work but the UI update does not happen. This method calls this.postStateToWebview() so not sure what is going on - James - if(msg.newProjectType !== "NONE") { + if(msg.newProjectType === "WEBAPP") { // Only switch to the creator manager if we're creating a new project // TODO: later when we need to make a different type of project, we need to change this await provider.handleModeSwitch(PEARAI_CREATOR_MODE_WEBAPP_MANAGER_SLUG); From d33a6db32c3ba47b76ecd94b19837a14d8447b4c Mon Sep 17 00:00:00 2001 From: nang-dev Date: Tue, 13 May 2025 01:01:30 -0400 Subject: [PATCH 70/80] Switch to pearai-creator-mode --- src/core/webview/ClineProvider.ts | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 9b0a947f9a1..5b5c4643a67 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -24,7 +24,7 @@ import { supportPrompt } from "../../shared/support-prompt" import { GlobalFileNames } from "../../shared/globalFileNames" import { HistoryItem } from "../../shared/HistoryItem" import { ExtensionMessage } from "../../shared/ExtensionMessage" -import { Mode, PromptComponent, defaultModeSlug } from "../../shared/modes" +import { Mode, PEARAI_CREATOR_MODE_WEBAPP_MANAGER_SLUG, PromptComponent, defaultModeSlug } from "../../shared/modes" import { experimentDefault } from "../../shared/experiments" import { formatLanguage } from "../../shared/language" import { Terminal } from "../../integrations/terminal/Terminal" @@ -825,7 +825,16 @@ export class ClineProvider extends EventEmitter implements const config = listApiConfig?.find((c) => c.id === savedConfigId) if (config?.name) { - const apiConfig = await this.providerSettingsManager.loadConfig(config.name) + let apiConfig = await this.providerSettingsManager.loadConfig(config.name) + + // Switch to pearai-model-creator model if we are in Creator Mode + if (newMode == PEARAI_CREATOR_MODE_WEBAPP_MANAGER_SLUG) { + apiConfig = { + ...apiConfig, + apiProvider: "pearai", + apiModelId: "pearai-model-creator", + } + } await Promise.all([ this.updateGlobalState("currentApiConfigName", config.name), @@ -858,7 +867,7 @@ export class ClineProvider extends EventEmitter implements ...providerSettings, creatorModeConfig: currentCline?.creatorModeConfig, } - + if (mode) { const currentApiConfigName = this.getGlobalState("currentApiConfigName") From af7ad2bea188c2094d824d6510b615356bc0bca6 Mon Sep 17 00:00:00 2001 From: nang-dev Date: Tue, 13 May 2025 01:05:11 -0400 Subject: [PATCH 71/80] Switch away from pearai-model-creator --- src/core/webview/ClineProvider.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 5b5c4643a67..f58f2a539f3 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -834,6 +834,14 @@ export class ClineProvider extends EventEmitter implements apiProvider: "pearai", apiModelId: "pearai-model-creator", } + } else { + if (apiConfig.apiModelId == "pearai-model-creator") { + apiConfig = { + ...apiConfig, + apiProvider: "pearai", + apiModelId: "pearai-model", + } + } } await Promise.all([ From c9f086df87d4b60efb54948be726437c6da329d5 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Tue, 13 May 2025 12:18:17 +0100 Subject: [PATCH 72/80] feat: include creator params in cline provider --- src/core/webview/ClineProvider.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index f58f2a539f3..2df680d8bf6 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1272,7 +1272,7 @@ export class ClineProvider extends EventEmitter implements ...baseApiConfiguration } - const telemetryKey = process.env.POSTHOG_API_KEY + const telemetryKey = 'phc_RRjQ4roADRjH6xMbXDUDTA9WLeM5ePPvAJK19w3yj0z' const machineId = vscode.env.machineId const allowedCommands = vscode.workspace.getConfiguration("roo-cline").get("allowedCommands") || [] const cwd = this.cwd @@ -1556,6 +1556,7 @@ export class ClineProvider extends EventEmitter implements const properties: Record = { vscodeVersion, platform, + isCreatorView: this.isCreatorView, } // Add extension version From 380940db8a3c0aeb2c1477103495a137034bb94e Mon Sep 17 00:00:00 2001 From: James Arnott Date: Tue, 13 May 2025 13:18:08 +0100 Subject: [PATCH 73/80] fix: creator analytics --- src/core/webview/ClineProvider.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 2df680d8bf6..28fa9ec56fc 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1556,7 +1556,6 @@ export class ClineProvider extends EventEmitter implements const properties: Record = { vscodeVersion, platform, - isCreatorView: this.isCreatorView, } // Add extension version @@ -1594,6 +1593,11 @@ export class ClineProvider extends EventEmitter implements properties.diffStrategy = currentCline.diffStrategy.getName() } + // Add creator mode context if available + if (currentCline?.creatorModeConfig?.creatorMode) { + properties.isCreatorMode = true + } + return properties } } From 4b4718e876819d13a324cdbcc4141645f2109a3d Mon Sep 17 00:00:00 2001 From: James Arnott Date: Tue, 13 May 2025 15:32:48 +0100 Subject: [PATCH 74/80] =?UTF-8?q?chore:=20enabling=20telemetry=20by=20defa?= =?UTF-8?q?ult,=20hardcoding=20api=20key=20=F0=9F=98=AD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/services/telemetry/PostHogClient.ts | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/src/services/telemetry/PostHogClient.ts b/src/services/telemetry/PostHogClient.ts index 784c9476e8b..ec62f31b04d 100644 --- a/src/services/telemetry/PostHogClient.ts +++ b/src/services/telemetry/PostHogClient.ts @@ -40,11 +40,12 @@ export class PostHogClient { private static instance: PostHogClient private client: PostHog private distinctId: string = vscode.env.machineId - private telemetryEnabled: boolean = false + private telemetryEnabled: boolean = true private providerRef: WeakRef | null = null private constructor() { - this.client = new PostHog(process.env.POSTHOG_API_KEY || "", { host: "https://us.i.posthog.com" }) + // TODO: HARDCODED POSTHOG API KEY IS NOT GREAT - SHOULD FIX SOME TIME + this.client = new PostHog('phc_RRjQ4roADRjH6xMbXDUDTA9WLeM5ePPvAJK19w3yj0z', { host: "https://us.i.posthog.com" }) } /** @@ -53,16 +54,16 @@ export class PostHogClient { * @param didUserOptIn Whether the user has explicitly opted into telemetry */ public updateTelemetryState(didUserOptIn: boolean): void { - this.telemetryEnabled = false + this.telemetryEnabled = true // First check global telemetry level - telemetry should only be enabled when level is "all" - const telemetryLevel = vscode.workspace.getConfiguration("telemetry").get("telemetryLevel", "all") - const globalTelemetryEnabled = telemetryLevel === "all" + // const telemetryLevel = vscode.workspace.getConfiguration("telemetry").get("telemetryLevel", "all") + // const globalTelemetryEnabled = telemetryLevel === "all" // We only enable telemetry if global vscode telemetry is enabled - if (globalTelemetryEnabled) { - this.telemetryEnabled = didUserOptIn - } + // if (globalTelemetryEnabled) { + // this.telemetryEnabled = didUserOptIn + // } // Update PostHog client state based on telemetry preference if (this.telemetryEnabled) { From 214c382e5eea57dd62ba7f73e4dd9f0c5b75b1d3 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Tue, 13 May 2025 16:37:05 +0100 Subject: [PATCH 75/80] fix: identifying via pearai id --- src/services/telemetry/PostHogClient.ts | 37 +++++++++++++++++++++---- 1 file changed, 31 insertions(+), 6 deletions(-) diff --git a/src/services/telemetry/PostHogClient.ts b/src/services/telemetry/PostHogClient.ts index ec62f31b04d..1e88dbfc840 100644 --- a/src/services/telemetry/PostHogClient.ts +++ b/src/services/telemetry/PostHogClient.ts @@ -2,6 +2,7 @@ import { PostHog } from "posthog-node" import * as vscode from "vscode" import { logger } from "../../utils/logging" +import { getpearAIExports } from "../../activate/registerPearListener" // This forward declaration is needed to avoid circular dependencies export interface ClineProviderInterface { @@ -38,14 +39,38 @@ export class PostHogClient { } private static instance: PostHogClient - private client: PostHog - private distinctId: string = vscode.env.machineId - private telemetryEnabled: boolean = true - private providerRef: WeakRef | null = null + private readonly client: PostHog + private readonly vscMachineId: string + private pearaiId: string + private telemetryEnabled: boolean + private providerRef: WeakRef | null private constructor() { - // TODO: HARDCODED POSTHOG API KEY IS NOT GREAT - SHOULD FIX SOME TIME + this.vscMachineId = vscode.env.machineId + this.pearaiId = this.vscMachineId // Initialize with machine ID as fallback + this.telemetryEnabled = true + this.providerRef = null this.client = new PostHog('phc_RRjQ4roADRjH6xMbXDUDTA9WLeM5ePPvAJK19w3yj0z', { host: "https://us.i.posthog.com" }) + + // getting the pearai id from the submodule + void this.initializePearAIId() + } + + private async initializePearAIId(): Promise { + try { + const exports = await getpearAIExports() + if (exports) { + this.pearaiId = await exports.pearAPI.getUserId() + this.client.identify({ + distinctId: this.pearaiId, + properties: { + vscMachineId: this.vscMachineId + } + }) + } + } catch (error) { + logger.debug("Failed to get PearAI exports, using machine ID as fallback") + } } /** @@ -125,7 +150,7 @@ export class PostHogClient { } this.client.capture({ - distinctId: this.distinctId, + distinctId: this.vscMachineId, event: event.event, properties: mergedProperties, }) From 90a601d6330017c842cc87b4283be5d23cd7b725 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Wed, 14 May 2025 13:50:57 +0100 Subject: [PATCH 76/80] fix: live indicator clipping --- webview-ui/src/components/chat/PlanningBar.tsx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/webview-ui/src/components/chat/PlanningBar.tsx b/webview-ui/src/components/chat/PlanningBar.tsx index 9df0ea31722..6cde678022f 100644 --- a/webview-ui/src/components/chat/PlanningBar.tsx +++ b/webview-ui/src/components/chat/PlanningBar.tsx @@ -23,10 +23,11 @@ export const PlanningBar: FC = ({ isStreaming, requestedPlan, className={`${isStreaming ? "rainbow-border-glow-visible" : ""} absolute inset-0 rainbow-border-glow blur -z-10 rounded-full `} /> -
-
+
+
+
Creating
{requestedPlan}
From d9de44245214efd7ba71eb0c0f5382f94bf29649 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Wed, 14 May 2025 14:36:59 +0100 Subject: [PATCH 77/80] fix: using posthog aliases --- src/services/telemetry/PostHogClient.ts | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/services/telemetry/PostHogClient.ts b/src/services/telemetry/PostHogClient.ts index 1e88dbfc840..31a7fb70bd7 100644 --- a/src/services/telemetry/PostHogClient.ts +++ b/src/services/telemetry/PostHogClient.ts @@ -62,10 +62,14 @@ export class PostHogClient { if (exports) { this.pearaiId = await exports.pearAPI.getUserId() this.client.identify({ - distinctId: this.pearaiId, + distinctId: this.vscMachineId, properties: { - vscMachineId: this.vscMachineId + pearAiId: this.pearaiId, } + }); + this.client.alias({ + distinctId: this.vscMachineId, + alias: this.pearaiId, }) } } catch (error) { From 6aee6699252b732dcf34255e8320426fb6d14b3b Mon Sep 17 00:00:00 2001 From: James Arnott Date: Wed, 14 May 2025 15:55:52 +0100 Subject: [PATCH 78/80] feat(BREAKING): importing types from pearai submodule --- package-lock.json | 93 ++++++++++++++++++++++++++++++++++++ package.json | 1 + webview-ui/package-lock.json | 93 ++++++++++++++++++++++++++++++++++++ webview-ui/package.json | 1 + 4 files changed, 188 insertions(+) diff --git a/package-lock.json b/package-lock.json index 5abe8b91a57..526bae528ac 100644 --- a/package-lock.json +++ b/package-lock.json @@ -15,6 +15,7 @@ "@google/genai": "^0.9.0", "@mistralai/mistralai": "^1.3.6", "@modelcontextprotocol/sdk": "^1.7.0", + "@pearai/core": "file:./../pearai-submodule/core", "@types/clone-deep": "^4.0.4", "@types/pdf-parse": "^1.1.4", "@types/tmp": "^0.2.6", @@ -112,6 +113,94 @@ "vscode": "^1.84.0" } }, + "../pearai-submodule/core": { + "name": "@continuedev/core", + "version": "1.0.13", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-bedrock-runtime": "^3.620.1", + "@aws-sdk/credential-providers": "^3.620.1", + "@continuedev/config-types": "^1.0.10", + "@continuedev/llm-info": "^1.0.1", + "@mozilla/readability": "^0.5.0", + "@octokit/rest": "^20.0.2", + "@supabase/supabase-js": "^2.45.1", + "@typescript-eslint/eslint-plugin": "^7.8.0", + "@typescript-eslint/parser": "^7.8.0", + "@xenova/transformers": "2.14.0", + "adf-to-md": "^1.1.0", + "async-mutex": "^0.5.0", + "axios": "^1.6.7", + "cheerio": "^1.0.0-rc.12", + "commander": "^12.0.0", + "comment-json": "^4.2.3", + "dbinfoz": "^0.1.4", + "dotenv": "^16.4.5", + "fastest-levenshtein": "^1.0.16", + "follow-redirects": "^1.15.5", + "handlebars": "^4.7.8", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "ignore": "^5.3.1", + "js-tiktoken": "^1.0.8", + "jsdom": "^24.0.0", + "jwt-decode": "^4.0.0", + "launchdarkly-node-client-sdk": "^3.2.0", + "llm-code-highlighter": "^0.0.14", + "mac-ca": "^3.1.0", + "node-fetch": "^3.3.2", + "node-html-markdown": "^1.3.0", + "ollama": "^0.4.6", + "onnxruntime-node": "1.14.0", + "openai": "^4.20.1", + "pg": "^8.11.3", + "posthog-node": "^3.6.3", + "quick-lru": "^7.0.0", + "replicate": "^0.26.0", + "request": "^2.88.2", + "socket.io-client": "^4.7.3", + "sqlite": "^5.1.1", + "sqlite3": "^5.1.7", + "system-ca": "^1.0.3", + "tree-sitter-wasms": "^0.1.11", + "uuid": "^9.0.1", + "vectordb": "^0.4.20", + "web-tree-sitter": "^0.21.0", + "win-ca": "^3.5.1", + "workerpool": "^9.1.3", + "yaml": "^2.4.2", + "zod": "^3.23.8" + }, + "devDependencies": { + "@babel/preset-env": "^7.24.7", + "@biomejs/biome": "1.6.4", + "@google/generative-ai": "^0.11.4", + "@types/follow-redirects": "^1.14.4", + "@types/jest": "^29.5.12", + "@types/jquery": "^3.5.29", + "@types/jsdom": "^21.1.6", + "@types/mozilla-readability": "^0.2.1", + "@types/mustache": "^4.2.5", + "@types/node-fetch": "^2.6.11", + "@types/pg": "^8.11.6", + "@types/request": "^2.48.12", + "@types/uuid": "^9.0.7", + "@types/win-ca": "^3.5.4", + "cross-env": "^7.0.3", + "esbuild": "^0.17.19", + "eslint": "^8", + "eslint-plugin-import": "^2.29.1", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "myers-diff": "^2.1.0", + "onnxruntime-common": "1.14.0", + "onnxruntime-web": "1.14.0", + "ts-jest": "^29.1.1" + }, + "engines": { + "node": ">=20.11.0" + } + }, "node_modules/@ampproject/remapping": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz", @@ -6811,6 +6900,10 @@ "dev": true, "license": "MIT" }, + "node_modules/@pearai/core": { + "resolved": "../pearai-submodule/core", + "link": true + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", diff --git a/package.json b/package.json index 1b372e92267..6b3db19a012 100644 --- a/package.json +++ b/package.json @@ -384,6 +384,7 @@ "@google/genai": "^0.9.0", "@mistralai/mistralai": "^1.3.6", "@modelcontextprotocol/sdk": "^1.7.0", + "@pearai/core": "file:./../pearai-submodule/core", "@types/clone-deep": "^4.0.4", "@types/pdf-parse": "^1.1.4", "@types/tmp": "^0.2.6", diff --git a/webview-ui/package-lock.json b/webview-ui/package-lock.json index c2b07ba65ef..d0d15af855c 100644 --- a/webview-ui/package-lock.json +++ b/webview-ui/package-lock.json @@ -10,6 +10,7 @@ "dependencies": { "@headlessui/react": "^2.2.0", "@heroicons/react": "^2.2.0", + "@pearai/core": "file:./../../pearai-submodule/core", "@radix-ui/react-alert-dialog": "^1.1.6", "@radix-ui/react-checkbox": "^1.1.5", "@radix-ui/react-collapsible": "^1.1.3", @@ -92,6 +93,94 @@ "vite": "6.0.11" } }, + "../../pearai-submodule/core": { + "name": "@continuedev/core", + "version": "1.0.13", + "license": "Apache-2.0", + "dependencies": { + "@aws-sdk/client-bedrock-runtime": "^3.620.1", + "@aws-sdk/credential-providers": "^3.620.1", + "@continuedev/config-types": "^1.0.10", + "@continuedev/llm-info": "^1.0.1", + "@mozilla/readability": "^0.5.0", + "@octokit/rest": "^20.0.2", + "@supabase/supabase-js": "^2.45.1", + "@typescript-eslint/eslint-plugin": "^7.8.0", + "@typescript-eslint/parser": "^7.8.0", + "@xenova/transformers": "2.14.0", + "adf-to-md": "^1.1.0", + "async-mutex": "^0.5.0", + "axios": "^1.6.7", + "cheerio": "^1.0.0-rc.12", + "commander": "^12.0.0", + "comment-json": "^4.2.3", + "dbinfoz": "^0.1.4", + "dotenv": "^16.4.5", + "fastest-levenshtein": "^1.0.16", + "follow-redirects": "^1.15.5", + "handlebars": "^4.7.8", + "http-proxy-agent": "^7.0.1", + "https-proxy-agent": "^7.0.3", + "ignore": "^5.3.1", + "js-tiktoken": "^1.0.8", + "jsdom": "^24.0.0", + "jwt-decode": "^4.0.0", + "launchdarkly-node-client-sdk": "^3.2.0", + "llm-code-highlighter": "^0.0.14", + "mac-ca": "^3.1.0", + "node-fetch": "^3.3.2", + "node-html-markdown": "^1.3.0", + "ollama": "^0.4.6", + "onnxruntime-node": "1.14.0", + "openai": "^4.20.1", + "pg": "^8.11.3", + "posthog-node": "^3.6.3", + "quick-lru": "^7.0.0", + "replicate": "^0.26.0", + "request": "^2.88.2", + "socket.io-client": "^4.7.3", + "sqlite": "^5.1.1", + "sqlite3": "^5.1.7", + "system-ca": "^1.0.3", + "tree-sitter-wasms": "^0.1.11", + "uuid": "^9.0.1", + "vectordb": "^0.4.20", + "web-tree-sitter": "^0.21.0", + "win-ca": "^3.5.1", + "workerpool": "^9.1.3", + "yaml": "^2.4.2", + "zod": "^3.23.8" + }, + "devDependencies": { + "@babel/preset-env": "^7.24.7", + "@biomejs/biome": "1.6.4", + "@google/generative-ai": "^0.11.4", + "@types/follow-redirects": "^1.14.4", + "@types/jest": "^29.5.12", + "@types/jquery": "^3.5.29", + "@types/jsdom": "^21.1.6", + "@types/mozilla-readability": "^0.2.1", + "@types/mustache": "^4.2.5", + "@types/node-fetch": "^2.6.11", + "@types/pg": "^8.11.6", + "@types/request": "^2.48.12", + "@types/uuid": "^9.0.7", + "@types/win-ca": "^3.5.4", + "cross-env": "^7.0.3", + "esbuild": "^0.17.19", + "eslint": "^8", + "eslint-plugin-import": "^2.29.1", + "jest": "^29.7.0", + "jest-environment-jsdom": "^29.7.0", + "myers-diff": "^2.1.0", + "onnxruntime-common": "1.14.0", + "onnxruntime-web": "1.14.0", + "ts-jest": "^29.1.1" + }, + "engines": { + "node": ">=20.11.0" + } + }, "node_modules/@adobe/css-tools": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.1.tgz", @@ -3807,6 +3896,10 @@ "node": ">= 8" } }, + "node_modules/@pearai/core": { + "resolved": "../../pearai-submodule/core", + "link": true + }, "node_modules/@pkgjs/parseargs": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", diff --git a/webview-ui/package.json b/webview-ui/package.json index 0a1a7bfaed6..69adac66f32 100644 --- a/webview-ui/package.json +++ b/webview-ui/package.json @@ -17,6 +17,7 @@ "clean": "rimraf build" }, "dependencies": { + "@pearai/core": "file:./../../pearai-submodule/core", "@headlessui/react": "^2.2.0", "@heroicons/react": "^2.2.0", "@radix-ui/react-alert-dialog": "^1.1.6", From 0b7a8dfc4b73cb6403907061b9a48fbbcaf0d997 Mon Sep 17 00:00:00 2001 From: James Arnott Date: Wed, 14 May 2025 16:24:24 +0100 Subject: [PATCH 79/80] feat: added type imports from roo code --- src/activate/registerPearListener.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/activate/registerPearListener.ts b/src/activate/registerPearListener.ts index f40be03b73c..053a984ecb7 100644 --- a/src/activate/registerPearListener.ts +++ b/src/activate/registerPearListener.ts @@ -2,6 +2,7 @@ import * as vscode from "vscode" import { ClineProvider } from "../core/webview/ClineProvider" import { assert } from "../utils/util" import { PEARAI_CREATOR_MODE_WEBAPP_MANAGER_SLUG } from "../shared/modes" +import { PearAIExtensionExports } from "@pearai/core" export const getPearaiExtension = async () => { const pearAiExtension = vscode.extensions.getExtension("pearai.pearai") @@ -16,7 +17,7 @@ export const getPearaiExtension = async () => { } // TODO: TYPES -export const getpearAIExports = async () => { +export const getpearAIExports = async (): Promise => { const pearAiExtension = await getPearaiExtension() assert(!!pearAiExtension.exports, "⚠️⚠️ Error, no PearAI Exports could be found :( ⚠️⚠️"); @@ -30,8 +31,7 @@ type CreatorModeState = "OVERLAY_CLOSED" | "OVERLAY_OPEN" | "OVERLAY_CLOSED_CREA export const registerPearListener = async (provider: ClineProvider) => { // Getting the pear ai extension instance const exports = await getpearAIExports() - - exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg: any) => { + exports.pearAPI.creatorMode.onDidRequestExecutePlan(async (msg) => { console.dir(`onDidRequestNewTask triggered with: ${JSON.stringify(msg)}`) let canContinue = false; From 0195cc2d06086a1c40f3f8c9e0e44e6ec8147dfe Mon Sep 17 00:00:00 2001 From: James Arnott Date: Wed, 14 May 2025 16:40:29 +0100 Subject: [PATCH 80/80] fix: types + posthog key --- src/core/webview/ClineProvider.ts | 2 +- src/exports/types.ts | 684 ++++++++++++++---------- src/services/telemetry/PostHogClient.ts | 7 +- 3 files changed, 409 insertions(+), 284 deletions(-) diff --git a/src/core/webview/ClineProvider.ts b/src/core/webview/ClineProvider.ts index 28fa9ec56fc..177cc58de5a 100644 --- a/src/core/webview/ClineProvider.ts +++ b/src/core/webview/ClineProvider.ts @@ -1272,7 +1272,7 @@ export class ClineProvider extends EventEmitter implements ...baseApiConfiguration } - const telemetryKey = 'phc_RRjQ4roADRjH6xMbXDUDTA9WLeM5ePPvAJK19w3yj0z' + const telemetryKey = 'phc_EixCfQZYA5It6ZjtZG2C8THsUQzPzXZsdCsvR8AYhfh' const machineId = vscode.env.machineId const allowedCommands = vscode.workspace.getConfiguration("roo-cline").get("allowedCommands") || [] const cwd = this.cwd diff --git a/src/exports/types.ts b/src/exports/types.ts index c449b349e86..e964fdbe46c 100644 --- a/src/exports/types.ts +++ b/src/exports/types.ts @@ -2,175 +2,215 @@ // Do not edit it directly. type ProviderSettings = { - apiProvider?: ("anthropic" | "glama" | "openrouter" | "bedrock" | "vertex" | "openai" | "ollama" | "vscode-lm" | "lmstudio" | "gemini" | "openai-native" | "mistral" | "deepseek" | "unbound" | "requesty" | "human-relay" | "fake-ai" | "pearai" | "xai") | undefined; - apiModelId?: string | undefined; - apiKey?: string | undefined; - anthropicBaseUrl?: string | undefined; - anthropicUseAuthToken?: boolean | undefined; - glamaModelId?: string | undefined; - glamaApiKey?: string | undefined; - openRouterApiKey?: string | undefined; - openRouterModelId?: string | undefined; - openRouterBaseUrl?: string | undefined; - openRouterSpecificProvider?: string | undefined; - openRouterUseMiddleOutTransform?: boolean | undefined; - awsAccessKey?: string | undefined; - awsSecretKey?: string | undefined; - awsSessionToken?: string | undefined; - awsRegion?: string | undefined; - awsUseCrossRegionInference?: boolean | undefined; - awsUsePromptCache?: boolean | undefined; - awspromptCacheId?: string | undefined; - awsProfile?: string | undefined; - awsUseProfile?: boolean | undefined; - awsCustomArn?: string | undefined; - vertexKeyFile?: string | undefined; - vertexJsonCredentials?: string | undefined; - vertexProjectId?: string | undefined; - vertexRegion?: string | undefined; - openAiBaseUrl?: string | undefined; - openAiApiKey?: string | undefined; - openAiLegacyFormat?: boolean | undefined; - openAiR1FormatEnabled?: boolean | undefined; - openAiModelId?: string | undefined; - openAiCustomModelInfo?: ({ - maxTokens?: (number | null) | undefined; - maxThinkingTokens?: (number | null) | undefined; - contextWindow: number; - supportsImages?: boolean | undefined; - supportsComputerUse?: boolean | undefined; - supportsPromptCache: boolean; - isPromptCacheOptional?: boolean | undefined; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - description?: string | undefined; - reasoningEffort?: ("low" | "medium" | "high") | undefined; - thinking?: boolean | undefined; - minTokensPerCachePoint?: number | undefined; - maxCachePoints?: number | undefined; - cachableFields?: string[] | undefined; - underlyingModel?: string | undefined; - tiers?: { - contextWindow: number; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - }[] | undefined; - } | null) | undefined; - openAiUseAzure?: boolean | undefined; - azureApiVersion?: string | undefined; - openAiStreamingEnabled?: boolean | undefined; - enableReasoningEffort?: boolean | undefined; - openAiHostHeader?: string | undefined; - openAiHeaders?: { - [x: string]: string; - } | undefined; - ollamaModelId?: string | undefined; - ollamaBaseUrl?: string | undefined; - vsCodeLmModelSelector?: { - vendor?: string | undefined; - family?: string | undefined; - version?: string | undefined; - id?: string | undefined; - } | undefined; - lmStudioModelId?: string | undefined; - lmStudioBaseUrl?: string | undefined; - lmStudioDraftModelId?: string | undefined; - lmStudioSpeculativeDecodingEnabled?: boolean | undefined; - geminiApiKey?: string | undefined; - googleGeminiBaseUrl?: string | undefined; - openAiNativeApiKey?: string | undefined; - openAiNativeBaseUrl?: string | undefined; - mistralApiKey?: string | undefined; - mistralCodestralUrl?: string | undefined; - deepSeekBaseUrl?: string | undefined; - deepSeekApiKey?: string | undefined; - unboundApiKey?: string | undefined; - unboundModelId?: string | undefined; - requestyApiKey?: string | undefined; - requestyModelId?: string | undefined; - xaiApiKey?: string | undefined; - modelMaxTokens?: number | undefined; - modelMaxThinkingTokens?: number | undefined; - includeMaxTokens?: boolean | undefined; - reasoningEffort?: ("low" | "medium" | "high") | undefined; - promptCachingEnabled?: boolean | undefined; - diffEnabled?: boolean | undefined; - fuzzyMatchThreshold?: number | undefined; - modelTemperature?: (number | null) | undefined; - rateLimitSeconds?: number | undefined; - fakeAi?: unknown | undefined; - pearaiBaseUrl?: string | undefined; - pearaiModelId?: string | undefined; - pearaiApiKey?: string | undefined; - pearaiModelInfo?: ({ - maxTokens?: (number | null) | undefined; - maxThinkingTokens?: (number | null) | undefined; - contextWindow: number; - supportsImages?: boolean | undefined; - supportsComputerUse?: boolean | undefined; - supportsPromptCache: boolean; - isPromptCacheOptional?: boolean | undefined; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - description?: string | undefined; - reasoningEffort?: ("low" | "medium" | "high") | undefined; - thinking?: boolean | undefined; - minTokensPerCachePoint?: number | undefined; - maxCachePoints?: number | undefined; - cachableFields?: string[] | undefined; - underlyingModel?: string | undefined; - tiers?: { - contextWindow: number; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - }[] | undefined; - } | null) | undefined; - pearaiAgentModels?: { - models: { - [x: string]: { - maxTokens?: (number | null) | undefined; - maxThinkingTokens?: (number | null) | undefined; - contextWindow: number; - supportsImages?: boolean | undefined; - supportsComputerUse?: boolean | undefined; - supportsPromptCache: boolean; - isPromptCacheOptional?: boolean | undefined; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - description?: string | undefined; - reasoningEffort?: ("low" | "medium" | "high") | undefined; - thinking?: boolean | undefined; - minTokensPerCachePoint?: number | undefined; - maxCachePoints?: number | undefined; - cachableFields?: string[] | undefined; - underlyingModel?: string | undefined; - tiers?: { - contextWindow: number; - inputPrice?: number | undefined; - outputPrice?: number | undefined; - cacheWritesPrice?: number | undefined; - cacheReadsPrice?: number | undefined; - }[] | undefined; - }; - }; - defaultModelId?: string | undefined; - } | undefined; - creatorModeConfig?: { - creatorMode?: boolean | undefined; - newProjectType?: string | undefined; - newProjectPath?: string | undefined; - } | undefined; -}; + apiProvider?: + | ( + | "anthropic" + | "glama" + | "openrouter" + | "bedrock" + | "vertex" + | "openai" + | "ollama" + | "vscode-lm" + | "lmstudio" + | "gemini" + | "openai-native" + | "mistral" + | "deepseek" + | "unbound" + | "requesty" + | "human-relay" + | "fake-ai" + | "pearai" + | "xai" + ) + | undefined + apiModelId?: string | undefined + apiKey?: string | undefined + anthropicBaseUrl?: string | undefined + anthropicUseAuthToken?: boolean | undefined + glamaModelId?: string | undefined + glamaApiKey?: string | undefined + openRouterApiKey?: string | undefined + openRouterModelId?: string | undefined + openRouterBaseUrl?: string | undefined + openRouterSpecificProvider?: string | undefined + openRouterUseMiddleOutTransform?: boolean | undefined + awsAccessKey?: string | undefined + awsSecretKey?: string | undefined + awsSessionToken?: string | undefined + awsRegion?: string | undefined + awsUseCrossRegionInference?: boolean | undefined + awsUsePromptCache?: boolean | undefined + awspromptCacheId?: string | undefined + awsProfile?: string | undefined + awsUseProfile?: boolean | undefined + awsCustomArn?: string | undefined + vertexKeyFile?: string | undefined + vertexJsonCredentials?: string | undefined + vertexProjectId?: string | undefined + vertexRegion?: string | undefined + openAiBaseUrl?: string | undefined + openAiApiKey?: string | undefined + openAiLegacyFormat?: boolean | undefined + openAiR1FormatEnabled?: boolean | undefined + openAiModelId?: string | undefined + openAiCustomModelInfo?: + | ({ + maxTokens?: (number | null) | undefined + maxThinkingTokens?: (number | null) | undefined + contextWindow: number + supportsImages?: boolean | undefined + supportsComputerUse?: boolean | undefined + supportsPromptCache: boolean + isPromptCacheOptional?: boolean | undefined + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + description?: string | undefined + reasoningEffort?: ("low" | "medium" | "high") | undefined + thinking?: boolean | undefined + minTokensPerCachePoint?: number | undefined + maxCachePoints?: number | undefined + cachableFields?: string[] | undefined + underlyingModel?: string | undefined + tiers?: + | { + contextWindow: number + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + }[] + | undefined + } | null) + | undefined + openAiUseAzure?: boolean | undefined + azureApiVersion?: string | undefined + openAiStreamingEnabled?: boolean | undefined + enableReasoningEffort?: boolean | undefined + openAiHostHeader?: string | undefined + openAiHeaders?: + | { + [x: string]: string + } + | undefined + ollamaModelId?: string | undefined + ollamaBaseUrl?: string | undefined + vsCodeLmModelSelector?: + | { + vendor?: string | undefined + family?: string | undefined + version?: string | undefined + id?: string | undefined + } + | undefined + lmStudioModelId?: string | undefined + lmStudioBaseUrl?: string | undefined + lmStudioDraftModelId?: string | undefined + lmStudioSpeculativeDecodingEnabled?: boolean | undefined + geminiApiKey?: string | undefined + googleGeminiBaseUrl?: string | undefined + openAiNativeApiKey?: string | undefined + openAiNativeBaseUrl?: string | undefined + mistralApiKey?: string | undefined + mistralCodestralUrl?: string | undefined + deepSeekBaseUrl?: string | undefined + deepSeekApiKey?: string | undefined + unboundApiKey?: string | undefined + unboundModelId?: string | undefined + requestyApiKey?: string | undefined + requestyModelId?: string | undefined + xaiApiKey?: string | undefined + modelMaxTokens?: number | undefined + modelMaxThinkingTokens?: number | undefined + includeMaxTokens?: boolean | undefined + reasoningEffort?: ("low" | "medium" | "high") | undefined + promptCachingEnabled?: boolean | undefined + diffEnabled?: boolean | undefined + fuzzyMatchThreshold?: number | undefined + modelTemperature?: (number | null) | undefined + rateLimitSeconds?: number | undefined + fakeAi?: unknown | undefined + pearaiBaseUrl?: string | undefined + pearaiModelId?: string | undefined + pearaiApiKey?: string | undefined + pearaiModelInfo?: + | ({ + maxTokens?: (number | null) | undefined + maxThinkingTokens?: (number | null) | undefined + contextWindow: number + supportsImages?: boolean | undefined + supportsComputerUse?: boolean | undefined + supportsPromptCache: boolean + isPromptCacheOptional?: boolean | undefined + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + description?: string | undefined + reasoningEffort?: ("low" | "medium" | "high") | undefined + thinking?: boolean | undefined + minTokensPerCachePoint?: number | undefined + maxCachePoints?: number | undefined + cachableFields?: string[] | undefined + underlyingModel?: string | undefined + tiers?: + | { + contextWindow: number + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + }[] + | undefined + } | null) + | undefined + pearaiAgentModels?: + | { + models: { + [x: string]: { + maxTokens?: (number | null) | undefined + maxThinkingTokens?: (number | null) | undefined + contextWindow: number + supportsImages?: boolean | undefined + supportsComputerUse?: boolean | undefined + supportsPromptCache: boolean + isPromptCacheOptional?: boolean | undefined + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + description?: string | undefined + reasoningEffort?: ("low" | "medium" | "high") | undefined + thinking?: boolean | undefined + minTokensPerCachePoint?: number | undefined + maxCachePoints?: number | undefined + cachableFields?: string[] | undefined + underlyingModel?: string | undefined + tiers?: + | { + contextWindow: number + inputPrice?: number | undefined + outputPrice?: number | undefined + cacheWritesPrice?: number | undefined + cacheReadsPrice?: number | undefined + }[] + | undefined + } + } + defaultModelId?: string | undefined + } + | undefined + creatorModeConfig?: + | { + creatorMode?: boolean | undefined + newProjectType?: string | undefined + newProjectPath?: string | undefined + } + | undefined +} export type { ProviderSettings } @@ -352,123 +392,207 @@ type GlobalSettings = { export type { GlobalSettings } type ClineMessage = { - ts: number; - type: "ask" | "say"; - ask?: ("followup" | "command" | "command_output" | "completion_result" | "tool" | "api_req_failed" | "resume_task" | "resume_completed_task" | "mistake_limit_reached" | "browser_action_launch" | "use_mcp_server") | undefined; - say?: ("error" | "api_req_started" | "api_req_finished" | "api_req_retried" | "api_req_retry_delayed" | "api_req_deleted" | "text" | "reasoning" | "completion_result" | "user_feedback" | "user_feedback_diff" | "command_output" | "shell_integration_warning" | "browser_action" | "browser_action_result" | "mcp_server_request_started" | "mcp_server_response" | "subtask_result" | "checkpoint_saved" | "rooignore_error" | "diff_error") | undefined; - text?: string | undefined; - images?: string[] | undefined; - partial?: boolean | undefined; - reasoning?: string | undefined; - conversationHistoryIndex?: number | undefined; - checkpoint?: { - [x: string]: unknown; - } | undefined; - progressStatus?: { - id?: string | undefined; - icon?: string | undefined; - text?: string | undefined; - } | undefined; -}; + ts: number + type: "ask" | "say" + ask?: + | ( + | "followup" + | "command" + | "command_output" + | "completion_result" + | "tool" + | "api_req_failed" + | "resume_task" + | "resume_completed_task" + | "mistake_limit_reached" + | "browser_action_launch" + | "use_mcp_server" + ) + | undefined + say?: + | ( + | "error" + | "api_req_started" + | "api_req_finished" + | "api_req_retried" + | "api_req_retry_delayed" + | "api_req_deleted" + | "text" + | "reasoning" + | "completion_result" + | "user_feedback" + | "user_feedback_diff" + | "command_output" + | "shell_integration_warning" + | "browser_action" + | "browser_action_result" + | "mcp_server_request_started" + | "mcp_server_response" + | "subtask_result" + | "checkpoint_saved" + | "rooignore_error" + | "diff_error" + ) + | undefined + text?: string | undefined + images?: string[] | undefined + partial?: boolean | undefined + reasoning?: string | undefined + conversationHistoryIndex?: number | undefined + checkpoint?: + | { + [x: string]: unknown + } + | undefined + progressStatus?: + | { + id?: string | undefined + icon?: string | undefined + text?: string | undefined + } + | undefined +} export type { ClineMessage } type TokenUsage = { - totalTokensIn: number; - totalTokensOut: number; - totalCacheWrites?: number | undefined; - totalCacheReads?: number | undefined; - totalCost: number; - contextTokens: number; -}; + totalTokensIn: number + totalTokensOut: number + totalCacheWrites?: number | undefined + totalCacheReads?: number | undefined + totalCost: number + contextTokens: number +} export type { TokenUsage } type RooCodeEvents = { - message: [ - { - taskId: string; - action: "created" | "updated"; - message: { - ts: number; - type: "ask" | "say"; - ask?: ("followup" | "command" | "command_output" | "completion_result" | "tool" | "api_req_failed" | "resume_task" | "resume_completed_task" | "mistake_limit_reached" | "browser_action_launch" | "use_mcp_server") | undefined; - say?: ("error" | "api_req_started" | "api_req_finished" | "api_req_retried" | "api_req_retry_delayed" | "api_req_deleted" | "text" | "reasoning" | "completion_result" | "user_feedback" | "user_feedback_diff" | "command_output" | "shell_integration_warning" | "browser_action" | "browser_action_result" | "mcp_server_request_started" | "mcp_server_response" | "subtask_result" | "checkpoint_saved" | "rooignore_error" | "diff_error") | undefined; - text?: string | undefined; - images?: string[] | undefined; - partial?: boolean | undefined; - reasoning?: string | undefined; - conversationHistoryIndex?: number | undefined; - checkpoint?: { - [x: string]: unknown; - } | undefined; - progressStatus?: { - id?: string | undefined; - icon?: string | undefined; - text?: string | undefined; - } | undefined; - }; - } - ]; - taskCreated: [ - string - ]; - taskStarted: [ - string - ]; - taskModeSwitched: [ - string, - string - ]; - taskPaused: [ - string - ]; - taskUnpaused: [ - string - ]; - taskAskResponded: [ - string - ]; - taskAborted: [ - string - ]; - taskSpawned: [ - string, - string - ]; - taskCompleted: [ - string, - { - totalTokensIn: number; - totalTokensOut: number; - totalCacheWrites?: number | undefined; - totalCacheReads?: number | undefined; - totalCost: number; - contextTokens: number; - }, - { - [x: string]: { - attempts: number; - failures: number; - }; - } - ]; - taskTokenUsageUpdated: [ - string, - { - totalTokensIn: number; - totalTokensOut: number; - totalCacheWrites?: number | undefined; - totalCacheReads?: number | undefined; - totalCost: number; - contextTokens: number; - } - ]; - taskToolFailed: [ - string, - "execute_command" | "read_file" | "write_to_file" | "apply_diff" | "insert_content" | "search_and_replace" | "search_files" | "list_files" | "list_code_definition_names" | "browser_action" | "use_mcp_tool" | "access_mcp_resource" | "ask_followup_question" | "attempt_completion" | "switch_mode" | "new_task" | "fetch_instructions", - string - ]; -}; + message: [ + { + taskId: string + action: "created" | "updated" + message: { + ts: number + type: "ask" | "say" + ask?: + | ( + | "followup" + | "command" + | "command_output" + | "completion_result" + | "tool" + | "api_req_failed" + | "resume_task" + | "resume_completed_task" + | "mistake_limit_reached" + | "browser_action_launch" + | "use_mcp_server" + ) + | undefined + say?: + | ( + | "error" + | "api_req_started" + | "api_req_finished" + | "api_req_retried" + | "api_req_retry_delayed" + | "api_req_deleted" + | "text" + | "reasoning" + | "completion_result" + | "user_feedback" + | "user_feedback_diff" + | "command_output" + | "shell_integration_warning" + | "browser_action" + | "browser_action_result" + | "mcp_server_request_started" + | "mcp_server_response" + | "subtask_result" + | "checkpoint_saved" + | "rooignore_error" + | "diff_error" + ) + | undefined + text?: string | undefined + images?: string[] | undefined + partial?: boolean | undefined + reasoning?: string | undefined + conversationHistoryIndex?: number | undefined + checkpoint?: + | { + [x: string]: unknown + } + | undefined + progressStatus?: + | { + id?: string | undefined + icon?: string | undefined + text?: string | undefined + } + | undefined + } + }, + ] + taskCreated: [string] + taskStarted: [string] + taskModeSwitched: [string, string] + taskPaused: [string] + taskUnpaused: [string] + taskAskResponded: [string] + taskAborted: [string] + taskSpawned: [string, string] + taskCompleted: [ + string, + { + totalTokensIn: number + totalTokensOut: number + totalCacheWrites?: number | undefined + totalCacheReads?: number | undefined + totalCost: number + contextTokens: number + }, + { + [x: string]: { + attempts: number + failures: number + } + }, + ] + taskTokenUsageUpdated: [ + string, + { + totalTokensIn: number + totalTokensOut: number + totalCacheWrites?: number | undefined + totalCacheReads?: number | undefined + totalCost: number + contextTokens: number + }, + ] + taskToolFailed: [ + string, + ( + | "execute_command" + | "read_file" + | "write_to_file" + | "apply_diff" + | "insert_content" + | "search_and_replace" + | "search_files" + | "list_files" + | "list_code_definition_names" + | "browser_action" + | "use_mcp_tool" + | "access_mcp_resource" + | "ask_followup_question" + | "attempt_completion" + | "switch_mode" + | "new_task" + | "fetch_instructions" + ), + string, + ] +} -export type { RooCodeEvents } \ No newline at end of file +export type { RooCodeEvents } diff --git a/src/services/telemetry/PostHogClient.ts b/src/services/telemetry/PostHogClient.ts index 31a7fb70bd7..abd4cbefeb7 100644 --- a/src/services/telemetry/PostHogClient.ts +++ b/src/services/telemetry/PostHogClient.ts @@ -50,7 +50,7 @@ export class PostHogClient { this.pearaiId = this.vscMachineId // Initialize with machine ID as fallback this.telemetryEnabled = true this.providerRef = null - this.client = new PostHog('phc_RRjQ4roADRjH6xMbXDUDTA9WLeM5ePPvAJK19w3yj0z', { host: "https://us.i.posthog.com" }) + this.client = new PostHog('phc_EixCfQZYA5It6ZjtZG2C8THsUQzPzXZsdCsvR8AYhfh', { host: "https://us.i.posthog.com" }) // getting the pearai id from the submodule void this.initializePearAIId() @@ -59,8 +59,9 @@ export class PostHogClient { private async initializePearAIId(): Promise { try { const exports = await getpearAIExports() - if (exports) { - this.pearaiId = await exports.pearAPI.getUserId() + const pearaiId = await exports.pearAPI.getUserId() + if (pearaiId) { + this.pearaiId = pearaiId this.client.identify({ distinctId: this.vscMachineId, properties: {