diff --git a/src/ai/parse-ai-codegen-response.ts b/src/ai/parse-ai-codegen-response.ts index 33b58cf..0d8ff52 100644 --- a/src/ai/parse-ai-codegen-response.ts +++ b/src/ai/parse-ai-codegen-response.ts @@ -55,7 +55,9 @@ export function parseAICodegenResponse(response: string): AIParsedResponse { } // Parse other fields - result.gitBranchName = parseField(response, 'git_branch_name'); + result.gitBranchName = + parseField(response, 'git_branch_name') || + `feature/ai-task-${Date.now()}`; result.gitCommitMessage = parseField(response, 'git_commit_message'); result.summary = parseField(response, 'summary'); result.potentialIssues = parseField(response, 'potential_issues'); diff --git a/src/ai/task-workflow.ts b/src/ai/task-workflow.ts index 3e22518..dd32d39 100644 --- a/src/ai/task-workflow.ts +++ b/src/ai/task-workflow.ts @@ -9,7 +9,7 @@ import { applyChanges } from '../git/apply-changes'; import { selectFilesPrompt } from '../interactive/select-files-prompt'; import type { AiAssistedTaskOptions, MarkdownOptions } from '../types'; import { DEFAULT_CACHE_PATH } from '../utils/cache-utils'; -import { ensureBranch } from '../utils/git-tools'; +import { ensureBranch, ensureValidBranchName } from '../utils/git-tools'; import { collectVariables, extractTemplateVariables, @@ -196,6 +196,10 @@ export async function runAIAssistedTask(options: AiAssistedTaskOptions) { const parsedResponse = parseAICodegenResponse(generatedCode); + parsedResponse.gitBranchName = ensureValidBranchName( + parsedResponse.gitBranchName, + ); + if (options.dryRun) { spinner.info( chalk.yellow( diff --git a/src/utils/git-tools.ts b/src/utils/git-tools.ts index 24dc066..5fc77fa 100644 --- a/src/utils/git-tools.ts +++ b/src/utils/git-tools.ts @@ -32,6 +32,21 @@ export async function prReview(prNumber: string): Promise { return []; } +export function ensureValidBranchName(branchName: string): string { + // Remove any characters that are not allowed in Git branch names + let sanitizedName = branchName.replace(/[^a-zA-Z0-9-_./]/g, '-'); + + // Ensure the branch name doesn't start or end with a slash + sanitizedName = sanitizedName.replace(/^\/+|\/+$/g, ''); + + // If the branch name is empty after sanitization, provide a default + if (!sanitizedName) { + sanitizedName = `feature/ai-task-${Date.now()}`; + } + + return sanitizedName; +} + export async function ensureBranch( basePath: string, initialBranchName: string,