From 270e92ecaf3efcea3fd4645794334c06134dbaf0 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 14:40:25 +0000 Subject: [PATCH 1/5] Initial plan From c46c104b0833892c8e395e0dd93b87b6172bc6bb Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 14:45:25 +0000 Subject: [PATCH 2/5] Initial planning for YAML issue template support Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> --- src/@types/vscode.proposed.chatParticipantAdditions.d.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/src/@types/vscode.proposed.chatParticipantAdditions.d.ts b/src/@types/vscode.proposed.chatParticipantAdditions.d.ts index 71520fa1ec..aa7001a3d2 100644 --- a/src/@types/vscode.proposed.chatParticipantAdditions.d.ts +++ b/src/@types/vscode.proposed.chatParticipantAdditions.d.ts @@ -105,6 +105,7 @@ declare module 'vscode' { isComplete?: boolean; toolSpecificData?: ChatTerminalToolInvocationData; fromSubAgent?: boolean; + presentation?: 'hidden' | 'hiddenAfterComplete' | undefined; constructor(toolName: string, toolCallId: string, isError?: boolean); } From 966777e62df268b9f790842f37c1b04c1930098a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 14:57:41 +0000 Subject: [PATCH 3/5] Add YAML issue template support Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/test-yaml-template.yml | 45 +++++++++++++ package.json | 3 +- src/github/folderRepositoryManager.ts | 11 ++-- src/issues/issueFeatureRegistrar.ts | 66 +++++++++++++++++++ src/issues/util.ts | 25 +++++++ yarn.lock | 5 ++ 6 files changed, 150 insertions(+), 5 deletions(-) create mode 100644 .github/ISSUE_TEMPLATE/test-yaml-template.yml diff --git a/.github/ISSUE_TEMPLATE/test-yaml-template.yml b/.github/ISSUE_TEMPLATE/test-yaml-template.yml new file mode 100644 index 0000000000..3473a74b2a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/test-yaml-template.yml @@ -0,0 +1,45 @@ +name: Test YAML Template +description: A test YAML issue template for verification +title: "[Test]: " +labels: ["test"] +body: + - type: markdown + attributes: + value: | + Thanks for reporting this test issue! + - type: input + id: contact + attributes: + label: Contact Details + description: How can we get in touch with you if we need more info? + placeholder: ex. email@example.com + validations: + required: false + - type: textarea + id: what-happened + attributes: + label: What happened? + description: Also tell us, what did you expect to happen? + placeholder: Tell us what you see! + value: "A bug happened!" + validations: + required: true + - type: dropdown + id: version + attributes: + label: Version + description: What version of our software are you running? + options: + - 1.0.0 + - 1.1.0 + - 1.2.0 + validations: + required: true + - type: checkboxes + id: terms + attributes: + label: Code of Conduct + description: By submitting this issue, you agree to follow our Code of Conduct + options: + - label: I agree to follow this project's Code of Conduct + required: true diff --git a/package.json b/package.json index 121adffe67..fed1b6a7f1 100644 --- a/package.json +++ b/package.json @@ -4351,6 +4351,7 @@ "@shikijs/monaco": "^3.7.0", "@types/chai": "^4.1.4", "@types/glob": "7.1.3", + "@types/js-yaml": "^4.0.9", "@types/lru-cache": "^5.1.0", "@types/marked": "^0.7.2", "@types/mocha": "^8.2.2", @@ -4452,4 +4453,4 @@ "string_decoder": "^1.3.0" }, "license": "MIT" -} \ No newline at end of file +} diff --git a/src/github/folderRepositoryManager.ts b/src/github/folderRepositoryManager.ts index 9dd9002c84..b32a89272f 100644 --- a/src/github/folderRepositoryManager.ts +++ b/src/github/folderRepositoryManager.ts @@ -1346,10 +1346,13 @@ export class FolderRepositoryManager extends Disposable { } async getIssueTemplates(): Promise { - const pattern = '{docs,.github}/ISSUE_TEMPLATE/*.md'; - return vscode.workspace.findFiles( - new vscode.RelativePattern(this._repository.rootUri, pattern), null - ); + const mdPattern = '{docs,.github}/ISSUE_TEMPLATE/*.md'; + const ymlPattern = '{docs,.github}/ISSUE_TEMPLATE/*.yml'; + const [mdTemplates, ymlTemplates] = await Promise.all([ + vscode.workspace.findFiles(new vscode.RelativePattern(this._repository.rootUri, mdPattern), null), + vscode.workspace.findFiles(new vscode.RelativePattern(this._repository.rootUri, ymlPattern), null) + ]); + return [...mdTemplates, ...ymlTemplates]; } async getPullRequestTemplateBody(owner: string): Promise { diff --git a/src/issues/issueFeatureRegistrar.ts b/src/issues/issueFeatureRegistrar.ts index a4f253a57d..c1afffaa5d 100644 --- a/src/issues/issueFeatureRegistrar.ts +++ b/src/issues/issueFeatureRegistrar.ts @@ -4,6 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { basename } from 'path'; +import * as yaml from 'js-yaml'; import * as vscode from 'vscode'; import { CurrentIssue } from './currentIssue'; import { IssueCompletionProvider } from './issueCompletionProvider'; @@ -56,6 +57,7 @@ import { PermalinkInfo, pushAndCreatePR, USER_EXPRESSION, + YamlIssueTemplate, } from './util'; import { truncate } from '../common/utils'; import { OctokitCommon } from '../github/common'; @@ -1250,6 +1252,18 @@ ${options?.body ?? ''}\n } private getDataFromTemplate(template: string): IssueTemplate { + // Try to parse as YAML first (YAML templates have a different structure) + try { + const parsed = yaml.load(template); + if (parsed && typeof parsed === 'object' && (parsed as YamlIssueTemplate).name) { + // This is a YAML template + return this.parseYamlTemplate(parsed as YamlIssueTemplate); + } + } catch (e) { + // Not a valid YAML, continue to Markdown parsing + } + + // Parse as Markdown frontmatter template const title = template.match(/title:\s*(.*)/)?.[1]?.replace(/^["']|["']$/g, ''); const name = template.match(/name:\s*(.*)/)?.[1]?.replace(/^["']|["']$/g, ''); const about = template.match(/about:\s*(.*)/)?.[1]?.replace(/^["']|["']$/g, ''); @@ -1257,6 +1271,58 @@ ${options?.body ?? ''}\n return { title, name, about, body }; } + private parseYamlTemplate(parsed: YamlIssueTemplate): IssueTemplate { + const name = parsed.name; + const about = parsed.description || parsed.about; + const title = parsed.title; + + // Convert YAML body fields to markdown + let body = ''; + if (parsed.body && Array.isArray(parsed.body)) { + for (const field of parsed.body) { + if (field.type === 'markdown' && field.attributes?.value) { + body += field.attributes.value + '\n\n'; + } else if (field.type === 'textarea' && field.attributes?.label) { + body += `## ${field.attributes.label}\n\n`; + if (field.attributes.description) { + body += `${field.attributes.description}\n\n`; + } + if (field.attributes.placeholder) { + body += `${field.attributes.placeholder}\n\n`; + } else if (field.attributes.value) { + body += `${field.attributes.value}\n\n`; + } + } else if (field.type === 'input' && field.attributes?.label) { + body += `## ${field.attributes.label}\n\n`; + if (field.attributes.description) { + body += `${field.attributes.description}\n\n`; + } + if (field.attributes.placeholder) { + body += `${field.attributes.placeholder}\n\n`; + } + } else if (field.type === 'dropdown' && field.attributes?.label) { + body += `## ${field.attributes.label}\n\n`; + if (field.attributes.description) { + body += `${field.attributes.description}\n\n`; + } + if (field.attributes.options && Array.isArray(field.attributes.options)) { + body += field.attributes.options.map((opt: string) => `- ${opt}`).join('\n') + '\n\n'; + } + } else if (field.type === 'checkboxes' && field.attributes?.label) { + body += `## ${field.attributes.label}\n\n`; + if (field.attributes.description) { + body += `${field.attributes.description}\n\n`; + } + if (field.attributes.options && Array.isArray(field.attributes.options)) { + body += field.attributes.options.map((opt: { label?: string } | string) => `- [ ] ${typeof opt === 'string' ? opt : opt.label || ''}`).join('\n') + '\n\n'; + } + } + } + } + + return { title, name, about, body: body.trim() || undefined }; + } + private async doCreateIssue( document: vscode.TextDocument | undefined, newIssue: NewIssue | undefined, diff --git a/src/issues/util.ts b/src/issues/util.ts index 87a4e7e382..39a82e5709 100644 --- a/src/issues/util.ts +++ b/src/issues/util.ts @@ -94,6 +94,31 @@ export interface IssueTemplate { body: string | undefined } +export interface YamlIssueTemplate { + name?: string; + description?: string; + about?: string; + title?: string; + labels?: string[]; + assignees?: string[]; + body?: YamlTemplateField[]; +} + +export interface YamlTemplateField { + type: 'markdown' | 'textarea' | 'input' | 'dropdown' | 'checkboxes'; + id?: string; + attributes?: { + label?: string; + description?: string; + placeholder?: string; + value?: string; + options?: (string | { label?: string; required?: boolean })[]; + }; + validations?: { + required?: boolean; + }; +} + const HEAD = 'HEAD'; const UPSTREAM = 1; const UPS = 2; diff --git a/yarn.lock b/yarn.lock index c69c2b7b0f..f41ef8d14d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -885,6 +885,11 @@ "@types/istanbul-lib-coverage" "*" "@types/istanbul-lib-report" "*" +"@types/js-yaml@^4.0.9": + version "4.0.9" + resolved "https://registry.yarnpkg.com/@types/js-yaml/-/js-yaml-4.0.9.tgz#cd82382c4f902fed9691a2ed79ec68c5898af4c2" + integrity sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg== + "@types/json-schema@^7.0.15": version "7.0.15" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" From 981e1263b711c0c176dfbe61154675f9fad03f6b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 14:59:25 +0000 Subject: [PATCH 4/5] Clean up test YAML template Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> --- .github/ISSUE_TEMPLATE/test-yaml-template.yml | 45 ------------------- 1 file changed, 45 deletions(-) delete mode 100644 .github/ISSUE_TEMPLATE/test-yaml-template.yml diff --git a/.github/ISSUE_TEMPLATE/test-yaml-template.yml b/.github/ISSUE_TEMPLATE/test-yaml-template.yml deleted file mode 100644 index 3473a74b2a..0000000000 --- a/.github/ISSUE_TEMPLATE/test-yaml-template.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: Test YAML Template -description: A test YAML issue template for verification -title: "[Test]: " -labels: ["test"] -body: - - type: markdown - attributes: - value: | - Thanks for reporting this test issue! - - type: input - id: contact - attributes: - label: Contact Details - description: How can we get in touch with you if we need more info? - placeholder: ex. email@example.com - validations: - required: false - - type: textarea - id: what-happened - attributes: - label: What happened? - description: Also tell us, what did you expect to happen? - placeholder: Tell us what you see! - value: "A bug happened!" - validations: - required: true - - type: dropdown - id: version - attributes: - label: Version - description: What version of our software are you running? - options: - - 1.0.0 - - 1.1.0 - - 1.2.0 - validations: - required: true - - type: checkboxes - id: terms - attributes: - label: Code of Conduct - description: By submitting this issue, you agree to follow our Code of Conduct - options: - - label: I agree to follow this project's Code of Conduct - required: true From 3d93c098194b855114110bafeaeea9ca4320946f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Wed, 10 Dec 2025 15:03:31 +0000 Subject: [PATCH 5/5] Address code review feedback: add js-yaml dependency and improve type safety Co-authored-by: alexr00 <38270282+alexr00@users.noreply.github.com> --- package.json | 1 + src/issues/issueFeatureRegistrar.ts | 5 +++-- yarn.lock | 7 +++++++ 3 files changed, 11 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index fed1b6a7f1..3382430511 100644 --- a/package.json +++ b/package.json @@ -4433,6 +4433,7 @@ "debounce": "^1.2.1", "events": "3.2.0", "fast-deep-equal": "^3.1.3", + "js-yaml": "^4.1.1", "jsonc-parser": "^3.3.1", "jszip": "^3.10.1", "lru-cache": "6.0.0", diff --git a/src/issues/issueFeatureRegistrar.ts b/src/issues/issueFeatureRegistrar.ts index c1afffaa5d..e3cc9dfec1 100644 --- a/src/issues/issueFeatureRegistrar.ts +++ b/src/issues/issueFeatureRegistrar.ts @@ -1255,7 +1255,8 @@ ${options?.body ?? ''}\n // Try to parse as YAML first (YAML templates have a different structure) try { const parsed = yaml.load(template); - if (parsed && typeof parsed === 'object' && (parsed as YamlIssueTemplate).name) { + // Check if it looks like a YAML issue template (has name and body fields) + if (parsed && typeof parsed === 'object' && (parsed as YamlIssueTemplate).name && (parsed as YamlIssueTemplate).body) { // This is a YAML template return this.parseYamlTemplate(parsed as YamlIssueTemplate); } @@ -1306,7 +1307,7 @@ ${options?.body ?? ''}\n body += `${field.attributes.description}\n\n`; } if (field.attributes.options && Array.isArray(field.attributes.options)) { - body += field.attributes.options.map((opt: string) => `- ${opt}`).join('\n') + '\n\n'; + body += field.attributes.options.map((opt: string | { label?: string }) => typeof opt === 'string' ? `- ${opt}` : `- ${opt.label || ''}`).join('\n') + '\n\n'; } } else if (field.type === 'checkboxes' && field.attributes?.label) { body += `## ${field.attributes.label}\n\n`; diff --git a/yarn.lock b/yarn.lock index f41ef8d14d..bfcc228559 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4765,6 +4765,13 @@ js-yaml@4.1.0, js-yaml@^4.1.0: dependencies: argparse "^2.0.1" +js-yaml@^4.1.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.1.tgz#854c292467705b699476e1a2decc0c8a3458806b" + integrity sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA== + dependencies: + argparse "^2.0.1" + jsdom-global@3.0.2: version "3.0.2" resolved "https://registry.yarnpkg.com/jsdom-global/-/jsdom-global-3.0.2.tgz#6bd299c13b0c4626b2da2c0393cd4385d606acb9"