diff --git a/extensions/copilot/.github/instructions/model-prompts.instructions.md b/extensions/copilot/.github/instructions/model-prompts.instructions.md index ef3eb752eff9..10a5373be1a7 100644 --- a/extensions/copilot/.github/instructions/model-prompts.instructions.md +++ b/extensions/copilot/.github/instructions/model-prompts.instructions.md @@ -21,12 +21,13 @@ Registration order matters within each phase. Register broad provider defaults t ### OpenAI Default -Unrecognized GPT families and endpoints identified as OpenAI use the latest approved GPT prompt bundle. The single promotion point is the `LatestOpenAIPromptResolver` import in `openai/latestOpenAIPrompt.ts`, currently GPT-5.6. It reuses the entire resolver, including reminders, identity, safety, tool-reference hints, and user-query tag defaults, without copying prompt text. +Unrecognized GPT families and endpoints identified as OpenAI use the latest approved GPT prompt bundle. The single promotion point is the `LatestOpenAIPromptResolver` import in `openai/latestOpenAIPrompt.ts`, currently GPT-6 Astra. It reuses the entire resolver, including reminders, identity, safety, tool-reference hints, and user-query tag defaults, without copying prompt text. - Do not add a prompt file just because a new OpenAI model ships. Add a dedicated resolver only when the model needs different instructions. - Existing specialized GPT/Codex resolvers and the explicitly retained legacy families in `defaultOpenAIPrompt.tsx` take precedence. Version matchers must distinguish `gpt-5.1` and its hyphenated variants from `gpt-5.10`. - OpenAI provider metadata can identify opaque preview names; an OpenAI-compatible API alone does not establish OpenAI model identity. Explicit family routing takes precedence over the provider fallback. -- Prompt inheritance must not alias the endpoint family or enable GPT-5.6-specific API/tool capabilities. Rendering still respects the actual endpoint's capabilities and available tools. +- Prompt inheritance must not alias the endpoint family or enable GPT-6-specific API/tool capabilities. Rendering still respects the actual endpoint's capabilities and available tools. +- Hidden model I is explicitly matched by the GPT-6 resolver and included alongside GPT-6 capability and instruction gates, independently of the provider fallback. Its model ID and family remain unchanged. - To promote a new default, update the resolver import in `latestOpenAIPrompt.ts` and the expected default in `test/openAIPrompts.spec.ts`. Run its routing/rendering tests and the existing agent prompt snapshots. Keep older specialized resolvers unchanged. ### Resolver Interface diff --git a/extensions/copilot/src/extension/prompts/node/agent/defaultAgentInstructions.tsx b/extensions/copilot/src/extension/prompts/node/agent/defaultAgentInstructions.tsx index ce9e8b74c532..b95f24c1e058 100644 --- a/extensions/copilot/src/extension/prompts/node/agent/defaultAgentInstructions.tsx +++ b/extensions/copilot/src/extension/prompts/node/agent/defaultAgentInstructions.tsx @@ -6,7 +6,7 @@ import { BasePromptElementProps, PromptElement, PromptSizing } from '@vscode/prompt-tsx'; import type { LanguageModelToolInformation } from 'vscode'; import { ConfigKey, IConfigurationService } from '../../../../platform/configuration/common/configurationService'; -import { isGpt5PlusFamily, isGpt6Family } from '../../../../platform/endpoint/common/chatModelCapabilities'; +import { isGpt5PlusFamily, isGpt6Family, isHiddenModelI } from '../../../../platform/endpoint/common/chatModelCapabilities'; import { IChatEndpoint } from '../../../../platform/networking/common/networking'; import { IPromptPathRepresentationService } from '../../../../platform/prompts/common/promptPathRepresentationService'; import { IExperimentationService } from '../../../../platform/telemetry/common/nullExperimentationService'; @@ -480,12 +480,12 @@ export class ApplyPatchInstructions extends PromptElement To edit files in the workspace, use the {ToolName.ApplyPatch} tool. If you have issues with it, you should first try to fix your patch and continue using {ToolName.ApplyPatch}. {this.props.tools[ToolName.EditFile] && <>If you are stuck, you can fall back on the {ToolName.EditFile} tool, but {ToolName.ApplyPatch} is much faster and is the preferred tool.}
- {isGpt5OrGpt6 && <>Prefer the smallest set of changes needed to satisfy the task. Avoid reformatting unrelated code; preserve existing style and public APIs unless the task requires changes. When practical, complete all edits for a file within a single message.
} + {supportsModernPatchInstructions && <>Prefer the smallest set of changes needed to satisfy the task. Avoid reformatting unrelated code; preserve existing style and public APIs unless the task requires changes. When practical, complete all edits for a file within a single message.
} {!useSimpleInstructions && <> The tool call requires both `input`, a string representing the patch to apply, and `explanation`, a short description of what the patch aims to achieve. The input follows a special format. For each snippet of code that needs to be changed, repeat the following:

diff --git a/extensions/copilot/src/extension/prompts/node/agent/openai/gpt6Prompt.tsx b/extensions/copilot/src/extension/prompts/node/agent/openai/gpt6Prompt.tsx index 0b1a0df4b33c..0e9394be16df 100644 --- a/extensions/copilot/src/extension/prompts/node/agent/openai/gpt6Prompt.tsx +++ b/extensions/copilot/src/extension/prompts/node/agent/openai/gpt6Prompt.tsx @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import { PromptElement, PromptSizing } from '@vscode/prompt-tsx'; -import { isGpt6Family } from '../../../../../platform/endpoint/common/chatModelCapabilities'; +import { isGpt6Family, isHiddenModelI } from '../../../../../platform/endpoint/common/chatModelCapabilities'; import { IChatEndpoint } from '../../../../../platform/networking/common/networking'; import { ToolName } from '../../../../tools/common/toolNames'; import { Gpt55CopilotIdentityRule as Gpt6CopilotIdentityRule } from '../../base/copilotIdentity'; @@ -263,7 +263,7 @@ class Gpt6Prompt extends PromptElement { export class Gpt6PromptResolver implements IAgentPrompt { static async matchesModel(endpoint: IChatEndpoint): Promise { - return isGpt6Family(endpoint); + return isGpt6Family(endpoint) || isHiddenModelI(endpoint); } static readonly familyPrefixes = []; diff --git a/extensions/copilot/src/extension/prompts/node/agent/openai/latestOpenAIPrompt.ts b/extensions/copilot/src/extension/prompts/node/agent/openai/latestOpenAIPrompt.ts index e2b2a05aec2c..58ab13f4256f 100644 --- a/extensions/copilot/src/extension/prompts/node/agent/openai/latestOpenAIPrompt.ts +++ b/extensions/copilot/src/extension/prompts/node/agent/openai/latestOpenAIPrompt.ts @@ -5,7 +5,7 @@ import { isOpenAIModel } from '../../../../../platform/endpoint/common/chatModelCapabilities'; import { PromptRegistry } from '../promptRegistry'; -import { Gpt56PromptResolver as LatestOpenAIPromptResolver } from './gpt56Prompt'; +import { Gpt6PromptResolver as LatestOpenAIPromptResolver } from './gpt6Prompt'; // Promote the entire prompt bundle by changing the resolver imported above. PromptRegistry.registerFallbackPrompt(LatestOpenAIPromptResolver, isOpenAIModel); diff --git a/extensions/copilot/src/extension/prompts/node/agent/test/applyPatchInstructions.spec.tsx b/extensions/copilot/src/extension/prompts/node/agent/test/applyPatchInstructions.spec.tsx index 643bfeba7b14..ba92140fc833 100644 --- a/extensions/copilot/src/extension/prompts/node/agent/test/applyPatchInstructions.spec.tsx +++ b/extensions/copilot/src/extension/prompts/node/agent/test/applyPatchInstructions.spec.tsx @@ -36,6 +36,7 @@ suite('ApplyPatchInstructions model gates', () => { ['gpt-6', true], ['gpt-6-preview', true], ['gpt-6.1', true], + ['testing-for-latest-prompt', false], ['gpt-4.1', false], [undefined, false], ] as const)('preserves patch instructions and experiment gating for %s', async (family, supported) => { diff --git a/extensions/copilot/src/extension/prompts/node/agent/test/openAIPrompts.spec.ts b/extensions/copilot/src/extension/prompts/node/agent/test/openAIPrompts.spec.ts index 0dedd2d20493..113e284786fa 100644 --- a/extensions/copilot/src/extension/prompts/node/agent/test/openAIPrompts.spec.ts +++ b/extensions/copilot/src/extension/prompts/node/agent/test/openAIPrompts.spec.ts @@ -51,7 +51,7 @@ suite('OpenAI prompt fallback', () => { ['preview-model', 'OpenAI'], ['preview-model', 'openai'], ])('%s from %s inherits the entire latest prompt bundle', async (family, provider) => { - expect(await resolve(createEndpoint(family, provider))).toEqual(await resolve(createEndpoint('gpt-5.6'))); + expect(await resolve(createEndpoint(family, provider))).toEqual(await resolve(createEndpoint('gpt-6-astra'))); }); test.each([ diff --git a/extensions/copilot/src/extension/tools/node/manageTodoListTool.tsx b/extensions/copilot/src/extension/tools/node/manageTodoListTool.tsx index d6f69098b59b..bf390768e566 100644 --- a/extensions/copilot/src/extension/tools/node/manageTodoListTool.tsx +++ b/extensions/copilot/src/extension/tools/node/manageTodoListTool.tsx @@ -4,7 +4,7 @@ *--------------------------------------------------------------------------------------------*/ import type * as vscode from 'vscode'; -import { isGpt5PlusFamily, isGpt6Family } from '../../../platform/endpoint/common/chatModelCapabilities'; +import { isGpt5PlusFamily, isGpt6Family, isHiddenModelI } from '../../../platform/endpoint/common/chatModelCapabilities'; import { IChatEndpoint } from '../../../platform/networking/common/networking'; import { ToolName } from '../common/toolNames'; import { ICopilotTool, ToolRegistry } from '../common/toolsRegistry'; @@ -17,7 +17,7 @@ class ManageTodoListTool implements ICopilotTool { public static readonly nonDeferred = true; alternativeDefinition(tool: vscode.LanguageModelToolInformation, endpoint?: IChatEndpoint): vscode.LanguageModelToolInformation { - if (!isGpt5PlusFamily(endpoint) && (!endpoint || !isGpt6Family(endpoint))) { + if (!isGpt5PlusFamily(endpoint) && (!endpoint || (!isGpt6Family(endpoint) && !isHiddenModelI(endpoint)))) { return tool; } diff --git a/extensions/copilot/src/extension/tools/node/test/manageTodoListTool.spec.ts b/extensions/copilot/src/extension/tools/node/test/manageTodoListTool.spec.ts index becd282b6f50..ac9f7838d990 100644 --- a/extensions/copilot/src/extension/tools/node/test/manageTodoListTool.spec.ts +++ b/extensions/copilot/src/extension/tools/node/test/manageTodoListTool.spec.ts @@ -27,6 +27,7 @@ suite('ManageTodoListTool model override', () => { ['gpt-6', true], ['gpt-6-preview', true], ['gpt-6.1', true], + ['testing-for-latest-prompt', false], ['gpt-4.1', false], [undefined, false], ] as const)('uses the plan description for %s: %s', (family, supported) => { diff --git a/extensions/copilot/src/platform/endpoint/common/chatModelCapabilities.ts b/extensions/copilot/src/platform/endpoint/common/chatModelCapabilities.ts index eb1e945a420d..f369a393246d 100644 --- a/extensions/copilot/src/platform/endpoint/common/chatModelCapabilities.ts +++ b/extensions/copilot/src/platform/endpoint/common/chatModelCapabilities.ts @@ -8,12 +8,6 @@ import { getCachedSha256Hash } from '../../../util/common/crypto'; import { ConfigKey, IConfigurationService } from '../../configuration/common/configurationService'; import type { IChatEndpoint } from '../../networking/common/networking'; -const HIDDEN_MODEL_A_HASHES = [ - 'a99dd17dfee04155d863268596b7f6dd36d0a6531cd326348dbe7416142a21a3', - '6b0f165d0590bf8d508540a796b4fda77bf6a0a4ed4e8524d5451b1913100a95' -]; - - const HIDDEN_MODEL_B_HASHES = [ '1f48b3271e760c69ab2b17dcae5f5c661fa5b644c5976a8a99b23e05ae3cb6d6', 'ffc50c70661c227edf8daae6f8dbed2dd0645386c12d43bc7fc44da166e043bd', @@ -51,10 +45,6 @@ const VSC_MODEL_HASHES_EDIT_TOOL_SET = [ 'e82ff0e2d4e4bae1f012dc599d520f8d61becfc4762f3717577b270be199db92', ]; -const HIDDEN_MODEL_E_HASHES: string[] = [ - '6013de0381f648b7f21518885c02b40b7583adfb33c6d9b64d3aed52c3934798' -]; - const HIDDEN_MODEL_F_HASHES: string[] = [ 'ab45e8474269b026f668d49860b36850122e18a50d5ea38f3fefdae08261865c', '9542d5c077c2bc379f92be32272b14be8b94a8841323465db0d5b3d6f4f0dab0', @@ -73,6 +63,13 @@ const HIDDEN_FAMILY_H_HASHES: string[] = [ '70fcded3f255d368e868cc807d8838a62108bfa5c86ce7d37966f58cda229e33', ]; +const HIDDEN_FAMILY_I_HASHES: string[] = [ + 'fce41f783960b53a2421c88c5492f80cdb1e04cce13e0a2c90153290d85edc72', + 'aa53bc5ce0c03800cb12d77bcbadad5fd6f932f19aa48ddd6cde7690e4c5f628', + '93160c45252a00e9594f286d814b5af7cef4e10b59a8b58cbf01d603631027ca' +]; + + /** * Per-model capability override. Lets advanced users (and evals) alias an * unknown/preview model id to a known production family for capability @@ -110,20 +107,9 @@ export function getModelId(model: LanguageModelChat | IChatEndpoint): string { return 'id' in model ? model.id : model.model; } -export function isHiddenModelA(model: LanguageModelChat | IChatEndpoint) { - const h = getCachedSha256Hash(model.family); - return HIDDEN_MODEL_A_HASHES.includes(h); -} - -export function isHiddenModelB(model: LanguageModelChat | IChatEndpoint | string) { - const h = getCachedSha256Hash(typeof model === 'string' ? model : model.family); - return HIDDEN_MODEL_B_HASHES.includes(h); -} - - -export function isHiddenModelE(model: LanguageModelChat | IChatEndpoint) { - const h = getCachedSha256Hash(model.family); - return HIDDEN_MODEL_E_HASHES.includes(h); +export function isHiddenModelI(model: LanguageModelChat | IChatEndpoint | string) { + const i = getCachedSha256Hash(typeof model === 'string' ? model : model.family); + return HIDDEN_FAMILY_I_HASHES.includes(i); } export function isHiddenModelF(model: LanguageModelChat | IChatEndpoint) { @@ -269,9 +255,10 @@ export function modelSupportsApplyPatch(model: LanguageModelChat | IChatEndpoint || isVSCModelB(model) || isGpt52Family(model.family) || isGpt54(model) - || isHiddenModelB(model) + || isGpt55(model) || isGpt56(model) - || isGpt6Family(model); + || isGpt6Family(model) + || isHiddenModelI(model); } /** @@ -284,9 +271,10 @@ export function modelPrefersJsonNotebookRepresentation(model: LanguageModelChat || isGpt53Codex(model.family) || isGpt52Family(model.family) || isGpt54(model) - || isHiddenModelB(model) + || isGpt55(model) || isGpt56(model) - || isGpt6Family(model); + || isGpt6Family(model) + || isHiddenModelI(model); } /** @@ -300,7 +288,7 @@ export function modelSupportsReplaceString(model: LanguageModelChat | IChatEndpo * Model supports multi_replace_string_in_file as an edit tool. */ export function modelSupportsMultiReplaceString(model: LanguageModelChat | IChatEndpoint): boolean { - return isAnthropicFamily(model) || isXAiFamily(model) || isHiddenModelE(model) || isVSCModelReplaceStringSet(model) || isMinimaxFamily(model) || isHiddenFamilyH(model) || isKimiFamily(model); + return isAnthropicFamily(model) || isXAiFamily(model) || isVSCModelReplaceStringSet(model) || isMinimaxFamily(model) || isHiddenFamilyH(model) || isKimiFamily(model); } /** @@ -308,7 +296,7 @@ export function modelSupportsMultiReplaceString(model: LanguageModelChat | IChat * without needing insert_edit_into_file. */ export function modelCanUseReplaceStringExclusively(model: LanguageModelChat | IChatEndpoint): boolean { - return isAnthropicFamily(model) || isXAiFamily(model) || isHiddenModelE(model) || model.family.toLowerCase().includes('gemini-3') || isVSCModelReplaceStringSet(model) || isHiddenModelF(model) || isMinimaxFamily(model) || isHiddenFamilyH(model) || isKimiFamily(model); + return isAnthropicFamily(model) || isXAiFamily(model) || model.family.toLowerCase().includes('gemini-3') || isVSCModelReplaceStringSet(model) || isHiddenModelF(model) || isMinimaxFamily(model) || isHiddenFamilyH(model) || isKimiFamily(model); } /** @@ -323,7 +311,7 @@ export function modelShouldUseReplaceStringHealing(model: LanguageModelChat | IC * The model can accept image urls as the `image_url` parameter in mcp tool results. */ export function modelCanUseMcpResultImageURL(model: LanguageModelChat | IChatEndpoint): boolean { - return !isAnthropicFamily(model) && !isHiddenModelE(model); + return !isAnthropicFamily(model); } /** @@ -337,7 +325,7 @@ export function modelCanUseImageURL(model: LanguageModelChat | IChatEndpoint): b * The model supports native PDF document processing via document content parts. */ export function modelSupportsPDFDocuments(model: LanguageModelChat | IChatEndpoint): boolean { - return isAnthropicFamily(model) || isGpt5PlusFamily(model) || isGpt56(model) || isGpt6Family(model); + return isAnthropicFamily(model) || isGpt5PlusFamily(model) || isGpt56(model) || isGpt6Family(model) || isHiddenModelI(model); } /** @@ -346,7 +334,7 @@ export function modelSupportsPDFDocuments(model: LanguageModelChat | IChatEndpoi * only, since this is an OpenAI-specific Responses API feature. */ export function modelSupportCacheBreakPoints(model: LanguageModelChat | IChatEndpoint): boolean { - return isGpt56(model) || isGpt6Family(model); + return isGpt56(model) || isGpt6Family(model) || isHiddenModelI(model); } /** @@ -358,7 +346,7 @@ export function modelCanUseApplyPatchExclusively(model: LanguageModelChat | ICha if (isVSCModelReplaceStringSet(model)) { return false; } - return isGpt5PlusFamily(model) || isGpt6Family(model) || isVSCModelA(model) || isVSCModelB(model); + return isGpt5PlusFamily(model) || isGpt6Family(model) || isHiddenModelI(model) || isVSCModelA(model) || isVSCModelB(model); } /** @@ -374,7 +362,7 @@ export function modelNeedsStrongReplaceStringHint(model: LanguageModelChat | ICh * Model can take the simple, modern apply_patch instructions. */ export function modelSupportsSimplifiedApplyPatchInstructions(model: LanguageModelChat | IChatEndpoint): boolean { - return isGpt5PlusFamily(model) || isGpt6Family(model) || isVSCModelA(model) || isVSCModelB(model); + return isGpt5PlusFamily(model) || isGpt6Family(model) || isHiddenModelI(model) || isVSCModelA(model) || isVSCModelB(model); } export function isAnthropicFamily(model: LanguageModelChat | IChatEndpoint): boolean { @@ -461,7 +449,7 @@ export function isOpenAIModel(model: Pick