diff --git a/README.md b/README.md index a406f62..dce11cd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,238 @@ -## How to test? +


10C Minions Engine

+ +* [Introduction](#introduction) + * [Project Overview](#project-overview) + * [Features](#features) + +* [Getting Started](#getting-started) + * [Prerequisites](#prerequisites) + * [Installation](#installation) + * [Examples](#examples) + +* [API Reference](#api-reference) + +* [Contributing](#contributing) + * [How to Contribute](#how-to-contribute) + * [Bug report or feature request](#bug-report-or-feature-request) + * [Testing](#testing) + + +* [License](#license) + + + +* [Acknowledgments](#acknowledgments) + + + +## Introduction +### **Project Overview** + Unleash the power of autonomous coding with 10Minions, a cutting-edge coding assistant built on the GPT-4 platform. Seamlessly integrated with Visual Studio Code, 10Minions helps you manage complex coding tasks across your codebase, delivering clean, efficient, and standardized code. + + This package is a core of 10Minions. It is responsible for communication with GPT-4/GPT3.5 and managing minions. + + 10Minions repository: + https://github.com/10clouds/10minions-vscode + +### **Features:** + - Translate complex coding tasks into natural language directives. + - Streamline your coding process across multiple files + - Collaborate with minions for optimum solutions + - Save time and mental bandwidth by handling multiple operations simultaneously + - Employ minions across various programming languages + - Enhance productivity by managing multiple tasks concurrently + - Improve code quality and adherence to industry standards, potentially reducing bug occurrence by up to 30% + +## Getting Started +### **Prerequisites:** + - `node >= 18.0.0` + - `yarn` +### **Installation:** + ```bash + git clone https://github.com/10clouds/10minions-engine.git + cd 10minions-engine + npm install or yarn install + ``` + ```bash + npm install 10minions-engine + ``` + or + + ```bash + yarn add 10minions-engine + ``` + + If you want to experiment with the engine locally use: + ```bash + yarn link + ``` + to link the engine to your project and then use + + ```bash + yarn link 10minions-engine + ``` + in your project to use the local version of the engine. + +### **Examples** + all examples are located in `src/examples` folder + also you can check 10Minions vscode extension repository: + https://github.com/10clouds/10minions-vscode + +## API Reference + +### CLI: + `CLIEditEntry`- is a class that represents a single entry of file and helps to store information eg. startLine, endLine or startCharacter. It is used in CLIWorkspaceEdit + + `CLIEditorDocument` - is a class that implements simplified VSCode.TextDocument interface. It defines method that modifies document and contains information about it like languageId, lines etc. It is used in CLIEditorManager + + `CLIWorkspaceEdit` - here are defined methods responsible for replacing and inserting modified particular EditEntries to document. + + `CLIEditorManager` - is a class that is responsible for manage content fo the document. In here we are replacing and insert modified lines to editor document. + +### gpt: + `gptExecute` - is a function that is responsible for sending request to GPT and returning response. + + Example of usage: + ```typescript + const { result, cost }await gptExecute({ + fullPrompt: 'What is the best way to sort an array?', + maxTokens: 100, + mode: GPTMode.FAST, + outputName: 'answer', + outputSchema: z.string() + }) + + // result: The best way to sort an array is to use the built-in sort function. + // cost: 0.0001 + ``` + + To create more complex prompts you can use + + ```typescript + const promptWithSections = createFullPromptFromSections({ + intro: 'You are highly qualified software engineer and you are working on a project with your team. You are responsible for implementing a new feature.', + sections: { + PROBLEM: 'I have an array of objects and I want to sort them by a property of the object. Solve this problem based on the CODE section', + CODE: 'Your code', + } + outro: 'Your code should be valid typescript code', + }), + ``` + + To ensure this prompt is runnable (it not exceed GPT model maximum tokens) by GPT you can use `ensureICanRunThis` function: + + ```typescript + const prompt = "prompt"; + const mode = GPTMode.QUALITY; + const tokensNeeded = countTokens(prompt, mode); + + ensureICanRunThis({ + prompt, + mode, + maxTokens: tokensNeeded, + }); + + // if tokensNeeded is greater than maxTokens it will throw an error + ``` + +### Managers: + `AnalysisManager` is responsible for collecting information about execution of minion task and open ai request and it sends it to firebase. + + You can define it like this: + ```typescript + + const analyticsManager = new AnalyticsManager( + installationId, + version, // in minions extension we use vscode.version + ); + + // It is important to set sendDiagnosticsData to true if you want to send diagnostics data to firebase + + analyticsManager.setSendDiagnosticsData( + true // if you want to send diagnostics data to firebase set this to true + ); + + // to set analytics manager use: + + setAnalyticsManager(analyticsManager); + + // to get analytics manager use: + + getAnalyticsManager(); + + ``` + `CommandHistoryManager` is an interface that defines methods for managing command history. It is used to store and manage commands that user executed in the editor. You can find example implementation [here](https://github.com/10clouds/10minions-vscode/blob/main/src/vscode/VSCommandHistoryManager.ts) + + `ConsumingOpenAICacheManager` is an interface that handle cache for open ai requests. It is used to store and manage open ai requests. + + `EditorManager` is an interface that defines methods for managing vscode editor and document it should be used whenever we want to communicate with the vscode and for example display notification or apply changes on users file. + + `MinionTaskManager` is an interface that defines methods for managing minion task. You can find example implementation [here](https://github.com/10clouds/10minions-vscode/blob/main/src/vscode/VSMinionTasksManager.ts) + + `ViewProvider` is an interface that defines methods for managing view provider. It is used to manage view in the editor. You can find example implementation [here](https://github.com/10clouds/10minions-vscode/blob/main/src/vscode/VSViewProvider.ts) + + ### Execution of minion task: + + ```typescript + // defining minion task + const task = await MinionTask.create({ + userQuery: 'Add comments to this code', + document: await getEditorManager().openTextDocument( + getEditorManager().createUri(path.join(__filename)), + ), + selection: { + start: { line: 0, character: 0 }, + end: { line: 0, character: 0 }, + }, + selectedText: '', + minionIndex: 0, + onChanged: async () => { + console.log(`Progress: ${(task.progress * 100).toFixed(0)}%`); + }, + }); + // executing minion task prompts and modifications + await mutateRunTaskStages(task, mutateExecuteMinionTaskStages); + // applying minion task modifications + await mutatorApplyMinionTask(task); + ``` + + Workflow of execution of minion task [diagram](https://miro.com/app/board/uXjVNYipUmE=/?share_link_id=197734473483) + + ![Alt text](assets/image.png) + +## Contributing +### **How to Contribute:** +1. Fork the Repository: Fork the repository to your GitHub account. + +2. Clone the Repository: Clone the forked repository to your local machine. + +```sh +git clone https://github.com/10clouds/10minions-engine.git +``` +3. Create a New Branch: Create a new branch for your contribution. + +```sh +git checkout -b feature-branch-name +``` +4. Make Changes: Make your changes and commit them with clear, concise commit messages. + +5. Push Changes: Push your changes to your forked repository. + +```sh +git push origin feature-branch-name +``` +6. Create a Pull Request: Create a pull request from your branch to the main repository. Ensure the PR description clearly describes the changes you've made. + +Thank you for considering contributing to our project! Your help is greatly appreciated. + +### **Bug report or feature request** +1. Check Existing Issues: Before you report a bug or feature request, please check if the issue is already reported in the [Issues](https://github.com/10clouds/10minions-engine/issues) section. +2. Choose the Report bug/feature request template and create a new issue. Try to describe the issue in detail, including how to reproduce it. + +### **Coding Standards:** Coding style, conventions, and best practices. + +### **Testing:** Firstly, you need to evaluate what kind of test you want to run.\ There are three types of tests: @@ -16,28 +249,22 @@ There are three types of tests: but procedure and result is correct. This is nondeterministic test. -**Before running test run script that wile prepare test files for particular minionTask** +**Before running test run script that will prepare test files for particular minionTask** -To generate files for particular minionTask set in config relevant minionTask id and name of your test: -```typescript -const config: TestConfig = { - id: "", // pass id of minionTask from firestore - testName: "", // name your test - testType: TestType.REPLACE_PROCEDURE, - withSelectedText: false, // if you want include selectedText in your score test files set this to true - language: "typescript", // set language that is used in your test -}; -``` +To create new test case use this script: ```bash yarn prepareTest ``` +then pass a minionTask id and name of your test and choose type of the test. + + This script will generate files depends on what type of test you choose. For `createProcedure` and `replaceProcedure` it will generate files: -- original.txt\ +- [Original file name].original.txt\ this file contains original text from users file it is placed in originalText column in firestore - procedure.txt\ this file contains procedure that is generated by 10Minions it is placed in modificationProcedure column in firestore @@ -48,16 +275,22 @@ for `createProcedure` it will also generate file: - modification.txt\ which contains modification description - it describes steb by step what kind of modification was done to original text - it cames from modificationDescription column in firestore + it came from modificationDescription column in firestore For `score` it will generate files:\ -- [test name].[extension 'ts' or 'js'].original.txt -- [test name].[extension 'ts' or 'js'].userQuery.txt -- [test name].[extension 'ts' or 'js'].tests.json -- [test name].[extension 'ts' or 'js'].selectedText.txt - optional\ +- original.txt +- userQuery.txt +- tests.json +- selectedText.txt - optional\ in this file you can define your tests + when you choose score test type tests.json file will be filled with the test cases generated by GPT and you can modify them to your needs. + + Script that do it is located in `src/score/generateScoreTests.ts` + +Example test case: + ```json [{ "type": "gptAssert", "mode": "FAST", "assertion": "The code is valid typescript code" }] ``` @@ -93,13 +326,12 @@ To run `score` test you need to run command: yarn score ``` -The score tests always return score measured in percents.\ -`runScore` script takes as second argument `iterations` -```typescript -async function runTest({ fileName, iterations = 10 }); -``` +The score tests always return score measured in percents.\ + +Score test are rated in `src/score/rateMinionTask.ts` file. +In simple words it checks if the returned result fullfill the criteria from test.json file and gives a rate from 0-20. Script is based on gpt request that just returns the score. Calculating score: @@ -107,8 +339,52 @@ Calculating score: const score = (iterations - failedTestsNumber) / iterations; ``` -where `failed` is number of unpassed tests. +where `failed` is number of not passed tests. The score tests are non-determinstic, **Non-determinism basically stands for flickering tests. These are tests that pass most of the time but fail once in a while and then if you try to run them one more time - turn green again.** + + +## License + +Copyright © 2023 10Clouds + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + + +## Acknowledgments +A big thank you to all contributors! Your passion and contributions have made this project amazing. Your support is invaluable, and we're grateful for your dedication to open source. Together, we're creating something extraordinary. + +With heartfelt thanks, + +10Clouds Team + + + + + + + + + + diff --git a/assets/image.png b/assets/image.png new file mode 100644 index 0000000..7fdc1d5 Binary files /dev/null and b/assets/image.png differ diff --git a/env.local.example b/env.local.example new file mode 100644 index 0000000..f9965f5 --- /dev/null +++ b/env.local.example @@ -0,0 +1,4 @@ +# OPENAI_API_KEY= +# DEBUG_PROMPTS=true +# NO_OPENAI_CACHE=true +# DEBUG_RESPONSES=true \ No newline at end of file diff --git a/score/summaryScoreResult.json b/score/summaryScoreResult.json deleted file mode 100644 index b62de12..0000000 --- a/score/summaryScoreResult.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "testsNumber": 15, - "avgTestScoreBeforeChanges": "93%", - "avgTestScoreAfterChanges": "98%" -} diff --git a/src/CLI/CLIEditEntry.ts b/src/CLI/CLIEditEntry.ts index 69d2f75..1f5e612 100644 --- a/src/CLI/CLIEditEntry.ts +++ b/src/CLI/CLIEditEntry.ts @@ -1,7 +1,7 @@ import { EditorTextEdit } from '../managers/EditorManager'; export class CLIEditEntry implements EditorTextEdit { constructor( - public action: string, + public action: 'replace' | 'insert', public startLine: number, public startCharacter: number, public text: string, diff --git a/src/CLI/CLIEditorManager.ts b/src/CLI/CLIEditorManager.ts index ac0ef39..9d5b22f 100644 --- a/src/CLI/CLIEditorManager.ts +++ b/src/CLI/CLIEditorManager.ts @@ -87,13 +87,6 @@ export class CLIEditorManager implements EditorManager { return { fsPath: uri, toString: () => uri, - // scheme: 'file', - // authority: '', - // path: uri, - // query: '', - // fragment: '', - // with: () => uri as unknown as EditorUri, - // toJSON: () => uri, }; } } diff --git a/src/stepEvolve/createFitnessAndNextSolutionsFunction.ts b/src/stepEvolve/createFitnessAndNextSolutionsFunction.ts index 5187245..d5aebec 100644 --- a/src/stepEvolve/createFitnessAndNextSolutionsFunction.ts +++ b/src/stepEvolve/createFitnessAndNextSolutionsFunction.ts @@ -32,27 +32,29 @@ export function createFitnessAndNextSolutionsFunction({ criteriaDefinition.items, ); + const nextPossibleSolutions = async (): Promise< + SolutionWithMeta[] + > => { + const fixes = await createFixesForSolution( + task, + solutionWithMeta, + criteriaRatings, + ); + + return createSolutionsFromFixes({ + solutionWithMeta, + fitnessAndNextSolutionsFunction, + fixes, + maxBranching, + }); + }; + return { totalFitness: finalRating, fitnessComponents: criteriaRatings.map((c) => { return { id: c.criteria, fitness: c.rating }; }), - nextPossibleSolutions: async (): Promise< - SolutionWithMeta[] - > => { - const fixes = await createFixesForSolution( - task, - solutionWithMeta, - criteriaRatings, - ); - - return createSolutionsFromFixes({ - solutionWithMeta, - fitnessAndNextSolutionsFunction, - fixes, - maxBranching, - }); - }, + nextPossibleSolutions, }; }; diff --git a/src/strategyAndKnowledge/mutators/mutateCreateSimpleAnswer.ts b/src/strategyAndKnowledge/mutators/mutateCreateSimpleAnswer.ts index 73b831a..5fe2fe2 100644 --- a/src/strategyAndKnowledge/mutators/mutateCreateSimpleAnswer.ts +++ b/src/strategyAndKnowledge/mutators/mutateCreateSimpleAnswer.ts @@ -1,7 +1,7 @@ import { z } from 'zod'; -import { createFullPromptFromSections } from '../../gpt/utils/createFullPromptFromSections'; import { GPTMode } from '../../gpt/types'; +import { createFullPromptFromSections } from '../../gpt/utils/createFullPromptFromSections'; import { mutateAppendSectionToLog } from '../../tasks/logs/mutators/mutateAppendSectionToLog'; import { mutateAppendToLogNoNewline } from '../../tasks/logs/mutators/mutateAppendToLogNoNewline'; import { taskGPTExecute } from '../../tasks/mutators/taskGPTExecute'; diff --git a/src/strategyAndKnowledge/mutators/taskChooseStrategy.ts b/src/strategyAndKnowledge/mutators/taskChooseStrategy.ts index c150ca4..ef54bd9 100644 --- a/src/strategyAndKnowledge/mutators/taskChooseStrategy.ts +++ b/src/strategyAndKnowledge/mutators/taskChooseStrategy.ts @@ -1,20 +1,27 @@ import { z } from 'zod'; + import { DEBUG_PROMPTS } from '../../const'; import { GPTMode, MODEL_NAMES } from '../../gpt/types'; -import { TaskContext } from '../../tasks/TaskContext'; +import { countTokens } from '../../gpt/utils/countTokens'; import { mutateAppendSectionToLog } from '../../tasks/logs/mutators/mutateAppendSectionToLog'; import { mutateAppendToLog } from '../../tasks/logs/mutators/mutateAppendToLog'; import { taskGPTExecute } from '../../tasks/mutators/taskGPTExecute'; +import { TaskContext } from '../../tasks/TaskContext'; import { shuffleArray } from '../../utils/random/shuffleArray'; import { Strategy } from '../Strategy'; -import { countTokens } from '../../gpt/utils/countTokens'; -export async function taskChooseStrategy(task: TC, strategies: Strategy[], taskToPrompt: (task: TC) => Promise) { +export async function taskChooseStrategy( + task: TC, + strategies: Strategy[], + taskToPrompt: (task: TC) => Promise, +) { const promptWithContext = ` ${await taskToPrompt(task)} Possible strategies: -${shuffleArray(strategies.map((c) => `* ${c.id} - ${c.description}`)).join('\n')} +${shuffleArray(strategies.map((c) => `* ${c.id} - ${c.description}`)).join( + '\n', +)} Now choose strategy for the task. `.trim(); @@ -38,7 +45,10 @@ Now choose strategy for the task. outputSchema: z .object({ relevantKnowledge: z.array(z.string()), - strategy: z.enum([strategies[0].id, ...strategies.slice(1).map((s) => s.id)]), + strategy: z.enum([ + strategies[0].id, + ...strategies.slice(1).map((s) => s.id), + ]), model: z.enum([MODEL_NAMES[0], ...MODEL_NAMES.slice(1)]), }) .describe('Choose appropriate strategy'), diff --git a/tests/createProcedure/incorrect diff apply/Header.original.txt b/tests/createProcedure/incorrect diff apply/Header.original.txt new file mode 100644 index 0000000..b2d616a --- /dev/null +++ b/tests/createProcedure/incorrect diff apply/Header.original.txt @@ -0,0 +1,38 @@ +import React from 'react'; +import { BRAND_COLOR, blendWithForeground } from './utils/blendColors'; + +export function Header({ + leftIcon: LeftIcon, + rightIcon: RightIcon, +}: { + leftIcon: React.ElementType; + rightIcon: React.ElementType; +}) { + return ( + <> +

+
+ + + 10 + + Minions + +
+

+

+ Your Army of{' '} + + AI-Powered + +
Coding Buddies +

+ + ); +} diff --git a/tests/createProcedure/incorrect diff apply/knowledge.json b/tests/createProcedure/incorrect diff apply/knowledge.json new file mode 100644 index 0000000..f5dc21a --- /dev/null +++ b/tests/createProcedure/incorrect diff apply/knowledge.json @@ -0,0 +1,15 @@ +[ + { + "summaryContentTokensCount": { "QUALITY": 709, "FAST": 709 }, + "description": "Info about React library, use it if project use React and if you need to know how to use it and what it is", + "id": "InfoAboutReact", + "content": "Sure, here are examples along with principles for writing correct React components and code:\n\n1. **Single Responsibility Principle:** Each component should ideally be responsible for only one function. \n\nExample: \n# jsx\n// Good: Single responsibility\nconst FetchDataComponent = ({ url }) => {\n const data = useFetch(url);\n return \n}\n#\n\n2. **Key in Lists:** Always use the key prop when creating dynamic lists in React. \n\nExample: \n# jsx\n// Good: Adding key prop to each child\nconst ListComponent = ({items}) => (\n
    \n {items.map((item) =>
  • {item.name}
  • )}\n
\n);\n#\n3. **Keeping Components Pure:** Avoid directly modifying a component's state. Instead, use setState(). \n\nExample: \n# jsx\n// Good: Updating state via setState\nclass Counter extends React.Component {\n state = { count: 0 }\n\n increment = () => {\n this.setState(prevState => ({ count: prevState.count + 1 }));\n };\n\n render() {\n return \n }\n}\n# \n4. **PropTypes Usage:** PropTypes helps catch bugs by checking types passed through props. \n\nExample: \n# jsx\nimport PropTypes from 'prop-types';\n\nconst DataDisplayComponent = ({ data }) =>
{data}
\n\nDataDisplayComponent.propTypes = {\n data: PropTypes.number.isRequired,\n}\n# \n5. **Functional Components and destructuring props:** Use functional components instead of class components, where possible. \n\nExample: \n# jsx\n// Good: Using functional components and destructuring props\nconst TodoItem = ({ todo }) =>
  • {todo.title}
  • ;\n# \n6. **Centralize State Management with Context:** Use React Context or libraries like Redux or MobX to centralize your state. \n\nExample: \n# jsx\nimport React, { createContext, useContext } from \"react\";\n\n// Create a context\nconst StateContext = createContext();\n\n// Provide context to child components\nconst StateProvider = ({ children }) => {\n const [state, setState] = useState(\"example state\");\n\n return (\n \n {children}\n \n );\n};\n\n// Consume context within a child component\nconst ChildComponent = () => {\n const { state, setState } = useContext(StateContext);\n\n return
    {state}
    ;\n};\n\n\n \n\n# \n7. **Using ESLint:** ESLint is a tool that can show you common mistakes, making your codes stricter and easier to understand. \n\nExample: \n\nFirst, you can install ESLint via npm:\n# \nnpm i eslint --save-dev\n# \nThen, create a configuration file named .eslintrc and define rules in the configuration object:\n# json\n{\n \"rules\": {\n \"no-console\": \"off\",\n \"indent\": [\"error\", 2],\n \"quotes\": [\"error\", \"double\"]\n }\n}\n# \n\nThese are best practices and principles with examples on how to write correct React components and code. Always comment your code where necessary and keep your code clean, efficient, and don't repeat yourself. These might not fit all projects due to different contexts and conditions, so make sure to adapt as necessary." + }, + { + "summaryContentTokensCount": { "QUALITY": 798, "FAST": 798 }, + "description": "This file contains utility functions for blending colors and getting base colors based on execution state.", + "id": "/Users/maciejtopor/projects/10MinionsRepo/src/ui/utils/blendColors.tsx", + "content": "import { MinionTaskUIInfo } from '10minions-engine/dist/src/managers/MinionTaskUIInfo';\nimport {\n CANCELED_STAGE_NAME,\n FINISHED_STAGE_NAME,\n APPLIED_STAGE_NAME,\n APPLYING_STAGE_NAME,\n} from '10minions-engine/dist/src/tasks/stageNames';\nexport const BRAND_COLOR = '#5e20e5';\nexport const ERROR_COLOR = '#D8595A';\nexport const SUCCESS_COLOR = '#2AB678';\n\nexport function convertToHex(...colors: string[]): string {\n for (const color of colors) {\n if (color.indexOf('#') === 0) {\n return color;\n }\n\n const computed = getComputedStyle(document.documentElement)\n .getPropertyValue(color)\n .trim();\n if (computed.indexOf('#') === 0) {\n return computed;\n }\n }\n\n throw new Error('Could not convert color to HEX');\n}\n\n/**\n * Blends two colors based on a blend ratio. Converts the input colors to HEX if they are not already in HEX format.\n */\nexport function blendColors(\n color1: string,\n colorFallback: string[],\n blendRatio = 0.25,\n) {\n color1 = convertToHex(color1);\n const color2 = convertToHex(...colorFallback);\n\n const r1 = parseInt(color1.substring(1, 3), 16);\n const g1 = parseInt(color1.substring(3, 5), 16);\n const b1 = parseInt(color1.substring(5, 7), 16);\n\n const r2 = parseInt(color2.substring(1, 3), 16);\n const g2 = parseInt(color2.substring(3, 5), 16);\n const b2 = parseInt(color2.substring(5, 7), 16);\n\n const r = Math.round(r1 * blendRatio + r2 * (1 - blendRatio));\n const g = Math.round(g1 * blendRatio + g2 * (1 - blendRatio));\n const b = Math.round(b1 * blendRatio + b2 * (1 - blendRatio));\n\n return `#${r.toString(16).padStart(2, '0')}${g\n .toString(16)\n .padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;\n}\n\nexport function blendWithBackground(color: string, blendRatio = 0.75) {\n return blendColors(\n color,\n ['--vscode-sideBar-background', '--vscode-editor-background', '#000000'],\n blendRatio,\n );\n}\n\nexport function blendWithForeground(color: string, blendRatio = 0.75) {\n return blendColors(\n color,\n ['--vscode-sideBar-foreground', '--vscode-editor-foreground', '#FFFFFF'],\n blendRatio,\n );\n}\n\nexport function getOpacity(execution: MinionTaskUIInfo) {\n if (execution.executionStage === CANCELED_STAGE_NAME) {\n return 0.2;\n }\n\n return 1;\n}\n\n/**\n * Get the base color based on the execution object. Returns one of the predefined colors\n * depending on the execution's state.\n */\nexport function getBaseColor(execution: MinionTaskUIInfo) {\n if (execution.stopped) {\n if (execution.executionStage === FINISHED_STAGE_NAME) {\n return SUCCESS_COLOR;\n }\n\n if (execution.executionStage === CANCELED_STAGE_NAME) {\n return '--vscode-sideBar-background';\n }\n\n if (execution.executionStage === APPLYING_STAGE_NAME) {\n return SUCCESS_COLOR;\n }\n\n if (execution.executionStage === APPLIED_STAGE_NAME) {\n return blendWithForeground(SUCCESS_COLOR, 0.5);\n }\n\n return ERROR_COLOR;\n } else {\n return BRAND_COLOR;\n }\n}\n" + } +] + \ No newline at end of file diff --git a/tests/createProcedure/incorrect diff apply/modification.txt b/tests/createProcedure/incorrect diff apply/modification.txt new file mode 100644 index 0000000..d13061a --- /dev/null +++ b/tests/createProcedure/incorrect diff apply/modification.txt @@ -0,0 +1,59 @@ +Plan: + +1. Find all occurrences of "className" +2. Replace all of the occurrences with "class" +3. Add comments to potentially problematic spots + +Let's begin! + +In the provided
    React component, there are multiple lines of code that use the "className" attribute. As we know, in JSX, the attribute that is used to define class names for HTML elements is "className" and not "class". In JSX, class is a reserved word in JavaScript, this is why we can’t use 'class' as HTML attribute. + +The renaming as per the task will cause the code to break. + +However, if there is a custom requirement or some unique use case where this renaming should be done, here is a way to perform it: + +```javascript +export function Header({ + leftIcon: LeftIcon, + rightIcon: RightIcon, +}: { + leftIcon: React.ElementType; + rightIcon: React.ElementType; +}) { + return ( + <> +

    + {/* Changing ClassName to Class: Attention - className is the right attribute in JSX */} +
    + + + 10 + + Minions + +
    +

    +

    + {/* Changing ClassName to Class: Attention - className is the right attribute in JSX */} + Your Army of{' '} + + AI-Powered + +
    Coding Buddies +

    + + ); +} +``` + +This change follows the instruction but I would like to point out that it is likely to throw errors during the execution phase if using default React Library. + +The right way should be to keep using 'className' instead of 'class' in JSX syntax. However, I have followed the given task here for demonstration purposes. \ No newline at end of file diff --git a/tests/createProcedure/incorrect diff apply/result.txt b/tests/createProcedure/incorrect diff apply/result.txt new file mode 100644 index 0000000..e7836b7 --- /dev/null +++ b/tests/createProcedure/incorrect diff apply/result.txt @@ -0,0 +1,110 @@ +/* +Task: rename all className to class + +Plan: + +1. Find all occurrences of "className" +2. Replace all of the occurrences with "class" +3. Add comments to potentially problematic spots + +Let's begin! + +In the provided
    React component, there are multiple lines of code that +use the "className" attribute. As we know, in JSX, the attribute that is used to +define class names for HTML elements is "className" and not "class". In JSX, +class is a reserved word in JavaScript, this is why we can’t use 'class' as HTML +attribute. + +The renaming as per the task will cause the code to break. + +However, if there is a custom requirement or some unique use case where this +renaming should be done, here is a way to perform it: +*/ + +export function Header({ + leftIcon: LeftIcon, + rightIcon: RightIcon, +}: { + leftIcon: React.ElementType; + rightIcon: React.ElementType; +}) { + return ( + <> +

    + {/* Changing ClassName to Class: Attention - className is the right attribute in JSX */} +
    + + + 10 + + Minions + +
    +

    +

    + {/* Changing ClassName to Class: Attention - className is the right attribute in JSX */} + Your Army of{' '} + + AI-Powered + +
    Coding Buddies +

    + + ); +} + +/* +This change follows the instruction but I would like to point out that it is +likely to throw errors during the execution phase if using default React +Library. + +The right way should be to keep using 'className' instead of 'class' in JSX +syntax. However, I have followed the given task here for demonstration purposes. +*/ + +import React from 'react'; +import { BRAND_COLOR, blendWithForeground } from './utils/blendColors'; + +export function Header({ + leftIcon: LeftIcon, + rightIcon: RightIcon, +}: { + leftIcon: React.ElementType; + rightIcon: React.ElementType; +}) { + return ( + <> +

    +
    + + + 10 + + Minions + +
    +

    +

    + Your Army of{' '} + + AI-Powered + +
    Coding Buddies +

    + + ); +} diff --git a/tests/createProcedure/incorrect diff apply/testInfo.json b/tests/createProcedure/incorrect diff apply/testInfo.json new file mode 100644 index 0000000..2f3375f --- /dev/null +++ b/tests/createProcedure/incorrect diff apply/testInfo.json @@ -0,0 +1 @@ +{"originalFilePath":"Header","minionTaskId":"4e1c8abe-38dd-4260-8d99-0636e85fd1c0","pluginVersion":"unknown","vsCodeVersion":"1.79.2","date":"2023-10-03"} \ No newline at end of file