From 2038b39c7bfb67d55106e3eefe8b3f4c56726a48 Mon Sep 17 00:00:00 2001 From: Sunbrye Ly <56200261+sunbrye@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:47:44 -0700 Subject: [PATCH 1/9] Enable Claude Sonnet 5 for Eclipse, Xcode, and JetBrains (#61991) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- data/tables/copilot/model-supported-clients.yml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/tables/copilot/model-supported-clients.yml b/data/tables/copilot/model-supported-clients.yml index e33839fa169d..a8755d060b9e 100644 --- a/data/tables/copilot/model-supported-clients.yml +++ b/data/tables/copilot/model-supported-clients.yml @@ -100,9 +100,9 @@ cli: true vscode: true vs: true - eclipse: false - xcode: false - jetbrains: false + eclipse: true + xcode: true + jetbrains: true - name: Gemini 2.5 Pro dotcom: false From 64c6022e03f88e57bef87a5c81e9bb9fc4926ee4 Mon Sep 17 00:00:00 2001 From: Sunbrye Ly <56200261+sunbrye@users.noreply.github.com> Date: Wed, 1 Jul 2026 13:48:44 -0700 Subject: [PATCH 2/9] [2026-06-30] Vision GA (#61970) Co-authored-by: Jason Chen --- .../copilot-cli/use-copilot-cli/overview.md | 14 ++++++++++++++ .../chat-with-copilot/chat-in-github.md | 4 ++-- .../copilot/image-pdf-attachment-handling.md | 1 + .../copilot/image-questions-and-file-types.md | 3 --- .../copilot/supported-attachment-file-types.md | 9 +++++++++ data/reusables/copilot/using-images-in-chat.md | 9 ++++++--- 6 files changed, 32 insertions(+), 8 deletions(-) create mode 100644 data/reusables/copilot/image-pdf-attachment-handling.md create mode 100644 data/reusables/copilot/supported-attachment-file-types.md diff --git a/content/copilot/how-tos/copilot-cli/use-copilot-cli/overview.md b/content/copilot/how-tos/copilot-cli/use-copilot-cli/overview.md index 5c330a1b9336..f8ceb71ca138 100644 --- a/content/copilot/how-tos/copilot-cli/use-copilot-cli/overview.md +++ b/content/copilot/how-tos/copilot-cli/use-copilot-cli/overview.md @@ -95,6 +95,20 @@ To add a specific file to your prompt, use `@` followed by the relative path to When you start typing a file path, the matching paths are displayed below the prompt box. Use the arrow keys to select a path and press Tab to complete the path in your prompt. +### Attach images and PDFs + +You can attach images and PDFs to your prompts when using a model that supports image input. + +{% data reusables.copilot.supported-attachment-file-types %} + +{% data reusables.copilot.image-pdf-attachment-handling %} + +You can attach a file in the following ways during an interactive session: + +* Reference the file in your prompt using `@` followed by the path to the file. +* Drag and drop a file into the interactive session. +* Copy an image to your clipboard, then paste it as an attachment. + ### Work with files in a different location To complete a task, {% data variables.product.prodname_copilot_short %} may need to work with files that are outside the current working directory. If a prompt you have entered in an interactive session requires {% data variables.product.prodname_copilot_short %} to modify a file outside the current location, it will ask you to approve access to the file's directory. diff --git a/content/copilot/how-tos/copilot-on-github/chat-with-copilot/chat-in-github.md b/content/copilot/how-tos/copilot-on-github/chat-with-copilot/chat-in-github.md index 47bb3dada0c6..2586826dcb71 100644 --- a/content/copilot/how-tos/copilot-on-github/chat-with-copilot/chat-in-github.md +++ b/content/copilot/how-tos/copilot-on-github/chat-with-copilot/chat-in-github.md @@ -68,9 +68,9 @@ The response to your edited question is displayed in a new subthread. An edit co ### Using images in {% data variables.copilot.copilot_chat_short %} -> [!NOTE] This feature is currently in {% data variables.release-phases.public_preview %} and subject to change. +{% data reusables.copilot.using-images-in-chat %} -You can attach images to your prompts by pasting, dragging, or clicking {% octicon "plus" aria-label="Add attachment" %} in the prompt box and then selecting **{% octicon "file-code" aria-hidden="true" %} Upload from computer**. Select a model that supports images from the model picker. For supported file types and example questions, see [AUTOTITLE](/copilot/how-tos/use-copilot-agents/coding-agent/provide-visual-inputs). +To attach a file, drag and drop it into the prompt box, or click {% octicon "plus" aria-label="Add attachment" %} and select **{% octicon "file-code" aria-hidden="true" %} Upload from computer**. Select a model that supports image input from the model picker. ### Continuing a conversation alongside an agent session diff --git a/data/reusables/copilot/image-pdf-attachment-handling.md b/data/reusables/copilot/image-pdf-attachment-handling.md new file mode 100644 index 000000000000..f358b80122d9 --- /dev/null +++ b/data/reusables/copilot/image-pdf-attachment-handling.md @@ -0,0 +1 @@ +Image and PDF attachments are available on all {% data variables.product.prodname_copilot_short %} plans and are enabled by default, with no policy required to turn the feature on or off. diff --git a/data/reusables/copilot/image-questions-and-file-types.md b/data/reusables/copilot/image-questions-and-file-types.md index 00d094d6948a..cbe9bea44a43 100644 --- a/data/reusables/copilot/image-questions-and-file-types.md +++ b/data/reusables/copilot/image-questions-and-file-types.md @@ -2,6 +2,3 @@ * A mockup of the user interface for an application and ask {% data variables.product.prodname_copilot_short %} to generate the code. * A flowchart and ask {% data variables.product.prodname_copilot_short %} to describe the processes shown in the image. * A screenshot of a web page and ask {% data variables.product.prodname_copilot_short %} to generate HTML for a similar page. - -> [!NOTE] -> The following types of image file are supported: JPEG (`.jpg`, `.jpeg`), PNG (`.png`), GIF (`.gif`), or WEBP (`.webp`). diff --git a/data/reusables/copilot/supported-attachment-file-types.md b/data/reusables/copilot/supported-attachment-file-types.md new file mode 100644 index 000000000000..09a179cc3e94 --- /dev/null +++ b/data/reusables/copilot/supported-attachment-file-types.md @@ -0,0 +1,9 @@ +{% data variables.product.prodname_copilot_short %} supports the following file types: + +* JPEG (`.jpg`, `.jpeg`) +* PNG (`.png`) +* GIF (`.gif`) +* WEBP (`.webp`) +* PDF (`.pdf`) +* HEIC (`.heic`) +* HEIF (`.heif`) diff --git a/data/reusables/copilot/using-images-in-chat.md b/data/reusables/copilot/using-images-in-chat.md index 8c5f73111984..faee89a50e52 100644 --- a/data/reusables/copilot/using-images-in-chat.md +++ b/data/reusables/copilot/using-images-in-chat.md @@ -1,6 +1,9 @@ -> [!NOTE] -> * {% data reusables.copilot.editor-preview-settings %} +You can attach images and PDFs to your prompts when using a model that supports image input. -You can attach images to your chat prompts and then ask {% data variables.product.prodname_copilot_short %} about the images. For example, you can attach: +{% data reusables.copilot.supported-attachment-file-types %} + +For example, you can attach: {% data reusables.copilot.image-questions-and-file-types %} + +{% data reusables.copilot.image-pdf-attachment-handling %} From 5e963dc4b8f9d9a9525854e6f7990050479a4238 Mon Sep 17 00:00:00 2001 From: Evan Bonsignori Date: Wed, 1 Jul 2026 14:49:34 -0700 Subject: [PATCH 3/9] Show checkmark on Copy as Markdown button after copy (#61954) --- .../tests/playwright-rendering.spec.ts | 35 +++++++++++++++++++ .../components/article/ViewMarkdownButton.tsx | 21 +++++++++-- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/fixtures/tests/playwright-rendering.spec.ts b/src/fixtures/tests/playwright-rendering.spec.ts index c9dc604eacc0..8041a1c6165a 100644 --- a/src/fixtures/tests/playwright-rendering.spec.ts +++ b/src/fixtures/tests/playwright-rendering.spec.ts @@ -1534,3 +1534,38 @@ test.describe('Non-child page resolution', () => { // The detailed sidebar filtering is tested by the survey test which verifies no duplicate entries }) }) + +test.describe('copy as markdown button', () => { + // The article-body fetch backing this button is served for this fixture page + // (see src/fixtures/tests/api-article-body.ts), so the copy path succeeds. + const articlePath = '/en/get-started/start-your-journey/api-article-body-test-page' + + test('swaps the copy icon for a checkmark after a successful copy', async ({ page, context }) => { + // The click handler writes the article markdown to the clipboard. + await context.grantPermissions(['clipboard-read', 'clipboard-write']) + + await page.goto(articlePath) + await turnOffExperimentsInPage(page) + + const copyButton = page.getByRole('button', { name: 'Copy as Markdown' }) + await expect(copyButton).toBeVisible() + + // Before clicking, the leading icon is the copy icon, not the checkmark. + await expect(copyButton.locator('.octicon-copy')).toBeVisible() + await expect(copyButton.locator('.octicon-check')).toHaveCount(0) + + await copyButton.click() + + // After a successful copy, the icon swaps to a checkmark... + await expect(copyButton.locator('.octicon-check')).toBeVisible() + await expect(copyButton.locator('.octicon-copy')).toHaveCount(0) + + // ...and the article markdown lands on the clipboard. + const clipboardText = await page.evaluate(() => navigator.clipboard.readText()) + expect(clipboardText).toContain('About GitHub') + + // The checkmark is temporary and reverts to the copy icon (2s timeout). + await expect(copyButton.locator('.octicon-copy')).toBeVisible({ timeout: 5000 }) + await expect(copyButton.locator('.octicon-check')).toHaveCount(0) + }) +}) diff --git a/src/frame/components/article/ViewMarkdownButton.tsx b/src/frame/components/article/ViewMarkdownButton.tsx index 63701f327a03..f42f25bf13f1 100644 --- a/src/frame/components/article/ViewMarkdownButton.tsx +++ b/src/frame/components/article/ViewMarkdownButton.tsx @@ -1,5 +1,6 @@ -import { useCallback } from 'react' +import { useCallback, useEffect, useRef, useState } from 'react' import { + CheckIcon, CopyIcon, CopilotIcon, FileIcon, @@ -22,6 +23,15 @@ interface CopyMarkdownMenuProps { export const CopyMarkdownMenu = ({ currentPath }: CopyMarkdownMenuProps) => { const { t } = useTranslation('pages') + const [copied, setCopied] = useState(false) + const timeoutRef = useRef | null>(null) + + useEffect(() => { + return () => { + if (timeoutRef.current) clearTimeout(timeoutRef.current) + } + }, []) + const encodedPath = encodeURIComponent(currentPath).replace(/%2F/g, '/').replace(/%40/g, '@') const markdownUrl = `/api/article/body?pathname=${encodedPath}` @@ -64,6 +74,9 @@ export const CopyMarkdownMenu = ({ currentPath }: CopyMarkdownMenuProps) => { const text = await res.text() await navigator.clipboard.writeText(text) announce(t('copied')) + setCopied(true) + if (timeoutRef.current) clearTimeout(timeoutRef.current) + timeoutRef.current = setTimeout(() => setCopied(false), 2000) } catch { // Fallback: open in new tab if fetch or clipboard fails window.open(markdownUrl, '_blank') @@ -81,7 +94,11 @@ export const CopyMarkdownMenu = ({ currentPath }: CopyMarkdownMenuProps) => { )} onClick={handleCopyClick} > -