From 09e61779bbe2aea7569384828fd8c74ce9e76544 Mon Sep 17 00:00:00 2001 From: Tim Rogers Date: Thu, 26 Jun 2025 13:42:10 +0100 Subject: [PATCH 1/5] [2025-06-26] GitHub Copilot coding agent expands to Copilot Pro [Public Preview] (#56259) Co-authored-by: hubwriter Co-authored-by: Sophie <29382425+sophietheking@users.noreply.github.com> --- .../about-github-copilot/plans-for-github-copilot.md | 4 ++-- .../adding-copilot-coding-agent-to-organization.md | 4 ++-- .../using-copilot-coding-agent-in-org.md | 2 +- .../coding-agent/troubleshooting-copilot-coding-agent.md | 8 ++++---- data/reusables/copilot/differences-cfi-cfb-table.md | 2 +- data/reusables/gated-features/copilot-coding-agent.md | 2 +- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/content/copilot/about-github-copilot/plans-for-github-copilot.md b/content/copilot/about-github-copilot/plans-for-github-copilot.md index 795041c54956..065ce647f38e 100644 --- a/content/copilot/about-github-copilot/plans-for-github-copilot.md +++ b/content/copilot/about-github-copilot/plans-for-github-copilot.md @@ -14,9 +14,9 @@ redirect_from: * **{% data variables.copilot.copilot_free %}** is available to individual developers who don't have access to {% data variables.product.prodname_copilot_short %} through an organization or enterprise. This free plan includes limited access to select {% data variables.product.prodname_copilot_short %} features, allowing you to try AI-powered coding assistance at no cost. -* **{% data variables.copilot.copilot_pro %}** is designed for individuals who want more flexibility. This paid plan includes unlimited completions, access to premium models in {% data variables.copilot.copilot_chat_short %}, and a monthly allowance of premium requests. Verified students, teachers, and maintainers of popular open source projects may be eligible for free access. +* **{% data variables.copilot.copilot_pro %}** is designed for individuals who want more flexibility. This paid plan includes unlimited completions, access to premium models in {% data variables.copilot.copilot_chat_short %}, access to {% data variables.copilot.copilot_coding_agent %}, and a monthly allowance of premium requests. Verified students, teachers, and maintainers of popular open source projects may be eligible for free access. -* **{% data variables.copilot.copilot_pro_plus %}** offers the highest level of access for individual developers. In addition to everything in {% data variables.copilot.copilot_pro_short %}, this plan includes {% data variables.copilot.copilot_coding_agent %}, a larger allowance of premium requests, and full access to all available models in {% data variables.copilot.copilot_chat_short %}. Ideal for AI power users who want access to the most advanced capabilities. +* **{% data variables.copilot.copilot_pro_plus %}** offers the highest level of access for individual developers. In addition to everything in {% data variables.copilot.copilot_pro_short %}, this plan includes a larger allowance of premium requests, and full access to all available models in {% data variables.copilot.copilot_chat_short %}. Ideal for AI power users who want access to the most advanced capabilities. * **{% data variables.copilot.copilot_for_business %}** is for organizations on {% data variables.product.prodname_free_team %} or {% data variables.product.prodname_team %} plan, or enterprises on {% data variables.product.prodname_ghe_cloud %}. This plan includes {% data variables.copilot.copilot_coding_agent %} and enables centralized management and {% data variables.product.prodname_copilot_short %} policy control for organization members. diff --git a/content/copilot/managing-copilot/managing-github-copilot-in-your-organization/adding-copilot-coding-agent-to-organization.md b/content/copilot/managing-copilot/managing-github-copilot-in-your-organization/adding-copilot-coding-agent-to-organization.md index 08837105ac77..3340ed98b611 100644 --- a/content/copilot/managing-copilot/managing-github-copilot-in-your-organization/adding-copilot-coding-agent-to-organization.md +++ b/content/copilot/managing-copilot/managing-github-copilot-in-your-organization/adding-copilot-coding-agent-to-organization.md @@ -23,9 +23,9 @@ shortTitle: 'Add {% data variables.copilot.copilot_coding_agent %}' {% data reusables.organizations.copilot-policy-ent-overrides-org %} -{% data variables.copilot.copilot_coding_agent %} and use of third-party MCP servers are disabled by default for organization members. +{% data variables.copilot.copilot_coding_agent %} and use of third-party MCP servers are disabled by default for organization members assigned a {% data variables.copilot.copilot_enterprise %} or {% data variables.copilot.copilot_business_short %} license by your organization. -Organizations with {% data variables.copilot.copilot_enterprise %} or {% data variables.copilot.copilot_business_short %} can enable these features for members on the {% data variables.product.prodname_copilot_short %} policies page for their organization. See [Enabling {% data variables.product.prodname_copilot_short %} features in your organization](/copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-policies-for-copilot-in-your-organization#enabling-copilot-features-in-your-organization). +Organizations with {% data variables.copilot.copilot_enterprise_short %} or {% data variables.copilot.copilot_business_short %} can enable these features for members on the {% data variables.product.prodname_copilot_short %} policies page for their organization. See [Enabling {% data variables.product.prodname_copilot_short %} features in your organization](/copilot/managing-copilot/managing-github-copilot-in-your-organization/managing-policies-for-copilot-in-your-organization#enabling-copilot-features-in-your-organization). * For the "{% data variables.copilot.copilot_coding_agent %}" policy, select "Enabled". * For the "MCP servers on {% data variables.product.prodname_dotcom_the_website %}" policy, select "Enabled". diff --git a/content/copilot/rolling-out-github-copilot-at-scale/enabling-developers/using-copilot-coding-agent-in-org.md b/content/copilot/rolling-out-github-copilot-at-scale/enabling-developers/using-copilot-coding-agent-in-org.md index ebced6c3fcfd..e5976c4488d1 100644 --- a/content/copilot/rolling-out-github-copilot-at-scale/enabling-developers/using-copilot-coding-agent-in-org.md +++ b/content/copilot/rolling-out-github-copilot-at-scale/enabling-developers/using-copilot-coding-agent-in-org.md @@ -85,7 +85,7 @@ All AI models are trained to meet a request, even if they don't have all the inf Sign up for {% data variables.product.prodname_copilot_short %} {% octicon "link-external" height:16 aria-label="link-external" %} -> [!TIP] During the {% data variables.release-phases.public_preview %}, you need {% data variables.copilot.copilot_pro_plus %}, {% data variables.copilot.copilot_for_business %} or {% data variables.copilot.copilot_enterprise %} to use {% data variables.copilot.copilot_coding_agent %}. +> [!TIP] You need {% data variables.copilot.copilot_pro %}, {% data variables.copilot.copilot_pro_plus %}, {% data variables.copilot.copilot_for_business %} or {% data variables.copilot.copilot_enterprise %} to use {% data variables.copilot.copilot_coding_agent %}. As with any other change to working practices, it's important to run a trial to learn how to deploy {% data variables.copilot.copilot_coding_agent %} effectively in your organization or enterprise. diff --git a/content/copilot/using-github-copilot/coding-agent/troubleshooting-copilot-coding-agent.md b/content/copilot/using-github-copilot/coding-agent/troubleshooting-copilot-coding-agent.md index db17cd85ff71..3aa92e1e30aa 100644 --- a/content/copilot/using-github-copilot/coding-agent/troubleshooting-copilot-coding-agent.md +++ b/content/copilot/using-github-copilot/coding-agent/troubleshooting-copilot-coding-agent.md @@ -18,20 +18,20 @@ redirect_from: ## {% data variables.product.prodname_copilot_short %} is not available in the "Assignees" list on my issue -You can only assign issues to {% data variables.product.prodname_copilot_short %} if you have access to {% data variables.product.prodname_copilot_short %} through either the **{% data variables.copilot.copilot_pro_plus %}** plan, the **{% data variables.copilot.copilot_for_business %}** plan, or the **{% data variables.copilot.copilot_enterprise %}** plan. +You can only assign issues to {% data variables.product.prodname_copilot_short %} if you have access to {% data variables.product.prodname_copilot_short %} through either the **{% data variables.copilot.copilot_pro %}** plan, **{% data variables.copilot.copilot_pro_plus %}** plan, the **{% data variables.copilot.copilot_for_business %}** plan, or the **{% data variables.copilot.copilot_enterprise %}** plan. If you do not already have a subscription for one of these plans, click this button for more information:
Sign up for {% data variables.product.prodname_copilot_short %} {% octicon "link-external" height:16 aria-label="link-external" %} -If you _do_ have {% data variables.copilot.copilot_pro_plus %}, {% data variables.copilot.copilot_for_business %}, or {% data variables.copilot.copilot_enterprise %}, check that {% data variables.copilot.copilot_coding_agent %} {% ifversion ghec %}is enabled and{% endif %} has not been manually disabled for the repository: +If you _do_ have {% data variables.copilot.copilot_pro %}, {% data variables.copilot.copilot_pro_plus %}, {% data variables.copilot.copilot_for_business %}, or {% data variables.copilot.copilot_enterprise %}, check that {% data variables.copilot.copilot_coding_agent %} {% ifversion ghec %}is enabled and{% endif %} has not been manually disabled for the repository: {% ifversion ghec %} -* If you are on the {% data variables.copilot.copilot_for_business %} or {% data variables.copilot.copilot_enterprise_short %} plan, your ability to use {% data variables.copilot.copilot_coding_agent %} is controlled at the enterprise level. See [AUTOTITLE](/enterprise-cloud@latest/copilot/managing-copilot/managing-copilot-for-your-enterprise/adding-copilot-coding-agent-to-enterprise). +* If you are on the {% data variables.copilot.copilot_for_business %} or {% data variables.copilot.copilot_enterprise_short %} plan, your ability to use {% data variables.copilot.copilot_coding_agent %} is controlled by your enterprise and/or organization administrator. See [AUTOTITLE](/enterprise-cloud@latest/copilot/managing-copilot/managing-copilot-for-your-enterprise/adding-copilot-coding-agent-to-enterprise). {% endif %} -* For organization-owned repositories, the availability of {% data variables.copilot.copilot_coding_agent %} in the repository is configured in the settings for the organization. See [AUTOTITLE](/enterprise-cloud@latest/copilot/managing-copilot/managing-github-copilot-in-your-organization/adding-copilot-coding-agent-to-organization). +* For organization-owned repositories, the availability of {% data variables.copilot.copilot_coding_agent %} in the repository is managed by the organization and/or enterprise administrators. See [AUTOTITLE](/enterprise-cloud@latest/copilot/managing-copilot/managing-github-copilot-in-your-organization/adding-copilot-coding-agent-to-organization). * For personal repositories, the availability of {% data variables.copilot.copilot_coding_agent %} in the repository is configured in your account settings. See [AUTOTITLE](/copilot/managing-copilot/managing-copilot-as-an-individual-subscriber/managing-your-copilot-plan/managing-copilot-policies-as-an-individual-subscriber#enabling-or-disabling-copilot-coding-agent). diff --git a/data/reusables/copilot/differences-cfi-cfb-table.md b/data/reusables/copilot/differences-cfi-cfb-table.md index 97471a5e98b2..169ce2a53b8b 100644 --- a/data/reusables/copilot/differences-cfi-cfb-table.md +++ b/data/reusables/copilot/differences-cfi-cfb-table.md @@ -14,7 +14,7 @@ | Agents | {% data variables.copilot.copilot_free_short %} | {% data variables.copilot.copilot_pro_short %} | {% data variables.copilot.copilot_pro_plus_short %} | {% data variables.copilot.copilot_business_short %} | {% data variables.copilot.copilot_enterprise_short %} | | --- | --- | --- | --- | --- | --- | -| {% data variables.copilot.copilot_coding_agent %} ({% data variables.release-phases.public_preview %}) | {% octicon "x" aria-label="Not included" %} | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | +| {% data variables.copilot.copilot_coding_agent %} ({% data variables.release-phases.public_preview %}) | {% octicon "x" aria-label="Not included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | Agent mode | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.product.prodname_copilot_short %} code review | Only "Review selection" in {% data variables.product.prodname_vscode_shortname %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | | {% data variables.copilot.copilot_extensions_short %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | {% octicon "check" aria-label="Included" %} | diff --git a/data/reusables/gated-features/copilot-coding-agent.md b/data/reusables/gated-features/copilot-coding-agent.md index 107938475922..0f1ef88d65a8 100644 --- a/data/reusables/gated-features/copilot-coding-agent.md +++ b/data/reusables/gated-features/copilot-coding-agent.md @@ -1 +1 @@ -{% data variables.copilot.copilot_coding_agent %} is available with the {% data variables.copilot.copilot_pro_plus %}, {% data variables.copilot.copilot_for_business %} and {% data variables.copilot.copilot_enterprise %} plans in repositories where it has not been disabled. {% data variables.copilot.copilot_coding_agent %} is not available in repositories owned by {% data variables.enterprise.prodname_managed_users %}. +{% data variables.copilot.copilot_coding_agent %} is available with the {% data variables.copilot.copilot_pro %}, {% data variables.copilot.copilot_pro_plus %}, {% data variables.copilot.copilot_for_business %} and {% data variables.copilot.copilot_enterprise %} plans in repositories where it has not been disabled. {% data variables.copilot.copilot_coding_agent %} is not available in repositories owned by {% data variables.enterprise.prodname_managed_users %}. From 921e931cb47fb506f8bb286e82eb9f0ec11b4ede Mon Sep 17 00:00:00 2001 From: chiph Date: Thu, 26 Jun 2025 07:47:09 -0500 Subject: [PATCH 2/5] Add mention of protected branches/rulesets WRT the Update branch button (#56239) Co-authored-by: mc <42146119+mchammer01@users.noreply.github.com> --- .../keeping-your-pull-request-in-sync-with-the-base-branch.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/content/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/keeping-your-pull-request-in-sync-with-the-base-branch.md b/content/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/keeping-your-pull-request-in-sync-with-the-base-branch.md index cbca3c951443..2a6ceb44bf7d 100644 --- a/content/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/keeping-your-pull-request-in-sync-with-the-base-branch.md +++ b/content/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/keeping-your-pull-request-in-sync-with-the-base-branch.md @@ -21,7 +21,9 @@ You can update a pull request's head branch from the command line or the pull re * The pull request branch is not up to date with the base branch. * The base branch requires branches to be up to date before merging or the setting to always suggest updating branches is enabled. -For more information, see [AUTOTITLE](/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches) and [AUTOTITLE](/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-suggestions-to-update-pull-request-branches). +> [!NOTE] You may not be able to update using the `Update branch` button if the HEAD branch of your pull request is a protected branch. + +For more information, see [AUTOTITLE](/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches), [AUTOTITLE](/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets) and [AUTOTITLE](/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-suggestions-to-update-pull-request-branches). If there are changes to the base branch that cause merge conflicts in your pull request branch, you will not be able to update the branch until all conflicts are resolved. For more information, see [AUTOTITLE](/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/about-merge-conflicts). From 603978b135600a07d8ef6a50a5a5c35b179befb7 Mon Sep 17 00:00:00 2001 From: Sarah Schneider Date: Thu, 26 Jun 2025 08:55:41 -0400 Subject: [PATCH 3/5] Fix product string bug (#56313) Co-authored-by: Evan Bonsignori Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/frame/lib/path-utils.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/frame/lib/path-utils.js b/src/frame/lib/path-utils.js index 73c8898fc7ee..1ce97e45e711 100644 --- a/src/frame/lib/path-utils.js +++ b/src/frame/lib/path-utils.js @@ -102,6 +102,7 @@ export function getProductStringFromPath(href) { if (href === '/') return 'homepage' + // The first segment will always be empty on this split const pathParts = href.split('/') if (pathParts.includes('early-access')) return 'early-access' @@ -109,6 +110,8 @@ export function getProductStringFromPath(href) { // For rest pages the currentProduct should be rest // We use this to show SidebarRest, which is a different sidebar than the rest of the site if (pathParts[1] === 'rest') return 'rest' + if (pathParts[1] === 'copilot') return 'copilot' + if (pathParts[1] === 'get-started') return 'get-started' return productIds.includes(pathParts[2]) ? pathParts[2] : pathParts[1] } From 784b71a20da6886adee355d222880e0dd9c79ba3 Mon Sep 17 00:00:00 2001 From: Sarah Schneider Date: Thu, 26 Jun 2025 09:05:17 -0400 Subject: [PATCH 4/5] [Hack week] AI-powered editors (#55906) Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/ai-editors/README.md | 37 +++++ src/ai-editors/lib/call-models-api.js | 24 +++ .../prompts/versioning-editor.prompt.yml | 31 ++++ src/ai-editors/scripts/ai-edit.js | 147 ++++++++++++++++++ 4 files changed, 239 insertions(+) create mode 100644 src/ai-editors/README.md create mode 100644 src/ai-editors/lib/call-models-api.js create mode 100644 src/ai-editors/prompts/versioning-editor.prompt.yml create mode 100755 src/ai-editors/scripts/ai-edit.js diff --git a/src/ai-editors/README.md b/src/ai-editors/README.md new file mode 100644 index 000000000000..eff9519842a8 --- /dev/null +++ b/src/ai-editors/README.md @@ -0,0 +1,37 @@ +# AI-powered editors + +A CLI tool for using AI to edit documentation according to defined prompts. + +This tool runs an AI review of content files based on an (extensible) set of prompt-driven guidelines. The default is versioning. In the future we might add: scannability, readability, style, technical accuracy. + +This script calls the [Models API](https://docs.github.com/en/rest/models/inference?apiVersion=2022-11-28#run-an-inference-request). It requires a personal access token with Models scopes in your `.env` file. + +## Usage + +```sh +tsx src/ai-editors/scripts/ai-edit.js --editor --response --files +``` + +* `--files, -f`: One or more content file paths to process (required). +* `--response, -r`: Specify the AI response format. Options: `rewrite` (default), `list`, `json`. +* `--editor, -e`: Specify one or more editor types (default: `versioning`). + +**Example:** + +```sh +tsx src/ai-editors/scripts/ai-edit.js --files content/pull-requests/collaborating-with-pull-requests/working-with-forks/fork-a-repo.md --editor versioning --response list +``` + +## Requirements + +* A valid `GITHUB_TOKEN` with Models scopes in your local `.env` file. + +## Future development ideas + +* Add prompts to support all available editors. +* Test prompts in Models UI and add evals to prevent regressions. +* Enable running in CI. +* Explore the new `llm` plugin for GitHub Models (see https://github.com/github/copilot-productivity/discussions/5937). +* Add MCP for more comprehensive context. +* Integrate with Copilot Edit mode in VS Code. +* Add unit tests. diff --git a/src/ai-editors/lib/call-models-api.js b/src/ai-editors/lib/call-models-api.js new file mode 100644 index 000000000000..d48a4ee15d81 --- /dev/null +++ b/src/ai-editors/lib/call-models-api.js @@ -0,0 +1,24 @@ +const modelsCompletionsEndpoint = 'https://models.github.ai/inference/chat/completions' + +export async function callModelsApi(promptWithContent) { + let aiResponse + try { + const response = await fetch(modelsCompletionsEndpoint, { + method: 'post', + body: JSON.stringify(promptWithContent), + headers: { + 'Content-Type': 'application/json', + Authorization: `Bearer ${process.env.GITHUB_TOKEN}`, + 'X-GitHub-Api-Version': '2022-11-28', + Accept: 'Accept: application/vnd.github+json', + }, + }) + const data = await response.json() + aiResponse = data.choices[0] + } catch (error) { + console.error('Error calling GitHub Models REST API') + throw error + } + + return aiResponse.message.content +} diff --git a/src/ai-editors/prompts/versioning-editor.prompt.yml b/src/ai-editors/prompts/versioning-editor.prompt.yml new file mode 100644 index 000000000000..2c1a2c0f384c --- /dev/null +++ b/src/ai-editors/prompts/versioning-editor.prompt.yml @@ -0,0 +1,31 @@ +messages: + - role: system + content: >- + Your task is to remove the conditional markup from content files that + looks like {% ifversion fpt or ghec %}Foo{% endif %}. You need to first try + to write the content without any versioning at all, so it still makes sense + to customers without causing confusion. If you need to explain versioning + differences, do so using prose. Here are the prose guidelines to follow: + * For versioning at the article level: + - When the feature is only available in certain products, use the "Who can + use this feature?" box to convey the content of this article applies only + to XYZ products. + - When an article only exists before the functionality is in older versions + of GHES (and not dotcom and newer versions of GHES), just remove that article. + (This is akin to declining to document a feature.) + * For versioning at the heading level: + - Use prose similar to the "Who can use this feature?" to convey that the + content of this section applies only to XYZ products. + * For versioning the paragraph or sentence level: + - Use one of the following content strategies: + - If you're briefly introducing a feature and then linking to an article, + there's no need to specify versioning. Let folks learn availability when + they follow the link, via the "Who can use this feature?" box. + - When necessary, start sentences with "With GitHub Enterprise Cloud...", + "On GitHub.com", "With GitHub Enterprise Server 3.15+..." etc. + - End list items with "(GitHub Enterprise Cloud only)", "(GitHub.com only)", etc. + - role: user + content: >- + Review this content according to the new prose versioning guidelines. {{responseTypeInstruction}} + {{input}} +model: openai/gpt-4.1-mini diff --git a/src/ai-editors/scripts/ai-edit.js b/src/ai-editors/scripts/ai-edit.js new file mode 100755 index 000000000000..cca7cc87c134 --- /dev/null +++ b/src/ai-editors/scripts/ai-edit.js @@ -0,0 +1,147 @@ +#!/usr/bin/env node + +import { fileURLToPath } from 'url' +import { Command } from 'commander' +import fs from 'fs' +import yaml from 'js-yaml' +import path from 'path' +import ora from 'ora' +import github from '#src/workflows/github.ts' +import { callModelsApi } from '#src/ai-editors/lib/call-models-api.js' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const promptDir = path.join(__dirname, '../prompts') + +if (!process.env.GITHUB_TOKEN) { + throw new Error('Error! You must have a GITHUB_TOKEN set in an .env file to run this script.') +} + +const responseTypes = { + rewrite: 'Edit the versioning only. Return the edited content.', + list: `Do NOT rewrite the content. Report your edits in numbered list format.`, + json: `Do NOT rewrite the content. Report your edits as a JSON list, with the format { lineNumber, currentText, suggestion }.`, +} + +const validResponseTypes = Object.keys(responseTypes) + +const editorTypes = { + versioning: { + promptFile: 'versioning-editor.prompt.yml', + description: 'Review against simplifying versioning guidelines.', + }, + // TODO + // scannability: { + // promptFile: 'scannability-editor.prompt.yml', + // description: 'Review against scannability guidelines.', + // }, + // readability: { + // promptFile: 'readability-editor.prompt.yml', + // description: + // 'Review against readability criteria like Gunning Fog index, Hemingway, word count, sentence length, etc.', + // }, + // technical: { + // promptFile: 'technical-editor.prompt.yml', + // description: 'Review against provided product information for technical accuracy.', + // }, + // styleguide: { + // promptFile: 'styleguide-editor.prompt.yml', + // description: 'Review against the GitHub Docs style guide.', + // }, + // contentModels: { + // promptFile: 'content-models-editor.prompt.yml', + // description: 'Review against the GitHub Docs content models.', + // }, + // Add more here... +} + +const editorDescriptions = () => { + let str = '\n\n' + Object.entries(editorTypes).forEach(([ed, edObj]) => { + str += `\t${ed}\n\t\t\t${edObj.description}\n\n` + }) + return str +} + +const program = new Command() + +program + .name('ai-edit') + .description('Edit content files using AI') + .option('-v, --verbose', 'Enable verbose output') + .option( + '-e, --editor ', + `Specify one or more editor type: ${editorDescriptions().trimEnd()}\n`, + ) + .option( + '-r, --response ', + `Specify response type: ${validResponseTypes.join(', ')} (default: rewrite)`, + ) + .requiredOption( + '-f, --files ', + 'One or more content file paths in the content directory', + ) + .action((options) => { + ;(async () => { + const spinner = ora('Starting AI review...').start() + + const files = options.files + const editors = options.editor || ['versioning'] + const response = options.response || 'rewrite' + + let responseTypeInstruction + if (validResponseTypes.includes(response)) { + responseTypeInstruction = responseTypes[response] + } else { + console.error( + `Invalid response type: ${response}. Must be one of: ${validResponseTypes.join(', ')}`, + ) + process.exit(1) + } + + for (const file of files) { + const filePath = path.resolve(process.cwd(), file) + spinner.text = `Checking file: ${file}` + + if (!fs.existsSync(filePath)) { + spinner.fail(`File not found: ${filePath}`) + process.exitCode = 1 + continue + } + + try { + spinner.text = `Reading file: ${file}` + const content = fs.readFileSync(filePath, 'utf8') + + for (const editorType of editors) { + spinner.text = `Running the AI-powered ${editorType} editor...` + const answer = await callEditor(editorType, responseTypeInstruction, content) + + if (response === 'rewrite') { + fs.writeFileSync(file, answer, 'utf-8') + spinner.succeed(`Processed file: ${file}`) + console.log(`To see changes, run "git diff" on the file.`) + } else { + spinner.succeed(`Processed file: ${file}`) + console.log(answer) + } + } + } catch (err) { + spinner.fail(`Error processing file ${file}: ${err.message}`) + process.exitCode = 1 + } + } + })() + }) + +program.parse(process.argv) + +async function callEditor(editorType, responseTypeInstruction, content) { + const promptName = editorTypes[editorType].promptFile + const promptPath = path.join(promptDir, promptName) + const prompt = yaml.load(fs.readFileSync(promptPath, 'utf8')) + prompt.messages.forEach((msg) => { + msg.content = msg.content.replace('{{responseTypeInstruction}}', responseTypeInstruction) + msg.content = msg.content.replace('{{input}}', content) + }) + return callModelsApi(prompt) +} From 5b75825602a64eee163f31af09a82a02311542e4 Mon Sep 17 00:00:00 2001 From: Sarah Schneider Date: Thu, 26 Jun 2025 10:56:50 -0400 Subject: [PATCH 5/5] Fix product string bug (take 2) (#56330) --- src/frame/lib/path-utils.js | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/frame/lib/path-utils.js b/src/frame/lib/path-utils.js index 1ce97e45e711..dd3fb7b9f36e 100644 --- a/src/frame/lib/path-utils.js +++ b/src/frame/lib/path-utils.js @@ -96,6 +96,7 @@ export function getVersionObjectFromPath(href) { return allVersions[versionFromPath] } +// TODO needs refactoring + tests // Return the product segment from the path export function getProductStringFromPath(href) { href = getPathWithoutLanguage(href) @@ -110,10 +111,15 @@ export function getProductStringFromPath(href) { // For rest pages the currentProduct should be rest // We use this to show SidebarRest, which is a different sidebar than the rest of the site if (pathParts[1] === 'rest') return 'rest' - if (pathParts[1] === 'copilot') return 'copilot' - if (pathParts[1] === 'get-started') return 'get-started' - return productIds.includes(pathParts[2]) ? pathParts[2] : pathParts[1] + // Possible scenarios for href (assume part[0] is an empty string): + // + // * part[1] is a version and part[2] is undefined, so return part[1] as an enterprise landing page + // * part[1] is a version and part[2] is defined, so return part[2] as the product + // * part[1] is NOT a version, so return part[1] as the product + const isEnterprise = supportedVersions.has(pathParts[1]) + const productString = isEnterprise && pathParts[2] ? pathParts[2] : pathParts[1] + return productString } export function getCategoryStringFromPath(href) {