diff --git a/apps/open-swe/src/graphs/programmer/nodes/open-pr.ts b/apps/open-swe/src/graphs/programmer/nodes/open-pr.ts index 9005af2c..32386978 100644 --- a/apps/open-swe/src/graphs/programmer/nodes/open-pr.ts +++ b/apps/open-swe/src/graphs/programmer/nodes/open-pr.ts @@ -1,5 +1,6 @@ import { v4 as uuidv4 } from "uuid"; import { + CustomRules, GraphConfig, GraphState, GraphUpdate, @@ -54,16 +55,32 @@ Here are all of the tasks you completed: {USER_REQUEST_PROMPT} +{CUSTOM_RULES} + With all of this in mind, please use the \`open_pr\` tool to open a pull request.`; +const formatCustomRulesPrompt = (pullRequestFormatting: string): string => { + return ` +The user has provided the following custom rules around how to format the contents of the pull request. +IMPORTANT: You must follow these instructions exactly when generating the pull request contents. Do not deviate from them in any way. + +${pullRequestFormatting} +`; +}; + const formatPrompt = ( taskPlan: PlanItem[], messages: BaseMessage[], + customRules?: CustomRules, ): string => { const completedTasks = taskPlan.filter((task) => task.completed); + const customPrFormattingRules = customRules?.pullRequestFormatting + ? formatCustomRulesPrompt(customRules.pullRequestFormatting) + : ""; return openPrSysPrompt .replace("{COMPLETED_TASKS}", formatPlanPromptWithSummaries(completedTasks)) - .replace("{USER_REQUEST_PROMPT}", formatUserRequestPrompt(messages)); + .replace("{USER_REQUEST_PROMPT}", formatUserRequestPrompt(messages)) + .replace("{CUSTOM_RULES}", customPrFormattingRules); }; export async function openPullRequest( diff --git a/apps/open-swe/src/utils/custom-rules.ts b/apps/open-swe/src/utils/custom-rules.ts index 46bff3b6..37f80f76 100644 --- a/apps/open-swe/src/utils/custom-rules.ts +++ b/apps/open-swe/src/utils/custom-rules.ts @@ -15,6 +15,8 @@ const DEPENDENCIES_AND_INSTALLATION_CLOSE_TAG = ""; const TESTING_INSTRUCTIONS_OPEN_TAG = ""; const TESTING_INSTRUCTIONS_CLOSE_TAG = ""; +const PULL_REQUEST_FORMATTING_OPEN_TAG = ""; +const PULL_REQUEST_FORMATTING_CLOSE_TAG = ""; const ALL_TAGS = [ GENERAL_RULES_OPEN_TAG, GENERAL_RULES_CLOSE_TAG, @@ -24,6 +26,8 @@ const ALL_TAGS = [ DEPENDENCIES_AND_INSTALLATION_CLOSE_TAG, TESTING_INSTRUCTIONS_OPEN_TAG, TESTING_INSTRUCTIONS_CLOSE_TAG, + PULL_REQUEST_FORMATTING_OPEN_TAG, + PULL_REQUEST_FORMATTING_CLOSE_TAG, ]; export function parseCustomRulesFromString( @@ -39,6 +43,7 @@ export function parseCustomRulesFromString( let repositoryStructure = ""; let dependenciesAndInstallation = ""; let testingInstructions = ""; + let pullRequestFormatting = ""; if ( contents.includes(GENERAL_RULES_OPEN_TAG) && @@ -79,12 +84,23 @@ export function parseCustomRulesFromString( contents.indexOf(TESTING_INSTRUCTIONS_CLOSE_TAG), ); } + if ( + contents.includes(PULL_REQUEST_FORMATTING_OPEN_TAG) && + contents.includes(PULL_REQUEST_FORMATTING_CLOSE_TAG) + ) { + pullRequestFormatting = contents.substring( + contents.indexOf(PULL_REQUEST_FORMATTING_OPEN_TAG) + + PULL_REQUEST_FORMATTING_OPEN_TAG.length, + contents.indexOf(PULL_REQUEST_FORMATTING_CLOSE_TAG), + ); + } if ( !generalRules && !repositoryStructure && !dependenciesAndInstallation && - !testingInstructions + !testingInstructions && + !pullRequestFormatting ) { return undefined; } @@ -94,6 +110,7 @@ export function parseCustomRulesFromString( repositoryStructure, dependenciesAndInstallation, testingInstructions, + pullRequestFormatting, }; } diff --git a/apps/web/src/components/v2/quick-actions.tsx b/apps/web/src/components/v2/quick-actions.tsx index 5f778ea4..fedbf974 100644 --- a/apps/web/src/components/v2/quick-actions.tsx +++ b/apps/web/src/components/v2/quick-actions.tsx @@ -7,6 +7,7 @@ const GENERATE_RULES_PROMPT = `You're given a task to write a collection of rule - **Repository Structure**: This section is where you'll include high level context about how the repository is laid out, any highly useful and not overly obvious information about how the directories/files are structured, different apps/packages/services inside the repository, etc. Do not include every last detail about the repository contents, only a high level technical overview on the repository structure. - **Dependencies and Installation**: This section should include high level context about how to install dependencies, where to install them, package managers, etc. Do not include overly verbose context in this section as most repositories typically have straightforward dependency management. - **Testing Instructions**: A general guide on testing in this repository. It should include context such as testing frameworks, roughly what types of modules should be tested, how to run tests, and any other context a developer wouldn't be able to infer by looking at test files on how to write & run tests. Do not include every last detail about testing in this section, only the most used/important context necessary to run tests. +- **Pull request formatting**: Rules and guidelines around how to format pull request titles and descriptions. This should only be populated if you find specific instructions in the repository around how to format pull request titles and descriptions. If the repository does not have specific instructions, leave this section empty. The agent will already generate well thought out titles and descriptions, so unless there are special rules specific to this repository, leave this section empty. Ensure each category is properly wrapped in opening and closing XML tags. The tags to use are as follows: @@ -17,6 +18,8 @@ Ensure each category is properly wrapped in opening and closing XML tags. The ta + + It is incredibly important that you ALWAYS wrap your sections in the opening and closing XML tags. Failure to do so will result in an invalid file and will not be accepted. diff --git a/packages/shared/src/open-swe/types.ts b/packages/shared/src/open-swe/types.ts index 3abf0618..a400d774 100644 --- a/packages/shared/src/open-swe/types.ts +++ b/packages/shared/src/open-swe/types.ts @@ -157,6 +157,7 @@ export type CustomRules = { repositoryStructure?: string; dependenciesAndInstallation?: string; testingInstructions?: string; + pullRequestFormatting?: string; }; export const GraphAnnotation = MessagesZodState.extend({