Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions src/@types/vscode.proposed.chatParticipantAdditions.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ declare module 'vscode' {
isComplete?: boolean;
toolSpecificData?: ChatTerminalToolInvocationData;
fromSubAgent?: boolean;
presentation?: 'hidden' | 'hiddenAfterComplete' | undefined;

constructor(toolName: string, toolCallId: string, isError?: boolean);
}
Expand Down
5 changes: 5 additions & 0 deletions src/@types/vscode.proposed.chatSessionsProvider.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,11 @@ declare module 'vscode' {
*/
description?: string | MarkdownString;

/**
* An optional badge that provides additional context about the chat session.
*/
badge?: string | MarkdownString;

/**
* An optional status indicating the current state of the session.
*/
Expand Down
13 changes: 13 additions & 0 deletions src/github/createPRViewProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -753,6 +753,19 @@ export class CreatePullRequestViewProvider extends BaseCreatePullRequestViewProv
// Ignore and fall back to commit message
Logger.debug(`Error while getting total commits: ${e}`, CreatePullRequestViewProvider.ID);
}

// Apply variable substitution to title and description
const activeIssue = this._folderRepositoryManager.activeIssue;
let currentUser: string | undefined;
try {
currentUser = activeIssue ? (await this._folderRepositoryManager.getCurrentUser(activeIssue.githubRepository)).login : undefined;
} catch (e) {
Logger.debug(`Failed to get current user for variable substitution: ${e}`, CreatePullRequestViewProvider.ID);
currentUser = undefined;
}
title = variableSubstitution(title, activeIssue, this._pullRequestDefaults, currentUser);
description = variableSubstitution(description, activeIssue, this._pullRequestDefaults, currentUser);

return { title, description };
}

Expand Down
87 changes: 86 additions & 1 deletion src/test/github/utils.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
*--------------------------------------------------------------------------------------------*/

import { default as assert } from 'assert';
import { getPRFetchQuery, sanitizeIssueTitle } from '../../github/utils';
import { getPRFetchQuery, sanitizeIssueTitle, variableSubstitution } from '../../github/utils';
import { IssueModel } from '../../github/issueModel';
import { PullRequestDefaults } from '../../github/folderRepositoryManager';

describe('utils', () => {

Expand Down Expand Up @@ -41,4 +43,87 @@ describe('utils', () => {
});
});
});

describe('variableSubstitution', () => {
const defaults: PullRequestDefaults = {
owner: 'testOwner',
repo: 'testRepo',
base: 'main'
};

it('replaces ${issueNumber} with issue number', () => {
const issueModel = {
number: 123,
title: 'Test Issue',
remote: { owner: 'testOwner', repositoryName: 'testRepo' }
} as unknown as IssueModel;
const result = variableSubstitution('Closes ${issueNumber}', issueModel, defaults, 'testUser');
assert.strictEqual(result, 'Closes 123');
});

it('replaces ${issueNumberLabel} with #number for same repo', () => {
const issueModel = {
number: 456,
title: 'Test Issue',
remote: { owner: 'testOwner', repositoryName: 'testRepo' }
} as unknown as IssueModel;
const result = variableSubstitution('Fixes ${issueNumberLabel}', issueModel, defaults, 'testUser');
assert.strictEqual(result, 'Fixes #456');
});

it('replaces ${issueNumberLabel} with owner/repo#number for different repo', () => {
const issueModel = {
number: 789,
title: 'Test Issue',
remote: { owner: 'otherOwner', repositoryName: 'otherRepo' }
} as unknown as IssueModel;
const result = variableSubstitution('Resolves ${issueNumberLabel}', issueModel, defaults, 'testUser');
assert.strictEqual(result, 'Resolves otherOwner/otherRepo#789');
});

it('replaces ${issueTitle} with issue title', () => {
const issueModel = {
number: 123,
title: 'Fix bug in parser',
remote: { owner: 'testOwner', repositoryName: 'testRepo' }
} as unknown as IssueModel;
const result = variableSubstitution('Working on: ${issueTitle}', issueModel, defaults, 'testUser');
assert.strictEqual(result, 'Working on: Fix bug in parser');
});

it('replaces ${user} with username', () => {
const result = variableSubstitution('Assigned to ${user}', undefined, defaults, 'johnDoe');
assert.strictEqual(result, 'Assigned to johnDoe');
});

it('replaces ${repository} with repo name', () => {
const result = variableSubstitution('From ${repository}', undefined, defaults, 'testUser');
assert.strictEqual(result, 'From testRepo');
});

it('replaces ${owner} with owner name', () => {
const result = variableSubstitution('By ${owner}', undefined, defaults, 'testUser');
assert.strictEqual(result, 'By testOwner');
});

it('replaces multiple variables in one string', () => {
const issueModel = {
number: 123,
title: 'Test Issue',
remote: { owner: 'testOwner', repositoryName: 'testRepo' }
} as unknown as IssueModel;
const result = variableSubstitution('Closes ${issueNumberLabel}: ${issueTitle}', issueModel, defaults, 'testUser');
assert.strictEqual(result, 'Closes #123: Test Issue');
});

it('leaves variable unchanged if issue is not provided', () => {
const result = variableSubstitution('Closes ${issueNumberLabel}', undefined, defaults, 'testUser');
assert.strictEqual(result, 'Closes ${issueNumberLabel}');
});

it('handles empty string', () => {
const result = variableSubstitution('', undefined, defaults, 'testUser');
assert.strictEqual(result, '');
});
});
});