From 7f63f3a5dce5e0caffcc9c4326cdac982c7adc73 Mon Sep 17 00:00:00 2001 From: Sunbrye Ly <56200261+sunbrye@users.noreply.github.com> Date: Tue, 29 Sep 2026 17:25:47 +0000 Subject: [PATCH 1/4] Tented Model 0067 (#63574) Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: 69af1954-1646-4d32-9728-e62654499046 --- .../reference/ai-models/model-hosting.md | 1 + .../reference/ai-models/supported-models.md | 2 ++ .../copilot-billing/models-and-pricing.md | 2 +- .../copilot-cloud-agent-non-auto-models.md | 1 + data/tables/copilot/model-comparison.yml | 7 +++++- data/tables/copilot/model-release-status.yml | 4 ++++ data/tables/copilot/model-supported-plans.yml | 7 ++++++ data/tables/copilot/models-and-pricing.yml | 22 +++++++++++++++++++ data/variables/copilot.yml | 1 + 9 files changed, 45 insertions(+), 2 deletions(-) diff --git a/content/copilot/reference/ai-models/model-hosting.md b/content/copilot/reference/ai-models/model-hosting.md index 4765f740441b..ce71be2d6b5e 100644 --- a/content/copilot/reference/ai-models/model-hosting.md +++ b/content/copilot/reference/ai-models/model-hosting.md @@ -30,6 +30,7 @@ Used for: * {% data variables.copilot.copilot_gpt_6_astra %} * {% data variables.copilot.copilot_gpt_6_luna %} * {% data variables.copilot.copilot_gpt_6_sol %} +* {% data variables.copilot.copilot_gpt_61_sol %} These models are hosted by OpenAI and {% data variables.product.github %}'s Azure infrastructure. diff --git a/content/copilot/reference/ai-models/supported-models.md b/content/copilot/reference/ai-models/supported-models.md index cc4530968d72..fb556cac70c8 100644 --- a/content/copilot/reference/ai-models/supported-models.md +++ b/content/copilot/reference/ai-models/supported-models.md @@ -97,6 +97,7 @@ Choosing a larger context window or higher reasoning will impact {% data variabl | {% data variables.copilot.copilot_gpt_6_astra %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | | {% data variables.copilot.copilot_gpt_6_luna %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | | {% data variables.copilot.copilot_gpt_6_sol %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | +| {% data variables.copilot.copilot_gpt_61_sol %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | | {% data variables.copilot.copilot_kimi_k3 %} | {% octicon "check" aria-label="Supported" %} | {% octicon "check" aria-label="Supported" %} | {% endrowheaders %} @@ -140,6 +141,7 @@ Some {% data variables.product.prodname_copilot_short %} models require minimum | {% data variables.copilot.copilot_gpt_6_astra %} | `1.136.1` | `17.14.19` | TBD | TBD | TBD | | {% data variables.copilot.copilot_gpt_6_luna %} | TBD | `17.14.19` | TBD | TBD | TBD | | {% data variables.copilot.copilot_gpt_6_sol %} | TBD | `17.14.19` | TBD | TBD | TBD | +| {% data variables.copilot.copilot_gpt_61_sol %} | TBD | `17.14.19` | TBD | TBD | TBD | | {% data variables.copilot.copilot_claude_opus_48 %} | `v1.118` | `17.14.6` | TBD | TBD | TBD | | {% data variables.copilot.copilot_claude_opus_5 %} | `v1.128.0` | `17.14.22` | TBD | TBD | TBD | | {% data variables.copilot.copilot_claude_opus_55 %} | TBD | `17.14.6` | TBD | TBD | TBD | diff --git a/content/copilot/reference/copilot-billing/models-and-pricing.md b/content/copilot/reference/copilot-billing/models-and-pricing.md index c316385ca524..b78eeffce4f1 100644 --- a/content/copilot/reference/copilot-billing/models-and-pricing.md +++ b/content/copilot/reference/copilot-billing/models-and-pricing.md @@ -33,7 +33,7 @@ All prices are **per 1 million tokens**. {% data reusables.copilot.extended-context-pricing %} -{% data variables.copilot.copilot_gpt_56_sol %}, {% data variables.copilot.copilot_gpt_56_terra %}, {% data variables.copilot.copilot_gpt_56_luna %}, {% data variables.copilot.copilot_gpt_6_astra %}, {% data variables.copilot.copilot_gpt_6_luna %}, and {% data variables.copilot.copilot_gpt_6_sol %} include a cache write cost in addition to cached input. Earlier OpenAI models have no cache write cost. +{% data variables.copilot.copilot_gpt_56_sol %}, {% data variables.copilot.copilot_gpt_56_terra %}, {% data variables.copilot.copilot_gpt_56_luna %}, {% data variables.copilot.copilot_gpt_6_astra %}, {% data variables.copilot.copilot_gpt_6_luna %}, {% data variables.copilot.copilot_gpt_6_sol %}, and {% data variables.copilot.copilot_gpt_61_sol %} include a cache write cost in addition to cached input. Earlier OpenAI models have no cache write cost. | Model | Release status | Category | Tier | Threshold (input tokens) | Input | Cached input | Cache write | Output | | --- | --- | --- | --- | --- | ---: | ---: | ---: | ---: | diff --git a/data/reusables/copilot/copilot-cloud-agent-non-auto-models.md b/data/reusables/copilot/copilot-cloud-agent-non-auto-models.md index d4d540cf1cae..03b55680a19e 100644 --- a/data/reusables/copilot/copilot-cloud-agent-non-auto-models.md +++ b/data/reusables/copilot/copilot-cloud-agent-non-auto-models.md @@ -14,6 +14,7 @@ * {% data variables.copilot.copilot_gpt_6_astra %} * {% data variables.copilot.copilot_gpt_6_luna %} * {% data variables.copilot.copilot_gpt_6_sol %} +* {% data variables.copilot.copilot_gpt_61_sol %} * {% data variables.copilot.copilot_grok_45 %} * {% data variables.copilot.copilot_grok_46 %} * {% data variables.copilot.copilot_grok_47 %} diff --git a/data/tables/copilot/model-comparison.yml b/data/tables/copilot/model-comparison.yml index e809ca6b35ac..b4aedd92909f 100644 --- a/data/tables/copilot/model-comparison.yml +++ b/data/tables/copilot/model-comparison.yml @@ -56,11 +56,16 @@ - name: GPT-6 Luna task_area: Fast help with simple or repetitive tasks excels_at: Quick, cost-efficient responses for smaller, faster tasks - further_reading: 'Coming soon' + further_reading: '[GPT-6 Luna model card](https://deploymentsafety.openai.com/gpt-6-astra/gpt-6-astra.pdf)' - name: GPT-6 Sol task_area: Interactive and agentic coding excels_at: All-round development tasks that benefit from careful, multistep validation + further_reading: '[GPT-6 Sol model card](https://deploymentsafety.openai.com/gpt-6-astra/gpt-6-astra.pdf)' + +- name: GPT-6.1 Sol + task_area: Complex coding tasks + excels_at: Advanced, efficient reasoning for complex coding tasks further_reading: 'Coming soon' # Anthropic diff --git a/data/tables/copilot/model-release-status.yml b/data/tables/copilot/model-release-status.yml index 2cee9f7eab8d..7dc65b595cae 100644 --- a/data/tables/copilot/model-release-status.yml +++ b/data/tables/copilot/model-release-status.yml @@ -63,6 +63,10 @@ provider: 'OpenAI' release_status: 'GA' +- name: 'GPT-6.1 Sol' + provider: 'OpenAI' + release_status: 'GA' + # Anthropic models - name: 'Claude Fable 5' diff --git a/data/tables/copilot/model-supported-plans.yml b/data/tables/copilot/model-supported-plans.yml index 1452069b07a9..ef37d4c026dc 100644 --- a/data/tables/copilot/model-supported-plans.yml +++ b/data/tables/copilot/model-supported-plans.yml @@ -201,6 +201,13 @@ business: true enterprise: true +- name: GPT-6.1 Sol + pro: false + pro_plus: true + max: true + business: true + enterprise: true + - name: Grok 4.5 pro: true pro_plus: true diff --git a/data/tables/copilot/models-and-pricing.yml b/data/tables/copilot/models-and-pricing.yml index 795f366a8493..8cddd0a838c0 100644 --- a/data/tables/copilot/models-and-pricing.yml +++ b/data/tables/copilot/models-and-pricing.yml @@ -240,6 +240,28 @@ output: $15.00 cache_write: $5.00 +- model: GPT-6.1 Sol + provider: openai + release_status: GA + category: Powerful + threshold: '≤ 272K' + tier: Default + input: $2.00 + cached_input: $0.10 + output: $10.00 + cache_write: $2.50 + +- model: GPT-6.1 Sol + provider: openai + release_status: GA + category: Powerful + threshold: '> 272K' + tier: 'Long context' + input: $4.00 + cached_input: $0.20 + output: $15.00 + cache_write: $5.00 + # Anthropic - model: Claude Haiku 4.5 provider: anthropic diff --git a/data/variables/copilot.yml b/data/variables/copilot.yml index 42d046597d72..e1bee4ee6b0e 100644 --- a/data/variables/copilot.yml +++ b/data/variables/copilot.yml @@ -237,6 +237,7 @@ copilot_gpt_56_terra: 'GPT-5.6 Terra' copilot_gpt_6_astra: 'GPT-6 Astra' copilot_gpt_6_luna: 'GPT-6 Luna' copilot_gpt_6_sol: 'GPT-6 Sol' +copilot_gpt_61_sol: 'GPT-6.1 Sol' # OpenAI 'o' series: copilot_o3: 'o3' copilot_o4_mini: 'o4-mini' From 5b8a33aae0052c06713415e161475c354a5a1a98 Mon Sep 17 00:00:00 2001 From: "Hector A." Date: Tue, 29 Sep 2026 18:01:31 +0000 Subject: [PATCH 2/4] Migrate CookBookFilter to Primer Brand (#63603) --- .../cookbook/examples/debugging.md | 14 +++ .../get-started/cookbook/examples/index.md | 8 ++ .../get-started/cookbook/examples/testing.md | 14 +++ .../content/get-started/cookbook/index.md | 16 +++ .../fixtures/content/get-started/index.md | 1 + .../tests/playwright-rendering.spec.ts | 80 ++++++++++++ src/frame/components/lib/action-menu.ts | 11 ++ .../components/CookBookFilter.module.scss | 46 ++++++- src/landings/components/CookBookFilter.tsx | 116 ++++++++++-------- .../shared/LandingArticleGridWithFilter.tsx | 9 +- 10 files changed, 254 insertions(+), 61 deletions(-) create mode 100644 src/fixtures/fixtures/content/get-started/cookbook/examples/debugging.md create mode 100644 src/fixtures/fixtures/content/get-started/cookbook/examples/index.md create mode 100644 src/fixtures/fixtures/content/get-started/cookbook/examples/testing.md create mode 100644 src/fixtures/fixtures/content/get-started/cookbook/index.md create mode 100644 src/frame/components/lib/action-menu.ts diff --git a/src/fixtures/fixtures/content/get-started/cookbook/examples/debugging.md b/src/fixtures/fixtures/content/get-started/cookbook/examples/debugging.md new file mode 100644 index 000000000000..5bfc0f206cc6 --- /dev/null +++ b/src/fixtures/fixtures/content/get-started/cookbook/examples/debugging.md @@ -0,0 +1,14 @@ +--- +title: Debug a workflow +intro: Diagnose a failed workflow. +versions: + fpt: '*' +category: + - Debugging code +surface: + - CLI +complexity: + - Advanced +--- + +Diagnose a failed workflow. diff --git a/src/fixtures/fixtures/content/get-started/cookbook/examples/index.md b/src/fixtures/fixtures/content/get-started/cookbook/examples/index.md new file mode 100644 index 000000000000..90e049c8d0dc --- /dev/null +++ b/src/fixtures/fixtures/content/get-started/cookbook/examples/index.md @@ -0,0 +1,8 @@ +--- +title: Cookbook examples +versions: + fpt: '*' +children: + - /testing + - /debugging +--- diff --git a/src/fixtures/fixtures/content/get-started/cookbook/examples/testing.md b/src/fixtures/fixtures/content/get-started/cookbook/examples/testing.md new file mode 100644 index 000000000000..8c9ecc542a83 --- /dev/null +++ b/src/fixtures/fixtures/content/get-started/cookbook/examples/testing.md @@ -0,0 +1,14 @@ +--- +title: Write unit tests +intro: Generate tests for a function. +versions: + fpt: '*' +category: + - Improve quality and maintainability +surface: + - Chat +complexity: + - Simple +--- + +Generate tests for a function. diff --git a/src/fixtures/fixtures/content/get-started/cookbook/index.md b/src/fixtures/fixtures/content/get-started/cookbook/index.md new file mode 100644 index 000000000000..387815b69fd4 --- /dev/null +++ b/src/fixtures/fixtures/content/get-started/cookbook/index.md @@ -0,0 +1,16 @@ +--- +title: Cookbook filters +intro: Test search and category landing filters. +versions: + fpt: '*' +layout: category-landing +filters: + - category + - surface + - complexity +spotlight: + - article: /examples/testing + image: /assets/images/placeholder.png +children: + - /examples +--- diff --git a/src/fixtures/fixtures/content/get-started/index.md b/src/fixtures/fixtures/content/get-started/index.md index 9d6cf97acd56..63568b0eb672 100644 --- a/src/fixtures/fixtures/content/get-started/index.md +++ b/src/fixtures/fixtures/content/get-started/index.md @@ -48,6 +48,7 @@ children: - /multi-carousel - /non-child-resolution - /discovery-filtered + - /cookbook communityRedirect: name: Provide HubGit Feedback href: 'https://hubgit.com/orgs/community/discussions/categories/get-started' diff --git a/src/fixtures/tests/playwright-rendering.spec.ts b/src/fixtures/tests/playwright-rendering.spec.ts index fa0e20479ab3..d59a4d672228 100644 --- a/src/fixtures/tests/playwright-rendering.spec.ts +++ b/src/fixtures/tests/playwright-rendering.spec.ts @@ -1634,6 +1634,86 @@ test.describe('Docs 2026 in-article navigation', () => { }) }) +test.describe('CookBookFilter component', () => { + const filters = [ + { name: 'Category', value: 'Improve quality and maintainability' }, + { name: 'Surface', value: 'Chat' }, + { name: 'Complexity', value: 'Simple' }, + ] + + for (const { name, value } of filters) { + test(`${name} filters articles`, async ({ page }) => { + await page.goto('/get-started/cookbook') + await expect(page.getByRole('heading', { name: 'Explore 2 examples' })).toBeVisible() + + const trigger = page.getByRole('button', { name: new RegExp(`^${name}:`) }) + await trigger.click() + const menu = page.getByRole('menu', { name, exact: true }) + await menu.getByRole('menuitemradio', { name: value, exact: true }).click() + + await expect(page.getByRole('heading', { name: 'Explore 1 examples' })).toBeVisible() + await expect(trigger).toHaveText(`${name}: ${value}`) + await trigger.click() + await expect(menu.getByRole('menuitemradio', { checked: true })).toHaveText(value) + }) + } + + test('search combines with filters and reset clears both', async ({ page }) => { + await page.goto('/get-started/cookbook') + for (const { name, value } of filters) { + await page.getByRole('button', { name: `${name}: All`, exact: true }).click() + await page.getByRole('menuitemradio', { name: value, exact: true }).click() + } + + const search = page.getByRole('textbox', { name: 'Search examples' }) + await search.fill('workflow') + await expect(page.getByRole('heading', { name: 'Explore 0 examples' })).toBeVisible() + await search.fill('tests') + await expect(page.getByRole('heading', { name: 'Explore 1 examples' })).toBeVisible() + + await page.getByRole('button', { name: 'Reset filters', exact: true }).click() + await expect(search).toHaveValue('') + await expect(page.getByRole('heading', { name: 'Explore 2 examples' })).toBeVisible() + for (const { name } of filters) { + await expect(page.getByRole('button', { name: `${name}: All`, exact: true })).toBeVisible() + } + }) + + for (const key of ['Enter', 'Space']) { + test(`category menu supports ${key} selection and Escape`, async ({ page }) => { + await page.goto('/get-started/cookbook') + const trigger = page.getByRole('button', { name: /^Category:/ }) + await trigger.focus() + await page.keyboard.press(key) + const menu = page.getByRole('menu', { name: 'Category', exact: true }) + await expect(menu.getByRole('menuitemradio', { name: 'All', exact: true })).toBeFocused() + await page.keyboard.press('ArrowDown') + await page.keyboard.press(key) + + await expect(menu).toHaveCount(0) + await expect(trigger).toBeFocused() + await expect(trigger).toContainText('Improve quality and maintainability') + await expect(page.getByRole('heading', { name: 'Explore 1 examples' })).toBeVisible() + await trigger.click() + await page.keyboard.press('Escape') + await expect(menu).toHaveCount(0) + await expect(trigger).toBeFocused() + }) + } + + test('long category options fit within the mobile viewport', async ({ page }) => { + await page.setViewportSize({ width: 320, height: 1000 }) + await page.goto('/get-started/cookbook') + await page.getByRole('button', { name: 'Category: All', exact: true }).click() + const menu = page.getByRole('menu', { name: 'Category', exact: true }) + await expect(menu).toBeVisible() + const bounds = await menu.boundingBox() + expect(bounds).not.toBeNull() + expect(bounds!.x).toBeGreaterThanOrEqual(0) + expect(bounds!.x + bounds!.width).toBeLessThanOrEqual(320) + }) +}) + test.describe('LandingArticleGridWithFilter component', () => { test('category menu selects once via keyboard and preserves URL state', async ({ page }) => { await page.goto('/get-started/article-grid-discovery?articles-filter=Grid&articles-page=2') diff --git a/src/frame/components/lib/action-menu.ts b/src/frame/components/lib/action-menu.ts new file mode 100644 index 000000000000..bb22ca001ba9 --- /dev/null +++ b/src/frame/components/lib/action-menu.ts @@ -0,0 +1,11 @@ +import type { KeyboardEvent } from 'react' + +// Brand's ActionMenu fires onSelect from both the overlay's own Enter listener +// and the focused Item's Enter/Space handler, double-invoking onSelect for one +// keypress. Route both keys through a single click instead. +export function onActionMenuItemKeyDownCapture(event: KeyboardEvent) { + if (event.key !== 'Enter' && event.key !== ' ') return + event.preventDefault() + event.stopPropagation() + event.currentTarget.click() +} diff --git a/src/landings/components/CookBookFilter.module.scss b/src/landings/components/CookBookFilter.module.scss index 7bf7407a36c9..c5d314db8569 100644 --- a/src/landings/components/CookBookFilter.module.scss +++ b/src/landings/components/CookBookFilter.module.scss @@ -1,5 +1,47 @@ -.textInput { - min-width: 100%; +.controls { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem; + padding: 0.25rem; +} + +.search { + flex: 1 1 16rem; + min-width: 0; +} + +.filters { + display: flex; + flex-wrap: wrap; + align-items: center; + gap: 0.5rem; + min-width: 0; + + // Brand adds a wrapper around each trigger and keeps its overlay inline. + > div { + min-width: 0; + max-width: 100%; + } + + [role="menu"] { + width: max-content; + min-width: 0; + max-width: calc(100vw - 2rem); + } + + // Brand's max-content item text otherwise forces long options past the viewport. + :global([class*="ActionMenu__item-text"]) { + width: auto; + } + + // Brand caps the button's label span at 200px and hides overflow, which wraps + // longer labels (like "Category: Author and optimize with Copilot") onto + // multiple lines instead of keeping them on one. + :global([class*="ActionMenu__button"]) > span:first-of-type { + max-width: none; + white-space: nowrap; + } } .categoryLabel { diff --git a/src/landings/components/CookBookFilter.tsx b/src/landings/components/CookBookFilter.tsx index 63a1acc652b0..99add55ce367 100644 --- a/src/landings/components/CookBookFilter.tsx +++ b/src/landings/components/CookBookFilter.tsx @@ -1,8 +1,8 @@ -import { TextInput, ActionMenu, ActionList } from '@primer/react' -import { Button } from '@primer/react-brand' +import { ActionMenu, Button, TextInput } from '@primer/react-brand' import { SearchIcon } from '@primer/octicons-react' import { useRef, useEffect, useState, type ChangeEvent } from 'react' import { ArticleCardItems } from '@/landings/types' +import { onActionMenuItemKeyDownCapture } from '@/frame/components/lib/action-menu' import { useTranslation } from '@/languages/components/useTranslation' import styles from './CookBookFilter.module.scss' @@ -68,15 +68,16 @@ export const CookBookFilter = ({ }, [isSearchOpen]) return ( -
-
+
+
e.preventDefault()}> } placeholder={t('search_articles')} + aria-label={t('search_articles')} ref={inputRef} - autoComplete="false" + autoComplete="off" onChange={(e: ChangeEvent) => { const query = e.target.value || '' onSearch(query) @@ -84,67 +85,79 @@ export const CookBookFilter = ({ />
-
- - +
+ onFilter(categories[Number(value)], 'category', Number(value))} + > + {t('category')}:{' '} {categories[selectedCategory]} - - - {categories.map((category, index) => ( - onFilter(category, 'category', index)} - > - {category} - - ))} - + + {categories.map((category, index) => ( + + {category} + + ))} {showSurface && ( - - + onFilter(surfaces[Number(value)], 'surface', Number(value))} + > + {t('surface')}:{' '} {surfaces[selectedSurface]} - - - {surfaces.map((surface, index) => ( - onFilter(surface, 'surface', index)} - > - {surface} - - ))} - + + {surfaces.map((surface, index) => ( + + {surface} + + ))} )} {showComplexity && ( - - - {t('complexity')}:{' '} + onFilter(complexities[Number(value)], 'complexity', Number(value))} + > + + {t('complexity')}:{' '} {complexities[selectedComplexity]} - - - {complexities.map((complexity, index) => ( - onFilter(complexity, 'complexity', index)} - > - {complexity} - - ))} - + + {complexities.map((complexity, index) => ( + + {complexity} + + ))} )} @@ -152,7 +165,6 @@ export const CookBookFilter = ({