├── .nvmrc ├── webview-ui ├── public │ └── .gitkeep ├── src │ ├── stories │ │ ├── assets │ │ │ └── .gitkeep │ │ ├── Welcome.mdx │ │ ├── Progress.stories.tsx │ │ ├── AutosizeTextarea.stories.tsx │ │ ├── Slider.stories.tsx │ │ ├── Badge.stories.tsx │ │ ├── Collapsible.stories.tsx │ │ ├── Chat.stories.tsx │ │ └── Button.stories.ts │ ├── vite-env.d.ts │ ├── components │ │ ├── ui │ │ │ ├── hooks │ │ │ │ ├── index.ts │ │ │ │ └── useClipboard.ts │ │ │ ├── markdown │ │ │ │ ├── index.ts │ │ │ │ ├── Blockquote.tsx │ │ │ │ └── CodeBlock.tsx │ │ │ ├── chat │ │ │ │ ├── index.ts │ │ │ │ ├── ChatProvider.ts │ │ │ │ ├── useChatUI.ts │ │ │ │ ├── useChatInput.ts │ │ │ │ ├── ChatMessageProvider.ts │ │ │ │ ├── useChatMessage.ts │ │ │ │ ├── ChatInputProvider.ts │ │ │ │ ├── Chat.tsx │ │ │ │ ├── types.ts │ │ │ │ └── ChatMessages.tsx │ │ │ ├── collapsible.tsx │ │ │ ├── index.ts │ │ │ ├── textarea.tsx │ │ │ ├── separator.tsx │ │ │ ├── input.tsx │ │ │ ├── progress.tsx │ │ │ ├── badge.tsx │ │ │ ├── slider.tsx │ │ │ ├── tooltip.tsx │ │ │ ├── popover.tsx │ │ │ └── button.tsx │ │ ├── chat │ │ │ ├── checkpoints │ │ │ │ ├── schema.ts │ │ │ │ └── CheckpointSaved.tsx │ │ │ └── Announcement.tsx │ │ ├── common │ │ │ ├── __mocks__ │ │ │ │ ├── CodeBlock.tsx │ │ │ │ └── MarkdownBlock.tsx │ │ │ ├── CaretIcon.tsx │ │ │ └── VSCodeButtonLink.tsx │ │ ├── history │ │ │ ├── ExportButton.tsx │ │ │ ├── CopyButton.tsx │ │ │ └── DeleteTaskDialog.tsx │ │ ├── settings │ │ │ ├── ApiErrorMessage.tsx │ │ │ ├── ExperimentalFeature.tsx │ │ │ └── styles.ts │ │ ├── mcp │ │ │ ├── McpEnabledToggle.tsx │ │ │ └── McpResourceRow.tsx │ │ └── welcome │ │ │ └── WelcomeView.tsx │ ├── lib │ │ └── utils.ts │ ├── utils │ │ ├── formatPrice.ts │ │ ├── format.ts │ │ ├── highlight.ts │ │ ├── useDebounceEffect.ts │ │ ├── path-mentions.ts │ │ ├── clipboard.ts │ │ ├── mcp.ts │ │ ├── __tests__ │ │ │ ├── format.test.ts │ │ │ └── path-mentions.test.ts │ │ └── getLanguageFromPath.ts │ ├── __mocks__ │ │ ├── lucide-react.ts │ │ ├── pretty-bytes.js │ │ └── vscrui.ts │ ├── index.tsx │ └── setupTests.ts ├── .npmrc ├── .eslintrc.json ├── .storybook │ ├── preview.ts │ ├── main.ts │ └── vscode.css ├── index.html ├── .gitignore ├── components.json ├── tsconfig.json ├── vite.config.ts └── jest.config.cjs ├── .npmrc ├── .gitconfig ├── e2e ├── .env.integration.example ├── tsconfig.json ├── .vscode-test.mjs ├── package.json └── src │ ├── runTest.ts │ └── suite │ ├── extension.test.ts │ └── task.test.ts ├── .prettierignore ├── .github ├── CODEOWNERS ├── ISSUE_TEMPLATE │ ├── config.yml │ └── bug_report.yml ├── dependabot.yml ├── workflows │ ├── discord-pr-notify.yml │ └── marketplace-publish.yml ├── pull_request_template.md └── scripts │ └── get_prev_version_refs.py ├── audio ├── celebration.wav ├── notification.wav └── progress_loop.wav ├── assets ├── icons │ └── rocket.png └── docs │ └── demo.gif ├── .gitattributes ├── .prettierrc.json ├── src ├── __mocks__ │ ├── os-name.js │ ├── delay.js │ ├── strip-ansi.js │ ├── globby.js │ ├── get-folder-size.js │ ├── @modelcontextprotocol │ │ └── sdk │ │ │ ├── client │ │ │ ├── index.js │ │ │ └── stdio.js │ │ │ ├── index.js │ │ │ └── types.js │ ├── default-shell.js │ ├── p-wait-for.js │ ├── McpHub.ts │ ├── serialize-error.js │ ├── jest.setup.ts │ └── vscode.js ├── api │ ├── providers │ │ ├── constants.ts │ │ └── deepseek.ts │ └── transform │ │ ├── stream.ts │ │ └── simple-format.ts ├── activate │ ├── index.ts │ └── handleUri.ts ├── shared │ ├── HistoryItem.ts │ ├── vsCodeSelectorUtils.ts │ ├── globalFileNames.ts │ ├── checkExistApiConfig.ts │ ├── array.ts │ ├── mcp.ts │ ├── __tests__ │ │ ├── vsCodeSelectorUtils.test.ts │ │ ├── experiments.test.ts │ │ └── checkExistApiConfig.test.ts │ ├── tool-groups.ts │ └── experiments.ts ├── services │ ├── tree-sitter │ │ └── queries │ │ │ ├── python.ts │ │ │ ├── php.ts │ │ │ ├── java.ts │ │ │ ├── rust.ts │ │ │ ├── c.ts │ │ │ ├── c-sharp.ts │ │ │ ├── index.ts │ │ │ ├── go.ts │ │ │ ├── cpp.ts │ │ │ ├── typescript.ts │ │ │ ├── swift.ts │ │ │ ├── ruby.ts │ │ │ └── javascript.ts │ ├── checkpoints │ │ ├── constants.ts │ │ └── types.ts │ └── ripgrep │ │ └── __tests__ │ │ └── index.test.ts ├── core │ ├── prompts │ │ ├── tools │ │ │ ├── types.ts │ │ │ ├── switch-mode.ts │ │ │ ├── new-task.ts │ │ │ ├── read-file.ts │ │ │ ├── ask-followup-question.ts │ │ │ ├── list-code-definition-names.ts │ │ │ ├── list-files.ts │ │ │ ├── execute-command.ts │ │ │ ├── access-mcp-resource.ts │ │ │ ├── search-files.ts │ │ │ ├── use-mcp-tool.ts │ │ │ ├── attempt-completion.ts │ │ │ ├── write-to-file.ts │ │ │ ├── insert-content.ts │ │ │ ├── search-and-replace.ts │ │ │ └── browser-action.ts │ │ ├── sections │ │ │ ├── index.ts │ │ │ ├── tool-use.ts │ │ │ ├── objective.ts │ │ │ ├── tool-use-guidelines.ts │ │ │ ├── system-info.ts │ │ │ ├── custom-system-prompt.ts │ │ │ ├── capabilities.ts │ │ │ └── modes.ts │ │ └── __tests__ │ │ │ └── sections.test.ts │ ├── diff │ │ ├── strategies │ │ │ └── new-unified │ │ │ │ └── types.ts │ │ ├── DiffStrategy.ts │ │ ├── insert-groups.ts │ │ └── types.ts │ ├── webview │ │ ├── getNonce.ts │ │ └── getUri.ts │ ├── mode-validator.ts │ └── config │ │ ├── CustomModesSchema.ts │ │ └── __tests__ │ │ └── GroupConfigSchema.test.ts ├── utils │ ├── logging │ │ ├── index.ts │ │ └── __tests__ │ │ │ └── MockTransport.ts │ ├── single-completion-handler.ts │ ├── cost.ts │ ├── fs.ts │ └── sound.ts ├── integrations │ ├── terminal │ │ ├── __tests__ │ │ │ └── TerminalRegistry.test.ts │ │ └── get-latest-output.ts │ ├── misc │ │ └── process-images.ts │ └── editor │ │ └── detect-omission.ts └── exports │ ├── README.md │ └── index.ts ├── .git-blame-ignore-revs ├── .husky ├── pre-commit └── pre-push ├── .changeset ├── config.json ├── README.md └── changelog-config.js ├── .vscode ├── extensions.json ├── settings.json ├── launch.json └── tasks.json ├── .gitignore ├── CHANGELOG.md ├── .eslintrc.json ├── flake.lock ├── knip.json ├── flake.nix ├── tsconfig.json ├── ellipsis.yaml ├── .vscodeignore ├── .clinerules └── jest.config.js /.nvmrc: -------------------------------------------------------------------------------- 1 | lts/* -------------------------------------------------------------------------------- /webview-ui/public/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /webview-ui/src/stories/assets/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org/ -------------------------------------------------------------------------------- /webview-ui/.npmrc: -------------------------------------------------------------------------------- 1 | registry=https://registry.npmjs.org/ -------------------------------------------------------------------------------- /.gitconfig: -------------------------------------------------------------------------------- 1 | [blame] 2 | ignoreRevsFile = .git-blame-ignore-revs 3 | -------------------------------------------------------------------------------- /e2e/.env.integration.example: -------------------------------------------------------------------------------- 1 | OPENROUTER_API_KEY=sk-or-v1-... 2 | -------------------------------------------------------------------------------- /webview-ui/src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/hooks/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./useClipboard" 2 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/markdown/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./Markdown" 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | dist/ 2 | node_modules 3 | webview-ui/build/ 4 | CHANGELOG.md 5 | package-lock.json -------------------------------------------------------------------------------- /webview-ui/src/components/ui/chat/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./types" 2 | export * from "./Chat" 3 | -------------------------------------------------------------------------------- /webview-ui/.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "react-app", 3 | "ignorePatterns": ["!.storybook"] 4 | } 5 | -------------------------------------------------------------------------------- /.github/CODEOWNERS: -------------------------------------------------------------------------------- 1 | # These owners will be the default owners for everything in the repo 2 | * @mrubens @cte 3 | -------------------------------------------------------------------------------- /audio/celebration.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HybridTalentComputing/Roo-Code-Chinese/HEAD/audio/celebration.wav -------------------------------------------------------------------------------- /audio/notification.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HybridTalentComputing/Roo-Code-Chinese/HEAD/audio/notification.wav -------------------------------------------------------------------------------- /assets/icons/rocket.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HybridTalentComputing/Roo-Code-Chinese/HEAD/assets/icons/rocket.png -------------------------------------------------------------------------------- /audio/progress_loop.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/HybridTalentComputing/Roo-Code-Chinese/HEAD/audio/progress_loop.wav -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | demo.gif filter=lfs diff=lfs merge=lfs -text 2 | assets/docs/demo.gif filter=lfs diff=lfs merge=lfs -text 3 | -------------------------------------------------------------------------------- /.prettierrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "tabWidth": 4, 3 | "useTabs": true, 4 | "printWidth": 120, 5 | "semi": false, 6 | "bracketSameLine": true 7 | } 8 | -------------------------------------------------------------------------------- /src/__mocks__/os-name.js: -------------------------------------------------------------------------------- 1 | function osName() { 2 | return "macOS" 3 | } 4 | 5 | module.exports = osName 6 | module.exports.default = osName 7 | -------------------------------------------------------------------------------- /src/api/providers/constants.ts: -------------------------------------------------------------------------------- 1 | export const ANTHROPIC_DEFAULT_MAX_TOKENS = 8192 2 | 3 | export const DEEP_SEEK_DEFAULT_TEMPERATURE = 0.6 4 | -------------------------------------------------------------------------------- /assets/docs/demo.gif: -------------------------------------------------------------------------------- 1 | version https://git-lfs.github.com/spec/v1 2 | oid sha256:d426d600fa80e9ac237cbad6b3f7f47a4aa2005d5218184e6b9565a8ee46d1ba 3 | size 19108207 4 | -------------------------------------------------------------------------------- /src/__mocks__/delay.js: -------------------------------------------------------------------------------- 1 | function delay(ms) { 2 | return new Promise((resolve) => setTimeout(resolve, ms)) 3 | } 4 | 5 | module.exports = delay 6 | module.exports.default = delay 7 | -------------------------------------------------------------------------------- /.git-blame-ignore-revs: -------------------------------------------------------------------------------- 1 | # Ran Prettier on all files - https://github.com/RooVetGit/Roo-Code/pull/404 2 | 60a0a824b96a0b326af4d8871b6903f4ddcfe114 3 | 579bdd9dbf6d2d569e5e7adb5ff6292b1e42ea34 4 | -------------------------------------------------------------------------------- /src/__mocks__/strip-ansi.js: -------------------------------------------------------------------------------- 1 | function stripAnsi(string) { 2 | // Simple mock that just returns the input string 3 | return string 4 | } 5 | 6 | module.exports = stripAnsi 7 | module.exports.default = stripAnsi 8 | -------------------------------------------------------------------------------- /webview-ui/src/lib/utils.ts: -------------------------------------------------------------------------------- 1 | import { clsx, type ClassValue } from "clsx" 2 | import { twMerge } from "tailwind-merge" 3 | 4 | export function cn(...inputs: ClassValue[]) { 5 | return twMerge(clsx(inputs)) 6 | } 7 | -------------------------------------------------------------------------------- /.husky/pre-commit: -------------------------------------------------------------------------------- 1 | branch="$(git rev-parse --abbrev-ref HEAD)" 2 | 3 | if [ "$branch" = "main" ]; then 4 | echo "You can't commit directly to main - please check out a branch." 5 | exit 1 6 | fi 7 | 8 | npx lint-staged 9 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/markdown/Blockquote.tsx: -------------------------------------------------------------------------------- 1 | export const Blockquote = ({ children }: { children: React.ReactNode }) => { 2 | return
{children}
3 | } 4 | -------------------------------------------------------------------------------- /webview-ui/src/stories/Welcome.mdx: -------------------------------------------------------------------------------- 1 | import { Meta } from "@storybook/blocks"; 2 | 3 | 4 | 5 | # Welcome 6 | 7 | This Roo Code storybook is used to independently develop components for the Roo Code webview UI. 8 | -------------------------------------------------------------------------------- /src/__mocks__/globby.js: -------------------------------------------------------------------------------- 1 | function globby(patterns, options) { 2 | return Promise.resolve([]) 3 | } 4 | 5 | globby.sync = function (patterns, options) { 6 | return [] 7 | } 8 | 9 | module.exports = globby 10 | module.exports.default = globby 11 | -------------------------------------------------------------------------------- /src/activate/index.ts: -------------------------------------------------------------------------------- 1 | export { handleUri } from "./handleUri" 2 | export { registerCommands } from "./registerCommands" 3 | export { registerCodeActions } from "./registerCodeActions" 4 | export { registerTerminalActions } from "./registerTerminalActions" 5 | -------------------------------------------------------------------------------- /src/shared/HistoryItem.ts: -------------------------------------------------------------------------------- 1 | export type HistoryItem = { 2 | id: string 3 | ts: number 4 | task: string 5 | tokensIn: number 6 | tokensOut: number 7 | cacheWrites?: number 8 | cacheReads?: number 9 | totalCost: number 10 | size?: number 11 | } 12 | -------------------------------------------------------------------------------- /webview-ui/src/utils/formatPrice.ts: -------------------------------------------------------------------------------- 1 | export const formatPrice = (price: number) => { 2 | return new Intl.NumberFormat("en-US", { 3 | style: "currency", 4 | currency: "USD", 5 | minimumFractionDigits: 2, 6 | maximumFractionDigits: 2, 7 | }).format(price) 8 | } 9 | -------------------------------------------------------------------------------- /webview-ui/src/components/chat/checkpoints/schema.ts: -------------------------------------------------------------------------------- 1 | import { z } from "zod" 2 | 3 | export const checkpointSchema = z.object({ 4 | isFirst: z.boolean(), 5 | from: z.string(), 6 | to: z.string(), 7 | }) 8 | 9 | export type Checkpoint = z.infer 10 | -------------------------------------------------------------------------------- /src/__mocks__/get-folder-size.js: -------------------------------------------------------------------------------- 1 | module.exports = async function getFolderSize() { 2 | return { 3 | size: 1000, 4 | errors: [], 5 | } 6 | } 7 | 8 | module.exports.loose = async function getFolderSizeLoose() { 9 | return { 10 | size: 1000, 11 | errors: [], 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /webview-ui/src/__mocks__/lucide-react.ts: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export const Check = () => React.createElement("div") 4 | export const ChevronsUpDown = () => React.createElement("div") 5 | export const Loader = () => React.createElement("div") 6 | export const X = () => React.createElement("div") 7 | -------------------------------------------------------------------------------- /src/__mocks__/@modelcontextprotocol/sdk/client/index.js: -------------------------------------------------------------------------------- 1 | class Client { 2 | constructor() { 3 | this.request = jest.fn() 4 | } 5 | 6 | connect() { 7 | return Promise.resolve() 8 | } 9 | 10 | close() { 11 | return Promise.resolve() 12 | } 13 | } 14 | 15 | module.exports = { 16 | Client, 17 | } 18 | -------------------------------------------------------------------------------- /src/services/tree-sitter/queries/python.ts: -------------------------------------------------------------------------------- 1 | /* 2 | - class definitions 3 | - function definitions 4 | */ 5 | export default ` 6 | (class_definition 7 | name: (identifier) @name.definition.class) @definition.class 8 | 9 | (function_definition 10 | name: (identifier) @name.definition.function) @definition.function 11 | ` 12 | -------------------------------------------------------------------------------- /.changeset/config.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/@changesets/config@3.0.4/schema.json", 3 | "changelog": "./changelog-config.js", 4 | "commit": false, 5 | "fixed": [], 6 | "linked": [], 7 | "access": "restricted", 8 | "baseBranch": "main", 9 | "updateInternalDependencies": "patch", 10 | "ignore": [] 11 | } 12 | -------------------------------------------------------------------------------- /src/__mocks__/default-shell.js: -------------------------------------------------------------------------------- 1 | // Mock default shell based on platform 2 | const os = require("os") 3 | 4 | let defaultShell 5 | if (os.platform() === "win32") { 6 | defaultShell = "cmd.exe" 7 | } else { 8 | defaultShell = "/bin/bash" 9 | } 10 | 11 | module.exports = defaultShell 12 | module.exports.default = defaultShell 13 | -------------------------------------------------------------------------------- /webview-ui/src/components/common/__mocks__/CodeBlock.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | interface CodeBlockProps { 4 | children?: React.ReactNode 5 | language?: string 6 | } 7 | 8 | const CodeBlock: React.FC = () =>
Mocked Code Block
9 | 10 | export default CodeBlock 11 | -------------------------------------------------------------------------------- /src/core/prompts/tools/types.ts: -------------------------------------------------------------------------------- 1 | import { DiffStrategy } from "../../diff/DiffStrategy" 2 | import { McpHub } from "../../../services/mcp/McpHub" 3 | 4 | export type ToolArgs = { 5 | cwd: string 6 | supportsComputerUse: boolean 7 | diffStrategy?: DiffStrategy 8 | browserViewportSize?: string 9 | mcpHub?: McpHub 10 | toolOptions?: any 11 | } 12 | -------------------------------------------------------------------------------- /src/shared/vsCodeSelectorUtils.ts: -------------------------------------------------------------------------------- 1 | import { LanguageModelChatSelector } from "vscode" 2 | 3 | export const SELECTOR_SEPARATOR = "/" 4 | 5 | export function stringifyVsCodeLmModelSelector(selector: LanguageModelChatSelector): string { 6 | return [selector.vendor, selector.family, selector.version, selector.id].filter(Boolean).join(SELECTOR_SEPARATOR) 7 | } 8 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/chat/ChatProvider.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from "react" 2 | 3 | import { ChatHandler } from "./types" 4 | 5 | type ChatContext = ChatHandler & { 6 | assistantName: string 7 | } 8 | 9 | export const chatContext = createContext(null) 10 | 11 | export const ChatProvider = chatContext.Provider 12 | -------------------------------------------------------------------------------- /webview-ui/src/index.tsx: -------------------------------------------------------------------------------- 1 | import { StrictMode } from "react" 2 | import { createRoot } from "react-dom/client" 3 | 4 | import "./index.css" 5 | import App from "./App" 6 | import "../../node_modules/@vscode/codicons/dist/codicon.css" 7 | 8 | createRoot(document.getElementById("root")!).render( 9 | 10 | 11 | , 12 | ) 13 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/chat/useChatUI.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react" 2 | 3 | import { chatContext } from "./ChatProvider" 4 | 5 | export const useChatUI = () => { 6 | const context = useContext(chatContext) 7 | 8 | if (!context) { 9 | throw new Error("useChatUI must be used within a ChatProvider") 10 | } 11 | 12 | return context 13 | } 14 | -------------------------------------------------------------------------------- /webview-ui/.storybook/preview.ts: -------------------------------------------------------------------------------- 1 | import type { Preview } from "@storybook/react" 2 | 3 | import "./vscode.css" 4 | import "../src/index.css" 5 | 6 | const preview: Preview = { 7 | parameters: { 8 | controls: { 9 | matchers: { 10 | color: /(background|color)$/i, 11 | date: /Date$/i, 12 | }, 13 | }, 14 | }, 15 | } 16 | 17 | export default preview 18 | -------------------------------------------------------------------------------- /webview-ui/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Roo Code Chinese 7 | 8 | 9 |
10 | 11 | 12 | -------------------------------------------------------------------------------- /webview-ui/src/components/common/CaretIcon.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export const CaretIcon = () => ( 4 | 13 | 14 | 15 | ) 16 | -------------------------------------------------------------------------------- /webview-ui/src/components/common/__mocks__/MarkdownBlock.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | interface MarkdownBlockProps { 4 | children?: React.ReactNode 5 | content?: string 6 | } 7 | 8 | const MarkdownBlock: React.FC = ({ content }) => ( 9 |
{content}
10 | ) 11 | 12 | export default MarkdownBlock 13 | -------------------------------------------------------------------------------- /src/shared/globalFileNames.ts: -------------------------------------------------------------------------------- 1 | export const GlobalFileNames = { 2 | apiConversationHistory: "api_conversation_history.json", 3 | uiMessages: "ui_messages.json", 4 | glamaModels: "glama_models.json", 5 | openRouterModels: "openrouter_models.json", 6 | requestyModels: "requesty_models.json", 7 | mcpSettings: "cline_mcp_settings.json", 8 | unboundModels: "unbound_models.json", 9 | } 10 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/chat/useChatInput.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react" 2 | 3 | import { chatInputContext } from "./ChatInputProvider" 4 | 5 | export const useChatInput = () => { 6 | const context = useContext(chatInputContext) 7 | 8 | if (!context) { 9 | throw new Error("useChatInput must be used within a ChatInputProvider") 10 | } 11 | 12 | return context 13 | } 14 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/collapsible.tsx: -------------------------------------------------------------------------------- 1 | import * as CollapsiblePrimitive from "@radix-ui/react-collapsible" 2 | 3 | const Collapsible = CollapsiblePrimitive.Root 4 | 5 | const CollapsibleTrigger = CollapsiblePrimitive.CollapsibleTrigger 6 | 7 | const CollapsibleContent = CollapsiblePrimitive.CollapsibleContent 8 | 9 | export { Collapsible, CollapsibleTrigger, CollapsibleContent } 10 | -------------------------------------------------------------------------------- /webview-ui/.storybook/main.ts: -------------------------------------------------------------------------------- 1 | import type { StorybookConfig } from "@storybook/react-vite" 2 | 3 | const config: StorybookConfig = { 4 | stories: ["../src/**/*.mdx", "../src/**/*.stories.@(js|jsx|mjs|ts|tsx)"], 5 | addons: ["@storybook/addon-essentials", "storybook-dark-mode"], 6 | framework: { 7 | name: "@storybook/react-vite", 8 | options: {}, 9 | }, 10 | } 11 | export default config 12 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/chat/ChatMessageProvider.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from "react" 2 | 3 | import { Message } from "./types" 4 | 5 | export interface ChatMessageContext { 6 | message: Message 7 | isLast: boolean 8 | } 9 | 10 | export const chatMessageContext = createContext(null) 11 | 12 | export const ChatMessageProvider = chatMessageContext.Provider 13 | -------------------------------------------------------------------------------- /.vscode/extensions.json: -------------------------------------------------------------------------------- 1 | { 2 | // See http://go.microsoft.com/fwlink/?LinkId=827846 3 | // for the documentation about the extensions.json format 4 | "recommendations": [ 5 | "dbaeumer.vscode-eslint", 6 | "connor4312.esbuild-problem-matchers", 7 | "ms-vscode.extension-test-runner", 8 | "csstools.postcss", 9 | "bradlc.vscode-tailwindcss", 10 | "tobermory.es6-string-html" 11 | ] 12 | } 13 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/chat/useChatMessage.ts: -------------------------------------------------------------------------------- 1 | import { useContext } from "react" 2 | 3 | import { chatMessageContext } from "./ChatMessageProvider" 4 | 5 | export const useChatMessage = () => { 6 | const context = useContext(chatMessageContext) 7 | 8 | if (!context) { 9 | throw new Error("useChatMessage must be used within a ChatMessageProvider") 10 | } 11 | 12 | return context 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | out 3 | out-* 4 | node_modules 5 | coverage/ 6 | 7 | .DS_Store 8 | 9 | # Builds 10 | bin/ 11 | roo-cline-*.vsix 12 | 13 | # Local prompts and rules 14 | /local-prompts 15 | 16 | # Test environment 17 | .test_env 18 | .vscode-test/ 19 | 20 | # Docs 21 | docs/_site/ 22 | 23 | # Dotenv 24 | .env.integration 25 | 26 | #Local lint config 27 | .eslintrc.local.json 28 | 29 | #Logging 30 | logs 31 | -------------------------------------------------------------------------------- /src/core/diff/strategies/new-unified/types.ts: -------------------------------------------------------------------------------- 1 | export type Change = { 2 | type: "context" | "add" | "remove" 3 | content: string 4 | indent: string 5 | originalLine?: string 6 | } 7 | 8 | export type Hunk = { 9 | changes: Change[] 10 | } 11 | 12 | export type Diff = { 13 | hunks: Hunk[] 14 | } 15 | 16 | export type EditResult = { 17 | confidence: number 18 | result: string[] 19 | strategy: string 20 | } 21 | -------------------------------------------------------------------------------- /src/services/tree-sitter/queries/php.ts: -------------------------------------------------------------------------------- 1 | /* 2 | - class declarations 3 | - function definitions 4 | - method declarations 5 | */ 6 | export default ` 7 | (class_declaration 8 | name: (name) @name.definition.class) @definition.class 9 | 10 | (function_definition 11 | name: (name) @name.definition.function) @definition.function 12 | 13 | (method_declaration 14 | name: (name) @name.definition.function) @definition.function 15 | ` 16 | -------------------------------------------------------------------------------- /src/services/tree-sitter/queries/java.ts: -------------------------------------------------------------------------------- 1 | /* 2 | - class declarations 3 | - method declarations 4 | - interface declarations 5 | */ 6 | export default ` 7 | (class_declaration 8 | name: (identifier) @name.definition.class) @definition.class 9 | 10 | (method_declaration 11 | name: (identifier) @name.definition.method) @definition.method 12 | 13 | (interface_declaration 14 | name: (identifier) @name.definition.interface) @definition.interface 15 | ` 16 | -------------------------------------------------------------------------------- /webview-ui/.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | 25 | *storybook.log 26 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/chat/ChatInputProvider.ts: -------------------------------------------------------------------------------- 1 | import { createContext } from "react" 2 | 3 | interface ChatInputContext { 4 | isDisabled: boolean 5 | handleKeyDown: (e: React.KeyboardEvent) => void 6 | handleSubmit: (e: React.FormEvent) => void 7 | } 8 | 9 | export const chatInputContext = createContext(null) 10 | 11 | export const ChatInputProvider = chatInputContext.Provider 12 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Feature Request 4 | url: https://github.com/RooVetGit/Roo-Code/discussions/categories/feature-requests 5 | about: Share and vote on feature requests for Roo Code 6 | - name: Leave a Review 7 | url: https://marketplace.visualstudio.com/items?itemName=RooVeterinaryInc.roo-cline&ssr=false#review-details 8 | about: Enjoying Roo Code? Leave a review here! 9 | -------------------------------------------------------------------------------- /src/services/tree-sitter/queries/rust.ts: -------------------------------------------------------------------------------- 1 | /* 2 | - struct definitions 3 | - method definitions 4 | - function definitions 5 | */ 6 | export default ` 7 | (struct_item 8 | name: (type_identifier) @name.definition.class) @definition.class 9 | 10 | (declaration_list 11 | (function_item 12 | name: (identifier) @name.definition.method)) @definition.method 13 | 14 | (function_item 15 | name: (identifier) @name.definition.function) @definition.function 16 | ` 17 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Roo Code Changelog 2 | 3 | ## [3.7.12] 4 | 5 | - 将思维模型的最大令牌数扩展到 128k,最大思维预算超过 100k(感谢 @monotykamary!) 6 | - 修复键盘模式切换器未更新 API 配置文件的问题(感谢 @aheizi!) 7 | - 在 Anthropic 提供程序中使用 count_tokens API 以实现更准确的上下文窗口管理 8 | - 为 OpenRouter 默认启用中间压缩 9 | - 如果模式不支持 MCP,则从提示中排除 MCP 指令 10 | - 添加禁用浏览器工具的复选框 11 | - 当检查点加载时间过长时显示警告 12 | - 更新 VS LM API 的警告文本 13 | - 正确填充欢迎界面上的默认 OpenRouter 模型 14 | 15 | ## [3.7.11] 16 | 17 | - 不对非思维模型应用自定义最大令牌数限制 18 | - 在模式切换键盘快捷键中包含自定义模式 19 | - 支持可以运行命令的只读模式 -------------------------------------------------------------------------------- /e2e/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "module": "CommonJS", 4 | "moduleResolution": "Node", 5 | "esModuleInterop": true, 6 | "target": "ES2022", 7 | "lib": ["ES2022", "ESNext.Disposable", "DOM"], 8 | "sourceMap": true, 9 | "strict": true, 10 | "skipLibCheck": true, 11 | "useUnknownInCatchVariables": false, 12 | "outDir": "out" 13 | }, 14 | "include": ["src", "../src/exports/cline.d.ts"], 15 | "exclude": [".vscode-test", "**/node_modules/**", "out"] 16 | } 17 | -------------------------------------------------------------------------------- /webview-ui/components.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://ui.shadcn.com/schema.json", 3 | "style": "new-york", 4 | "rsc": false, 5 | "tsx": true, 6 | "tailwind": { 7 | "config": "tailwind.config.js", 8 | "css": "src/index.css", 9 | "baseColor": "neutral", 10 | "cssVariables": true, 11 | "prefix": "" 12 | }, 13 | "aliases": { 14 | "components": "@/components", 15 | "utils": "@/lib/utils", 16 | "ui": "@/components/ui", 17 | "lib": "@/lib", 18 | "hooks": "@/hooks" 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /e2e/.vscode-test.mjs: -------------------------------------------------------------------------------- 1 | /** 2 | * See: https://code.visualstudio.com/api/working-with-extensions/testing-extension 3 | */ 4 | 5 | import { defineConfig } from '@vscode/test-cli'; 6 | 7 | export default defineConfig({ 8 | label: 'integrationTest', 9 | files: 'out/suite/**/*.test.js', 10 | workspaceFolder: '.', 11 | mocha: { 12 | ui: 'tdd', 13 | timeout: 60000, 14 | }, 15 | launchArgs: [ 16 | '--enable-proposed-api=RooVeterinaryInc.roo-cline', 17 | '--disable-extensions' 18 | ] 19 | }); 20 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/index.ts: -------------------------------------------------------------------------------- 1 | export * from "./alert-dialog" 2 | export * from "./autosize-textarea" 3 | export * from "./badge" 4 | export * from "./button" 5 | export * from "./collapsible" 6 | export * from "./command" 7 | export * from "./dialog" 8 | export * from "./dropdown-menu" 9 | export * from "./input" 10 | export * from "./popover" 11 | export * from "./progress" 12 | export * from "./separator" 13 | export * from "./slider" 14 | export * from "./textarea" 15 | export * from "./tooltip" 16 | -------------------------------------------------------------------------------- /src/__mocks__/@modelcontextprotocol/sdk/client/stdio.js: -------------------------------------------------------------------------------- 1 | class StdioClientTransport { 2 | constructor() { 3 | this.start = jest.fn().mockResolvedValue(undefined) 4 | this.close = jest.fn().mockResolvedValue(undefined) 5 | this.stderr = { 6 | on: jest.fn(), 7 | } 8 | } 9 | } 10 | 11 | class StdioServerParameters { 12 | constructor() { 13 | this.command = "" 14 | this.args = [] 15 | this.env = {} 16 | } 17 | } 18 | 19 | module.exports = { 20 | StdioClientTransport, 21 | StdioServerParameters, 22 | } 23 | -------------------------------------------------------------------------------- /src/core/prompts/tools/switch-mode.ts: -------------------------------------------------------------------------------- 1 | export function getSwitchModeDescription(): string { 2 | return `## switch_mode 3 | 描述:请求切换到不同的模式。此工具允许模式在需要时请求切换到另一个模式,例如切换到代码模式以进行代码更改。用户必须批准模式切换。 4 | 参数: 5 | - mode_slug:(必需)要切换到的模式的标识符(例如,"code"、"ask"、"architect") 6 | - reason:(可选)切换模式的原因 7 | 用法: 8 | 9 | 在此输入模式标识符 10 | 在此输入切换原因 11 | 12 | 13 | 示例:请求切换到代码模式 14 | 15 | code 16 | 需要进行代码更改 17 | ` 18 | } 19 | -------------------------------------------------------------------------------- /webview-ui/src/components/history/ExportButton.tsx: -------------------------------------------------------------------------------- 1 | import { vscode } from "@/utils/vscode" 2 | import { Button } from "@/components/ui" 3 | 4 | export const ExportButton = ({ itemId }: { itemId: string }) => ( 5 | 16 | ) 17 | -------------------------------------------------------------------------------- /src/__mocks__/p-wait-for.js: -------------------------------------------------------------------------------- 1 | function pWaitFor(condition, options = {}) { 2 | return new Promise((resolve, reject) => { 3 | const interval = setInterval(() => { 4 | if (condition()) { 5 | clearInterval(interval) 6 | resolve() 7 | } 8 | }, options.interval || 20) 9 | 10 | if (options.timeout) { 11 | setTimeout(() => { 12 | clearInterval(interval) 13 | reject(new Error("Timed out")) 14 | }, options.timeout) 15 | } 16 | }) 17 | } 18 | 19 | module.exports = pWaitFor 20 | module.exports.default = pWaitFor 21 | -------------------------------------------------------------------------------- /.changeset/README.md: -------------------------------------------------------------------------------- 1 | # Changesets 2 | 3 | Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works 4 | with multi-package repos, or single-package repos to help you version and publish your code. You can 5 | find the full documentation for it [in our repository](https://github.com/changesets/changesets) 6 | 7 | We have a quick list of common questions to get you started engaging with this project in 8 | [our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md) 9 | -------------------------------------------------------------------------------- /src/__mocks__/McpHub.ts: -------------------------------------------------------------------------------- 1 | export class McpHub { 2 | connections = [] 3 | isConnecting = false 4 | 5 | constructor() { 6 | this.toggleToolAlwaysAllow = jest.fn() 7 | this.callTool = jest.fn() 8 | } 9 | 10 | async toggleToolAlwaysAllow(serverName: string, toolName: string, shouldAllow: boolean): Promise { 11 | return Promise.resolve() 12 | } 13 | 14 | async callTool(serverName: string, toolName: string, toolArguments?: Record): Promise { 15 | return Promise.resolve({ result: "success" }) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/core/prompts/sections/index.ts: -------------------------------------------------------------------------------- 1 | export { getRulesSection } from "./rules" 2 | export { getSystemInfoSection } from "./system-info" 3 | export { getObjectiveSection } from "./objective" 4 | export { addCustomInstructions } from "./custom-instructions" 5 | export { getSharedToolUseSection } from "./tool-use" 6 | export { getMcpServersSection } from "./mcp-servers" 7 | export { getToolUseGuidelinesSection } from "./tool-use-guidelines" 8 | export { getCapabilitiesSection } from "./capabilities" 9 | export { getModesSection } from "./modes" 10 | -------------------------------------------------------------------------------- /webview-ui/src/__mocks__/pretty-bytes.js: -------------------------------------------------------------------------------- 1 | module.exports = function prettyBytes(bytes) { 2 | if (typeof bytes !== "number") { 3 | throw new TypeError("Expected a number") 4 | } 5 | 6 | // Simple mock implementation that returns formatted strings. 7 | if (bytes === 0) return "0 B" 8 | if (bytes < 1024) return `${bytes} B` 9 | if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)} KB` 10 | if (bytes < 1024 * 1024 * 1024) return `${(bytes / (1024 * 1024)).toFixed(1)} MB` 11 | return `${(bytes / (1024 * 1024 * 1024)).toFixed(1)} GB` 12 | } 13 | -------------------------------------------------------------------------------- /webview-ui/src/components/settings/ApiErrorMessage.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | interface ApiErrorMessageProps { 4 | errorMessage: string | undefined 5 | children?: React.ReactNode 6 | } 7 | 8 | export const ApiErrorMessage = ({ errorMessage, children }: ApiErrorMessageProps) => ( 9 |
10 |
11 |
12 |
{errorMessage}
13 |
14 | {children} 15 |
16 | ) 17 | -------------------------------------------------------------------------------- /.changeset/changelog-config.js: -------------------------------------------------------------------------------- 1 | // Half-works to simplify the format but needs 'overwrite_changeset_changelog.py' in GHA to finish formatting 2 | 3 | const getReleaseLine = async (changeset) => { 4 | const [firstLine] = changeset.summary 5 | .split("\n") 6 | .map((l) => l.trim()) 7 | .filter(Boolean) 8 | return `- ${firstLine}` 9 | } 10 | 11 | const getDependencyReleaseLine = async () => { 12 | return "" 13 | } 14 | 15 | const changelogFunctions = { 16 | getReleaseLine, 17 | getDependencyReleaseLine, 18 | } 19 | 20 | module.exports = changelogFunctions 21 | -------------------------------------------------------------------------------- /webview-ui/src/stories/Progress.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from "@storybook/react" 2 | 3 | import { Progress } from "@/components/ui" 4 | 5 | const meta: Meta = { 6 | title: "Primitives/Progress", 7 | component: Progress, 8 | parameters: { 9 | layout: "centered", 10 | }, 11 | args: { 12 | className: "w-[300px]", 13 | }, 14 | tags: ["autodocs"], 15 | } 16 | 17 | export default meta 18 | 19 | type Story = StoryObj 20 | 21 | export const Default: Story = { 22 | args: { 23 | value: 50, 24 | }, 25 | } 26 | -------------------------------------------------------------------------------- /.eslintrc.json: -------------------------------------------------------------------------------- 1 | { 2 | "root": true, 3 | "parser": "@typescript-eslint/parser", 4 | "parserOptions": { 5 | "ecmaVersion": 6, 6 | "sourceType": "module" 7 | }, 8 | "plugins": ["@typescript-eslint"], 9 | "rules": { 10 | "@typescript-eslint/naming-convention": [ 11 | "warn", 12 | { 13 | "selector": "import", 14 | "format": ["camelCase", "PascalCase"] 15 | } 16 | ], 17 | "@typescript-eslint/semi": "off", 18 | "eqeqeq": "warn", 19 | "no-throw-literal": "warn", 20 | "semi": "off" 21 | }, 22 | "ignorePatterns": ["out", "dist", "**/*.d.ts"] 23 | } 24 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "npm" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "weekly" 12 | -------------------------------------------------------------------------------- /src/core/prompts/tools/new-task.ts: -------------------------------------------------------------------------------- 1 | import { ToolArgs } from "./types" 2 | 3 | export function getNewTaskDescription(args: ToolArgs): string { 4 | return `## new_task 5 | Description: 使用指定的启动模式和初始消息创建新任务。此工具指示系统在给定模式下创建新的 Cline 实例,并提供初始消息。 6 | 7 | Parameters: 8 | - mode: (必填) 启动新任务的模式标识符(例如:"code"、"ask"、"architect")。 9 | - message: (必填) 此新任务的初始用户消息或指令。 10 | 11 | Usage: 12 | 13 | 在此填写模式标识符 14 | 在此填写初始指令 15 | 16 | 17 | Example: 18 | 19 | code 20 | 为应用程序实现新功能。 21 | 22 | ` 23 | } 24 | -------------------------------------------------------------------------------- /src/services/tree-sitter/queries/c.ts: -------------------------------------------------------------------------------- 1 | /* 2 | - struct declarations 3 | - union declarations 4 | - function declarations 5 | - typedef declarations 6 | */ 7 | export default ` 8 | (struct_specifier name: (type_identifier) @name.definition.class body:(_)) @definition.class 9 | 10 | (declaration type: (union_specifier name: (type_identifier) @name.definition.class)) @definition.class 11 | 12 | (function_declarator declarator: (identifier) @name.definition.function) @definition.function 13 | 14 | (type_definition declarator: (type_identifier) @name.definition.type) @definition.type 15 | ` 16 | -------------------------------------------------------------------------------- /src/core/prompts/sections/tool-use.ts: -------------------------------------------------------------------------------- 1 | export function getSharedToolUseSection(): string { 2 | return `==== 3 | 4 | 工具使用 5 | 6 | 你可以使用一系列工具,这些工具将在用户批准后执行。每条消息你可以使用一个工具,并且在用户的回复中会收到该工具使用的结果。你需要一步一步地使用工具来完成给定的任务,每次工具的使用都应基于前一次工具使用的结果。 7 | 8 | # 工具使用格式 9 | 10 | 工具使用采用 XML 风格的标签格式。工具名称包含在开始和结束标签中,每个参数也同样包含在其自己的标签集中。结构如下: 11 | 12 | 13 | value1 14 | value2 15 | ... 16 | 17 | 18 | 例如: 19 | 20 | 21 | src/main.js 22 | 23 | 24 | 请始终遵循此格式以确保工具使用能够正确解析和执行。` 25 | } 26 | -------------------------------------------------------------------------------- /src/__mocks__/serialize-error.js: -------------------------------------------------------------------------------- 1 | function serializeError(error) { 2 | if (error instanceof Error) { 3 | return { 4 | name: error.name, 5 | message: error.message, 6 | stack: error.stack, 7 | } 8 | } 9 | return error 10 | } 11 | 12 | function deserializeError(errorData) { 13 | if (errorData && typeof errorData === "object") { 14 | const error = new Error(errorData.message) 15 | error.name = errorData.name 16 | error.stack = errorData.stack 17 | return error 18 | } 19 | return errorData 20 | } 21 | 22 | module.exports = { 23 | serializeError, 24 | deserializeError, 25 | } 26 | -------------------------------------------------------------------------------- /src/api/transform/stream.ts: -------------------------------------------------------------------------------- 1 | export type ApiStream = AsyncGenerator 2 | export type ApiStreamChunk = ApiStreamTextChunk | ApiStreamUsageChunk | ApiStreamReasoningChunk 3 | 4 | export interface ApiStreamTextChunk { 5 | type: "text" 6 | text: string 7 | } 8 | 9 | export interface ApiStreamReasoningChunk { 10 | type: "reasoning" 11 | text: string 12 | } 13 | 14 | export interface ApiStreamUsageChunk { 15 | type: "usage" 16 | inputTokens: number 17 | outputTokens: number 18 | cacheWriteTokens?: number 19 | cacheReadTokens?: number 20 | totalCost?: number // openrouter 21 | } 22 | -------------------------------------------------------------------------------- /src/core/prompts/tools/read-file.ts: -------------------------------------------------------------------------------- 1 | import { ToolArgs } from "./types" 2 | 3 | export function getReadFileDescription(args: ToolArgs): string { 4 | return `## read_file 5 | 描述:请求读取指定路径文件的内容。当您需要检查一个您不知道内容的现有文件时使用此工具,例如分析代码、查看文本文件或从配置文件中提取信息。输出内容会在每行前添加行号(例如:"1 | const x = 1"),这样在创建差异或讨论代码时更容易引用特定行。可以自动从PDF和DOCX文件中提取原始文本。可能不适用于其他类型的二进制文件,因为它会将原始内容作为字符串返回。 6 | 参数: 7 | - path:(必需)要读取的文件路径(相对于当前工作目录 ${args.cwd}) 8 | 用法: 9 | 10 | 在此处填写文件路径 11 | 12 | 13 | 示例:请求读取frontend-config.json文件 14 | 15 | frontend-config.json 16 | ` 17 | } 18 | -------------------------------------------------------------------------------- /src/core/webview/getNonce.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * A helper function that returns a unique alphanumeric identifier called a nonce. 3 | * 4 | * @remarks This function is primarily used to help enforce content security 5 | * policies for resources/scripts being executed in a webview context. 6 | * 7 | * @returns A nonce 8 | */ 9 | export function getNonce() { 10 | let text = "" 11 | const possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" 12 | for (let i = 0; i < 32; i++) { 13 | text += possible.charAt(Math.floor(Math.random() * possible.length)) 14 | } 15 | return text 16 | } 17 | -------------------------------------------------------------------------------- /src/services/tree-sitter/queries/c-sharp.ts: -------------------------------------------------------------------------------- 1 | /* 2 | - class declarations 3 | - interface declarations 4 | - method declarations 5 | - namespace declarations 6 | */ 7 | export default ` 8 | (class_declaration 9 | name: (identifier) @name.definition.class 10 | ) @definition.class 11 | 12 | (interface_declaration 13 | name: (identifier) @name.definition.interface 14 | ) @definition.interface 15 | 16 | (method_declaration 17 | name: (identifier) @name.definition.method 18 | ) @definition.method 19 | 20 | (namespace_declaration 21 | name: (identifier) @name.definition.module 22 | ) @definition.module 23 | ` 24 | -------------------------------------------------------------------------------- /src/core/prompts/tools/ask-followup-question.ts: -------------------------------------------------------------------------------- 1 | export function getAskFollowupQuestionDescription(): string { 2 | return `## ask_followup_question 3 | Description: 向用户提出问题以收集完成任务所需的额外信息。当您遇到模糊之处、需要澄清或需要更多细节以有效推进时,应使用此工具。它通过实现与用户的直接沟通来支持交互式问题解决。请谨慎使用此工具,在收集必要信息和避免过多来回交互之间保持平衡。 4 | Parameters: 5 | - question: (必填) 要向用户提出的问题。这应该是一个明确、具体的问题,针对您需要的信息。 6 | Usage: 7 | 8 | 在此处输入您的问题 9 | 10 | 11 | Example: 请求用户提供frontend-config.json文件的路径 12 | 13 | frontend-config.json文件的路径是什么? 14 | ` 15 | } 16 | -------------------------------------------------------------------------------- /src/core/prompts/tools/list-code-definition-names.ts: -------------------------------------------------------------------------------- 1 | import { ToolArgs } from "./types" 2 | 3 | export function getListCodeDefinitionNamesDescription(args: ToolArgs): string { 4 | return `## list_code_definition_names 5 | Description: 请求列出指定目录中源代码文件顶层的定义名称(类、函数、方法等)。该工具提供代码库结构和重要构造的洞察,封装了对理解整体架构至关重要的高层概念和关系。 6 | Parameters: 7 | - path: (必需) 要列出顶层源代码定义的目录路径(相对于当前工作目录 ${args.cwd})。 8 | Usage: 9 | 10 | 在此处填写目录路径 11 | 12 | 13 | Example: 请求列出当前目录中所有顶层源代码定义 14 | 15 | . 16 | ` 17 | } 18 | -------------------------------------------------------------------------------- /webview-ui/src/components/common/VSCodeButtonLink.tsx: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | import { VSCodeButton } from "@vscode/webview-ui-toolkit/react" 3 | 4 | interface VSCodeButtonLinkProps { 5 | href: string 6 | children: React.ReactNode 7 | [key: string]: any 8 | } 9 | 10 | const VSCodeButtonLink: React.FC = ({ href, children, ...props }) => { 11 | return ( 12 | 18 | {children} 19 | 20 | ) 21 | } 22 | 23 | export default VSCodeButtonLink 24 | -------------------------------------------------------------------------------- /webview-ui/src/stories/AutosizeTextarea.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from "@storybook/react" 2 | import { AutosizeTextarea } from "../components/ui/autosize-textarea" 3 | 4 | const meta: Meta = { 5 | title: "Primitives/AutosizeTextarea", 6 | component: AutosizeTextarea, 7 | tags: ["autodocs"], 8 | args: { 9 | minHeight: 40, 10 | maxHeight: 400, 11 | placeholder: "This textarea will expand as you type.", 12 | className: "p-2", 13 | }, 14 | } 15 | 16 | export default meta 17 | 18 | type Story = StoryObj 19 | 20 | export const Default: Story = { 21 | args: {}, 22 | } 23 | -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | // Place your settings in this file to overwrite default and user settings. 2 | { 3 | "files.exclude": { 4 | "out": false, // set this to true to hide the "out" folder with the compiled JS files 5 | "dist": false // set this to true to hide the "dist" folder with the compiled JS files 6 | }, 7 | "search.exclude": { 8 | "out": true, // set this to false to include "out" folder in search results 9 | "dist": true // set this to false to include "dist" folder in search results 10 | }, 11 | // Turn off tsc task auto detection since we have the necessary tasks as npm scripts 12 | "typescript.tsc.autoDetect": "off" 13 | } 14 | -------------------------------------------------------------------------------- /e2e/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "e2e", 3 | "version": "0.1.0", 4 | "private": true, 5 | "scripts": { 6 | "build": "cd .. && npm run build", 7 | "compile": "tsc -p tsconfig.json", 8 | "lint": "eslint src --ext ts", 9 | "check-types": "tsc --noEmit", 10 | "test": "npm run compile && npx dotenvx run -f .env.integration -- node ./out/runTest.js", 11 | "ci": "npm run build && npm run test" 12 | }, 13 | "devDependencies": { 14 | "@types/jest": "^29.5.14", 15 | "@types/mocha": "^10.0.10", 16 | "@vscode/test-cli": "^0.0.9", 17 | "@vscode/test-electron": "^2.4.1", 18 | "mocha": "^11.1.0", 19 | "typescript": "^5.4.5" 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/hooks/useClipboard.ts: -------------------------------------------------------------------------------- 1 | import { useState } from "react" 2 | 3 | export interface UseClipboardProps { 4 | timeout?: number 5 | } 6 | 7 | export function useClipboard({ timeout = 2000 }: UseClipboardProps = {}) { 8 | const [isCopied, setIsCopied] = useState(false) 9 | 10 | const copy = (value: string) => { 11 | if (typeof window === "undefined" || !navigator.clipboard?.writeText || !value) { 12 | return 13 | } 14 | 15 | navigator.clipboard.writeText(value).then(() => { 16 | setIsCopied(true) 17 | setTimeout(() => setIsCopied(false), timeout) 18 | }) 19 | } 20 | 21 | return { isCopied, copy } 22 | } 23 | -------------------------------------------------------------------------------- /src/core/prompts/tools/list-files.ts: -------------------------------------------------------------------------------- 1 | import { ToolArgs } from "./types" 2 | 3 | export function getListFilesDescription(args: ToolArgs): string { 4 | return `## list_files 5 | 描述:请求列出指定目录中的文件和目录。如果recursive为true,将递归列出所有文件和目录;如果recursive为false或未提供,则仅列出顶层内容。请勿使用此工具来确认您可能已创建的文件是否存在,因为用户会告知您文件是否创建成功。 6 | 参数: 7 | - path:(必需)要列出内容的目录路径(相对于当前工作目录 ${args.cwd}) 8 | - recursive:(可选)是否递归列出文件。使用true进行递归列出,使用false或省略则仅列出顶层内容。 9 | 用法: 10 | 11 | 在此处填写目录路径 12 | true或false(可选) 13 | 14 | 15 | 示例:请求列出当前目录中的所有文件 16 | 17 | . 18 | false 19 | ` 20 | } 21 | -------------------------------------------------------------------------------- /src/services/tree-sitter/queries/index.ts: -------------------------------------------------------------------------------- 1 | export { default as phpQuery } from "./php" 2 | export { default as typescriptQuery } from "./typescript" 3 | export { default as pythonQuery } from "./python" 4 | export { default as javascriptQuery } from "./javascript" 5 | export { default as javaQuery } from "./java" 6 | export { default as rustQuery } from "./rust" 7 | export { default as rubyQuery } from "./ruby" 8 | export { default as cppQuery } from "./cpp" 9 | export { default as cQuery } from "./c" 10 | export { default as csharpQuery } from "./c-sharp" 11 | export { default as goQuery } from "./go" 12 | export { default as swiftQuery } from "./swift" 13 | -------------------------------------------------------------------------------- /src/core/mode-validator.ts: -------------------------------------------------------------------------------- 1 | import { Mode, isToolAllowedForMode, getModeConfig, ModeConfig, FileRestrictionError } from "../shared/modes" 2 | import { ToolName } from "../shared/tool-groups" 3 | 4 | export { isToolAllowedForMode } 5 | export type { ToolName } 6 | 7 | export function validateToolUse( 8 | toolName: ToolName, 9 | mode: Mode, 10 | customModes?: ModeConfig[], 11 | toolRequirements?: Record, 12 | toolParams?: Record, 13 | ): void { 14 | if (!isToolAllowedForMode(toolName, mode, customModes ?? [], toolRequirements, toolParams)) { 15 | throw new Error(`Tool "${toolName}" is not allowed in ${mode} mode.`) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /webview-ui/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es5", 4 | "lib": ["dom", "dom.iterable", "esnext"], 5 | "allowJs": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "allowSyntheticDefaultImports": true, 9 | "strict": true, 10 | "forceConsistentCasingInFileNames": true, 11 | "noFallthroughCasesInSwitch": true, 12 | "module": "esnext", 13 | "moduleResolution": "node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "react-jsx", 18 | "baseUrl": ".", 19 | "paths": { 20 | "@/*": ["./src/*"] 21 | } 22 | }, 23 | "include": ["src", "../src/shared"] 24 | } 25 | -------------------------------------------------------------------------------- /src/core/prompts/tools/execute-command.ts: -------------------------------------------------------------------------------- 1 | import { ToolArgs } from "./types" 2 | 3 | export function getExecuteCommandDescription(args: ToolArgs): string | undefined { 4 | return `## execute_command 5 | Description: 请求在系统上执行CLI命令。当您需要执行系统操作或运行特定命令来完成用户任务中的任何步骤时,请使用此工具。您必须根据用户的系统定制命令,并清楚地解释命令的功能。对于命令链接,请使用适合用户shell的链接语法。相比创建可执行脚本,更推荐执行复杂的CLI命令,因为它们更灵活且更容易运行。命令将在当前工作目录执行:${args.cwd} 6 | Parameters: 7 | - command: (必需) 要执行的CLI命令。这应该是适用于当前操作系统的有效命令。确保命令格式正确且不包含任何有害指令。 8 | Usage: 9 | 10 | 在此处输入您的命令 11 | 12 | 13 | Example: 请求执行 npm run dev 14 | 15 | npm run dev 16 | ` 17 | } 18 | -------------------------------------------------------------------------------- /webview-ui/src/stories/Slider.stories.tsx: -------------------------------------------------------------------------------- 1 | import type { Meta, StoryObj } from "@storybook/react" 2 | 3 | import { Slider } from "@/components/ui" 4 | 5 | const meta: Meta = { 6 | title: "Primitives/Slider", 7 | component: Slider, 8 | parameters: { 9 | layout: "centered", 10 | }, 11 | args: { 12 | defaultValue: [50], 13 | max: 100, 14 | min: 0, 15 | step: 1, 16 | className: "w-[300px]", 17 | }, 18 | tags: ["autodocs"], 19 | } 20 | 21 | export default meta 22 | 23 | type Story = StoryObj 24 | 25 | export const Default: Story = { 26 | args: { 27 | defaultValue: [50], 28 | max: 100, 29 | min: 0, 30 | step: 1, 31 | }, 32 | } 33 | -------------------------------------------------------------------------------- /flake.lock: -------------------------------------------------------------------------------- 1 | { 2 | "nodes": { 3 | "nixpkgs": { 4 | "locked": { 5 | "lastModified": 1737569578, 6 | "narHash": "sha256-6qY0pk2QmUtBT9Mywdvif0i/CLVgpCjMUn6g9vB+f3M=", 7 | "owner": "nixos", 8 | "repo": "nixpkgs", 9 | "rev": "47addd76727f42d351590c905d9d1905ca895b82", 10 | "type": "github" 11 | }, 12 | "original": { 13 | "owner": "nixos", 14 | "ref": "nixos-24.11", 15 | "repo": "nixpkgs", 16 | "type": "github" 17 | } 18 | }, 19 | "root": { 20 | "inputs": { 21 | "nixpkgs": "nixpkgs" 22 | } 23 | } 24 | }, 25 | "root": "root", 26 | "version": 7 27 | } 28 | -------------------------------------------------------------------------------- /webview-ui/src/utils/format.ts: -------------------------------------------------------------------------------- 1 | export function formatLargeNumber(num: number): string { 2 | if (num >= 1e9) { 3 | return (num / 1e9).toFixed(1) + "b" 4 | } 5 | if (num >= 1e6) { 6 | return (num / 1e6).toFixed(1) + "m" 7 | } 8 | if (num >= 1e3) { 9 | return (num / 1e3).toFixed(1) + "k" 10 | } 11 | return num.toString() 12 | } 13 | 14 | export const formatDate = (timestamp: number) => { 15 | const date = new Date(timestamp) 16 | return date 17 | .toLocaleString("en-US", { 18 | month: "long", 19 | day: "numeric", 20 | hour: "numeric", 21 | minute: "2-digit", 22 | hour12: true, 23 | }) 24 | .replace(", ", " ") 25 | .replace(" at", ",") 26 | .toUpperCase() 27 | } 28 | -------------------------------------------------------------------------------- /src/__mocks__/@modelcontextprotocol/sdk/index.js: -------------------------------------------------------------------------------- 1 | const { Client } = require("./client/index.js") 2 | const { StdioClientTransport, StdioServerParameters } = require("./client/stdio.js") 3 | const { 4 | CallToolResultSchema, 5 | ListToolsResultSchema, 6 | ListResourcesResultSchema, 7 | ListResourceTemplatesResultSchema, 8 | ReadResourceResultSchema, 9 | ErrorCode, 10 | McpError, 11 | } = require("./types.js") 12 | 13 | module.exports = { 14 | Client, 15 | StdioClientTransport, 16 | StdioServerParameters, 17 | CallToolResultSchema, 18 | ListToolsResultSchema, 19 | ListResourcesResultSchema, 20 | ListResourceTemplatesResultSchema, 21 | ReadResourceResultSchema, 22 | ErrorCode, 23 | McpError, 24 | } 25 | -------------------------------------------------------------------------------- /src/core/prompts/tools/access-mcp-resource.ts: -------------------------------------------------------------------------------- 1 | import { ToolArgs } from "./types" 2 | 3 | export function getAccessMcpResourceDescription(args: ToolArgs): string | undefined { 4 | if (!args.mcpHub) { 5 | return undefined 6 | } 7 | return `## access_mcp_resource 8 | 描述:请求访问由已连接的MCP服务器提供的资源。资源代表可用作上下文的数据源,如文件、API响应或系统信息。 9 | 参数: 10 | - server_name:(必需)提供资源的MCP服务器名称 11 | - uri:(必需)用于标识要访问的特定资源的URI 12 | 使用方法: 13 | 14 | 在此填写服务器名称 15 | 在此填写资源URI 16 | 17 | 18 | 示例:请求访问MCP资源 19 | 20 | 21 | weather-server 22 | weather://san-francisco/current 23 | ` 24 | } 25 | -------------------------------------------------------------------------------- /src/shared/checkExistApiConfig.ts: -------------------------------------------------------------------------------- 1 | import { ApiConfiguration } from "../shared/api" 2 | 3 | export function checkExistKey(config: ApiConfiguration | undefined) { 4 | return config 5 | ? [ 6 | config.apiKey, 7 | config.glamaApiKey, 8 | config.openRouterApiKey, 9 | config.awsRegion, 10 | config.vertexProjectId, 11 | config.openAiApiKey, 12 | config.ollamaModelId, 13 | config.lmStudioModelId, 14 | config.geminiApiKey, 15 | config.openAiNativeApiKey, 16 | config.deepSeekApiKey, 17 | config.mistralApiKey, 18 | config.vsCodeLmModelSelector, 19 | config.requestyApiKey, 20 | config.unboundApiKey, 21 | ].some((key) => key !== undefined) 22 | : false 23 | } 24 | -------------------------------------------------------------------------------- /src/core/webview/getUri.ts: -------------------------------------------------------------------------------- 1 | import { Uri, Webview } from "vscode" 2 | /** 3 | * A helper function which will get the webview URI of a given file or resource. 4 | * 5 | * @remarks This URI can be used within a webview's HTML as a link to the 6 | * given file/resource. 7 | * 8 | * @param webview A reference to the extension webview 9 | * @param extensionUri The URI of the directory containing the extension 10 | * @param pathList An array of strings representing the path to a file/resource 11 | * @returns A URI pointing to the file/resource 12 | */ 13 | export function getUri(webview: Webview, extensionUri: Uri, pathList: string[]) { 14 | return webview.asWebviewUri(Uri.joinPath(extensionUri, ...pathList)) 15 | } 16 | -------------------------------------------------------------------------------- /.husky/pre-push: -------------------------------------------------------------------------------- 1 | branch="$(git rev-parse --abbrev-ref HEAD)" 2 | 3 | if [ "$branch" = "main" ]; then 4 | echo "You can't push directly to main - please check out a branch." 5 | exit 1 6 | fi 7 | 8 | npm run compile 9 | 10 | # Check for new changesets. 11 | NEW_CHANGESETS=$(find .changeset -name "*.md" ! -name "README.md" | wc -l | tr -d ' ') 12 | echo "Changeset files: $NEW_CHANGESETS" 13 | 14 | if [ "$NEW_CHANGESETS" == "0" ]; then 15 | echo "-------------------------------------------------------------------------------------" 16 | echo "Changes detected. Please run 'npm run changeset' to create a changeset if applicable." 17 | echo "-------------------------------------------------------------------------------------" 18 | fi 19 | -------------------------------------------------------------------------------- /e2e/src/runTest.ts: -------------------------------------------------------------------------------- 1 | import * as path from "path" 2 | 3 | import { runTests } from "@vscode/test-electron" 4 | 5 | async function main() { 6 | try { 7 | // The folder containing the Extension Manifest package.json 8 | // Passed to `--extensionDevelopmentPath` 9 | const extensionDevelopmentPath = path.resolve(__dirname, "../../") 10 | 11 | // The path to the extension test script 12 | // Passed to --extensionTestsPath 13 | const extensionTestsPath = path.resolve(__dirname, "./suite/index") 14 | 15 | // Download VS Code, unzip it and run the integration test 16 | await runTests({ extensionDevelopmentPath, extensionTestsPath }) 17 | } catch { 18 | console.error("Failed to run tests") 19 | process.exit(1) 20 | } 21 | } 22 | 23 | main() 24 | -------------------------------------------------------------------------------- /src/core/prompts/tools/search-files.ts: -------------------------------------------------------------------------------- 1 | import { ToolArgs } from "./types" 2 | 3 | export function getSearchFilesDescription(args: ToolArgs): string { 4 | return `## search_files 5 | 描述:请求在指定目录中执行正则表达式搜索,提供上下文丰富的结果。此工具在多个文件中搜索模式或特定内容,显示每个匹配项及其上下文。 6 | 参数: 7 | - path:(必需)要搜索的目录路径(相对于当前工作目录 ${args.cwd})。将递归搜索此目录。 8 | - regex:(必需)要搜索的正则表达式模式。使用 Rust 正则表达式语法。 9 | - file_pattern:(可选)用于过滤文件的 Glob 模式(例如,'*.ts' 表示 TypeScript 文件)。如果未提供,将搜索所有文件 (*)。 10 | 用法: 11 | 12 | 在此处填写目录路径 13 | 在此处填写正则表达式模式 14 | 在此处填写文件模式(可选) 15 | 16 | 17 | 示例:请求搜索当前目录中的所有 .ts 文件 18 | 19 | . 20 | .* 21 | *.ts 22 | ` 23 | } 24 | -------------------------------------------------------------------------------- /webview-ui/src/__mocks__/vscrui.ts: -------------------------------------------------------------------------------- 1 | import React from "react" 2 | 3 | export const Checkbox = ({ children, checked, onChange }: any) => 4 | React.createElement("div", { "data-testid": "mock-checkbox", onClick: onChange }, children) 5 | 6 | export const Dropdown = ({ children, value, onChange }: any) => 7 | React.createElement("div", { "data-testid": "mock-dropdown", onClick: onChange }, children) 8 | 9 | export const Pane = ({ children }: any) => React.createElement("div", { "data-testid": "mock-pane" }, children) 10 | 11 | export const Button = ({ children, ...props }: any) => 12 | React.createElement("div", { "data-testid": "mock-button", ...props }, children) 13 | 14 | export type DropdownOption = { 15 | label: string 16 | value: string 17 | } 18 | -------------------------------------------------------------------------------- /src/services/tree-sitter/queries/go.ts: -------------------------------------------------------------------------------- 1 | /* 2 | - function declarations (with associated comments) 3 | - method declarations (with associated comments) 4 | - type specifications 5 | */ 6 | export default ` 7 | ( 8 | (comment)* @doc 9 | . 10 | (function_declaration 11 | name: (identifier) @name.definition.function) @definition.function 12 | (#strip! @doc "^//\\s*") 13 | (#set-adjacent! @doc @definition.function) 14 | ) 15 | 16 | ( 17 | (comment)* @doc 18 | . 19 | (method_declaration 20 | name: (field_identifier) @name.definition.method) @definition.method 21 | (#strip! @doc "^//\\s*") 22 | (#set-adjacent! @doc @definition.method) 23 | ) 24 | 25 | (type_spec 26 | name: (type_identifier) @name.definition.type) @definition.type 27 | ` 28 | -------------------------------------------------------------------------------- /knip.json: -------------------------------------------------------------------------------- 1 | { 2 | "$schema": "https://unpkg.com/knip@latest/schema.json", 3 | "entry": ["src/extension.ts", "src/activate/index.ts", "webview-ui/src/index.tsx"], 4 | "project": ["src/**/*.ts", "webview-ui/src/**/*.{ts,tsx}"], 5 | "ignore": [ 6 | "**/__mocks__/**", 7 | "**/__tests__/**", 8 | "**/test/**", 9 | "**/*.test.ts", 10 | "**/*.test.tsx", 11 | "**/stories/**", 12 | "coverage/**", 13 | "dist/**", 14 | "out/**", 15 | "bin/**", 16 | "src/activate/**", 17 | "src/exports/**", 18 | "src/extension.ts", 19 | "e2e/.vscode-test.mjs", 20 | "e2e/src/runTest.ts", 21 | "e2e/src/suite/index.ts" 22 | ], 23 | "workspaces": { 24 | "webview-ui": { 25 | "entry": ["src/index.tsx"], 26 | "project": ["src/**/*.{ts,tsx}"] 27 | } 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/utils/logging/index.ts: -------------------------------------------------------------------------------- 1 | /** 2 | * @fileoverview Main entry point for the compact logging system 3 | * Provides a default logger instance with Jest environment detection 4 | */ 5 | 6 | import { CompactLogger } from "./CompactLogger" 7 | 8 | /** 9 | * No-operation logger implementation for production environments 10 | */ 11 | const noopLogger = { 12 | debug: () => {}, 13 | info: () => {}, 14 | warn: () => {}, 15 | error: () => {}, 16 | fatal: () => {}, 17 | child: () => noopLogger, 18 | close: () => {}, 19 | } 20 | 21 | /** 22 | * Default logger instance 23 | * Uses CompactLogger for normal operation, switches to noop logger in Jest test environment 24 | */ 25 | export const logger = process.env.JEST_WORKER_ID !== undefined ? new CompactLogger() : noopLogger 26 | -------------------------------------------------------------------------------- /flake.nix: -------------------------------------------------------------------------------- 1 | { 2 | description = "Roo Code development environment"; 3 | 4 | inputs = { 5 | nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11"; 6 | }; 7 | 8 | outputs = { self, nixpkgs, ... }: let 9 | systems = [ "aarch64-darwin" "x86_64-linux" ]; 10 | 11 | forAllSystems = nixpkgs.lib.genAttrs systems; 12 | 13 | mkDevShell = system: let 14 | pkgs = import nixpkgs { inherit system; }; 15 | in pkgs.mkShell { 16 | name = "roo-code"; 17 | 18 | packages = with pkgs; [ 19 | zsh 20 | nodejs_18 21 | corepack_18 22 | ]; 23 | 24 | shellHook = '' 25 | exec zsh 26 | ''; 27 | }; 28 | in { 29 | devShells = forAllSystems (system: { 30 | default = mkDevShell system; 31 | }); 32 | }; 33 | } 34 | -------------------------------------------------------------------------------- /webview-ui/src/setupTests.ts: -------------------------------------------------------------------------------- 1 | import "@testing-library/jest-dom" 2 | 3 | // Mock crypto.getRandomValues 4 | Object.defineProperty(window, "crypto", { 5 | value: { 6 | getRandomValues: function (buffer: Uint8Array) { 7 | for (let i = 0; i < buffer.length; i++) { 8 | buffer[i] = Math.floor(Math.random() * 256) 9 | } 10 | return buffer 11 | }, 12 | }, 13 | }) 14 | 15 | // Mock matchMedia 16 | Object.defineProperty(window, "matchMedia", { 17 | writable: true, 18 | value: jest.fn().mockImplementation((query) => ({ 19 | matches: false, 20 | media: query, 21 | onchange: null, 22 | addListener: jest.fn(), // deprecated 23 | removeListener: jest.fn(), // deprecated 24 | addEventListener: jest.fn(), 25 | removeEventListener: jest.fn(), 26 | dispatchEvent: jest.fn(), 27 | })), 28 | }) 29 | -------------------------------------------------------------------------------- /webview-ui/src/components/ui/textarea.tsx: -------------------------------------------------------------------------------- 1 | import * as React from "react" 2 | 3 | import { cn } from "@/lib/utils" 4 | 5 | const Textarea = React.forwardRef>( 6 | ({ className, ...props }, ref) => { 7 | return ( 8 |