Skip to content

Add create PR tool and skill#8631

Open
alexr00 wants to merge 1 commit intomainfrom
alexr00/deep-cuckoo
Open

Add create PR tool and skill#8631
alexr00 wants to merge 1 commit intomainfrom
alexr00/deep-cuckoo

Conversation

@alexr00
Copy link
Copy Markdown
Member

@alexr00 alexr00 commented Mar 30, 2026

No description provided.

Copilot AI review requested due to automatic review settings March 30, 2026 14:28
@alexr00 alexr00 enabled auto-merge (squash) March 30, 2026 14:29
@alexr00 alexr00 self-assigned this Mar 30, 2026
@alexr00 alexr00 disabled auto-merge March 30, 2026 14:32
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new Language Model (LM) tool + chat skill to let Copilot create GitHub pull requests via the extension, complementing the existing LM tools (fetch/search/read PR).

Changes:

  • Register a new LM tool github-pull-request_create_pull_request and expose it via package.json contributes.
  • Implement CreatePullRequestTool to create PRs using FolderRepositoryManager.createPullRequest.
  • Add a new chat skill (create-pull-request) and localize tool display strings.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
src/lm/tools/tools.ts Registers the new Create Pull Request LM tool.
src/lm/tools/createPullRequestTool.ts Implements PR creation + confirmation UI for tool invocation.
src/lm/skills/create-pull-request/SKILL.md Adds a skill playbook instructing the agent how/when to call the tool.
package.nls.json Adds localized display name/description for the new tool.
package.json Adds the skill path and the LM tool contribution (schema, descriptions, icon).
Comments suppressed due to low confidence (1)

src/lm/tools/createPullRequestTool.ts:46

  • resolveParams always prefixes input.head with ${headOwner}:. If the caller passes head as owner:branch (common in GitHub APIs), this will produce an invalid ref like someOwner:otherOwner:branch. Add validation/normalization (e.g. detect : in input.head and either parse it or reject it) and document the expected format.
		const defaults = await folderManager.getPullRequestDefaults();
		const headOwner = input.headOwner ?? defaults.owner;
		const head = `${headOwner}:${input.head}`;
		const base = input.base ?? defaults.base;

Comment on lines +89 to +91
message.appendMarkdown(`**Title:** ${options.input.title}\n\n`);
if (options.input.body) {
message.appendMarkdown(`**Description:** ${options.input.body}\n\n`);
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The confirmation MarkdownString is built with appendMarkdown using unescaped title/body. Since these values can contain arbitrary markdown, they can unintentionally render links/formatting in the confirmation UI. Prefer appendText for user/model-provided values (or escape markdown) and only use markdown for the fixed labels.

Suggested change
message.appendMarkdown(`**Title:** ${options.input.title}\n\n`);
if (options.input.body) {
message.appendMarkdown(`**Description:** ${options.input.body}\n\n`);
message.appendMarkdown('**Title:** ');
message.appendText(options.input.title);
message.appendMarkdown('\n\n');
if (options.input.body) {
message.appendMarkdown('**Description:** ');
message.appendText(options.input.body);
message.appendMarkdown('\n\n');

Copilot uses AI. Check for mistakes.
Comment on lines +81 to +83
async prepareInvocation(options: vscode.LanguageModelToolInvocationPrepareOptions<CreatePullRequestToolParameters>): Promise<vscode.PreparedToolInvocation> {
const resolved = await this.resolveParams(options.input);
const { owner, name, base } = resolved;
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

prepareInvocation calls resolveParams(), which calls getPullRequestDefaults() (network/metadata) and then invoke() calls resolveParams() again. This doubles the metadata work for a single tool call. Consider making prepareInvocation not depend on pull request defaults (or otherwise avoid repeating expensive repo/default resolution).

Copilot uses AI. Check for mistakes.
},
"head": {
"type": "string",
"description": "The name of the branch where your changes are implemented."
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The input schema/docs for head don’t state that the tool expects a branch name only (no owner: prefix), but the implementation always prefixes headOwner:. Please update the head description to explicitly require branch-name only (or update the tool to accept owner:branch), otherwise models/users may provide owner:branch and get an invalid head ref.

Suggested change
"description": "The name of the branch where your changes are implemented."
"description": "The name of the branch where your changes are implemented (branch name only, without owner prefix)."

Copilot uses AI. Check for mistakes.
},
"headOwner": {
"type": "string",
"description": "The owner of the head branch repository. Defaults to the upstream repository owner."
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The headOwner description says it defaults to the upstream repository owner, but for fork scenarios the natural default is usually the origin/push remote owner (where the head branch exists). Align the schema/docs with the actual defaulting behavior you want, otherwise the tool will be confusing and error-prone for fork-based PRs.

Suggested change
"description": "The owner of the head branch repository. Defaults to the upstream repository owner."
"description": "The owner of the head branch repository. Defaults to the origin/push remote repository owner."

Copilot uses AI. Check for mistakes.

After the tool returns successfully:

- Report the PR number and URL to the user as a markdown link. The link should be a VS Code URI like `vscode-insiders://github.vscode-pull-request-github/open-pull-request-webview?uri=https://github.com/microsoft/vscode-css-languageservice/pull/460`.
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This skill hardcodes a vscode-insiders://... URI scheme in the example link. That won’t work in stable VS Code, and can lead to incorrect guidance. Prefer a scheme-agnostic instruction (or mention both vscode:// and vscode-insiders://) and/or link to the PR’s https:// URL when constructing examples.

Suggested change
- Report the PR number and URL to the user as a markdown link. The link should be a VS Code URI like `vscode-insiders://github.vscode-pull-request-github/open-pull-request-webview?uri=https://github.com/microsoft/vscode-css-languageservice/pull/460`.
- Report the PR number and URL to the user as a markdown link, using the standard GitHub URL (for example, `https://github.com/microsoft/vscode-css-languageservice/pull/460`).
- If relevant for VS Code users, you may additionally provide a VS Code URI using either the `vscode://` or `vscode-insiders://` scheme that opens the PR in the GitHub Pull Requests extension.

Copilot uses AI. Check for mistakes.
private async resolveParams(input: CreatePullRequestToolParameters): Promise<ResolvedPullRequestParams> {
const { owner, name, folderManager } = await this.getRepoInfo({ owner: input.repo?.owner, name: input.repo?.name });
const defaults = await folderManager.getPullRequestDefaults();
const headOwner = input.headOwner ?? defaults.owner;
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

headOwner is defaulting to defaults.owner (the base/upstream repo owner). For fork-based PRs, the head branch typically lives on the origin/fork owner, so this default will build an invalid head ref (upstreamOwner:branch) and PR creation will fail. Consider defaulting headOwner based on the push/origin repo for the current branch (e.g. await folderManager.getOrigin()), and only fall back to the upstream owner when appropriate.

This issue also appears on line 43 of the same file.

Suggested change
const headOwner = input.headOwner ?? defaults.owner;
const origin = await folderManager.getOrigin();
const headOwner = input.headOwner ?? origin?.owner ?? defaults.owner;

Copilot uses AI. Check for mistakes.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants