mirror of
https://github.com/microsoft/vscode.git
synced 2026-09-30 06:58:55 +01:00
@@ -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
|
||||
|
||||
@@ -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<DefaultAgentPromptProp
|
||||
}
|
||||
|
||||
async render(state: void, sizing: PromptSizing) {
|
||||
const isGpt5OrGpt6 = isGpt5PlusFamily(this.props.modelFamily) || (this.props.modelFamily !== undefined && isGpt6Family(this.props.modelFamily));
|
||||
const useSimpleInstructions = isGpt5OrGpt6 && this.configurationService.getExperimentBasedConfig(ConfigKey.Advanced.Gpt5AlternativePatch, this._experimentationService);
|
||||
const supportsModernPatchInstructions = isGpt5PlusFamily(this.props.modelFamily) || (this.props.modelFamily !== undefined && (isGpt6Family(this.props.modelFamily) || isHiddenModelI(this.props.modelFamily)));
|
||||
const useSimpleInstructions = supportsModernPatchInstructions && this.configurationService.getExperimentBasedConfig(ConfigKey.Advanced.Gpt5AlternativePatch, this._experimentationService);
|
||||
|
||||
return <Tag name='applyPatchInstructions'>
|
||||
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.</>}<br />
|
||||
{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.<br /></>}
|
||||
{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.<br /></>}
|
||||
{!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:<br />
|
||||
<ApplyPatchFormatInstructions /><br />
|
||||
|
||||
@@ -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<DefaultAgentPromptProps> {
|
||||
export class Gpt6PromptResolver implements IAgentPrompt {
|
||||
|
||||
static async matchesModel(endpoint: IChatEndpoint): Promise<boolean> {
|
||||
return isGpt6Family(endpoint);
|
||||
return isGpt6Family(endpoint) || isHiddenModelI(endpoint);
|
||||
}
|
||||
|
||||
static readonly familyPrefixes = [];
|
||||
|
||||
@@ -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);
|
||||
|
||||
+1
@@ -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) => {
|
||||
|
||||
@@ -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([
|
||||
|
||||
@@ -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<unknown> {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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) => {
|
||||
|
||||
@@ -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<IChatEndpoint, 'family' | 'modelProvid
|
||||
* This takes a sync shortcut and should only be called when a model hash would have already been computed while rendering the prompt.
|
||||
*/
|
||||
export function getVerbosityForModelSync(model: IChatEndpoint, responsesApiVerbosityEnabled?: boolean): 'low' | 'medium' | 'high' | undefined {
|
||||
if (model.family === 'gpt-5.1' || model.family === 'gpt-5-mini' || ((isGpt56(model) || isGpt6Family(model)) && responsesApiVerbosityEnabled)) {
|
||||
if (model.family === 'gpt-5.1' || model.family === 'gpt-5-mini' || ((isGpt56(model) || isGpt6Family(model) || isHiddenModelI(model)) && responsesApiVerbosityEnabled)) {
|
||||
return 'low';
|
||||
}
|
||||
return undefined;
|
||||
@@ -473,6 +461,7 @@ export function getVerbosityForModelSync(model: IChatEndpoint, responsesApiVerbo
|
||||
* new and future Claude models are picked up automatically. The pre-4.5
|
||||
* generations are denied explicitly.
|
||||
* - OpenAI gpt-5.4, gpt-5.5, gpt-5.6, and gpt-6 families (via Responses API client-side tool search)
|
||||
* - Hidden model I (via Responses API client-side tool search)
|
||||
*
|
||||
* Accepts either an id string, a {@link LanguageModelChat}, or an
|
||||
* {@link IChatEndpoint} — when given an endpoint/chat the model **family**
|
||||
@@ -482,11 +471,11 @@ export function getVerbosityForModelSync(model: IChatEndpoint, responsesApiVerbo
|
||||
export function modelSupportsToolSearch(model: LanguageModelChat | IChatEndpoint | string): boolean {
|
||||
const id = typeof model === 'string' ? model : getModelId(model);
|
||||
const family = typeof model === 'string' ? model : model.family;
|
||||
const isGpt56OrGpt6 = isGpt56(model) || isGpt6Family(model);
|
||||
const hasToolSearchFamily = isGpt56(model) || isGpt6Family(model) || isHiddenModelI(model);
|
||||
const matches = (s: string) => {
|
||||
const n = s.toLowerCase().replace(/\./g, '-');
|
||||
// OpenAI models with client-side tool search.
|
||||
if (n === 'gpt-5-4' || n === 'gpt-5-5' || isGpt56OrGpt6) {
|
||||
if (n === 'gpt-5-4' || n === 'gpt-5-5' || hasToolSearchFamily) {
|
||||
return true;
|
||||
}
|
||||
if (!n.startsWith('claude')) {
|
||||
|
||||
Reference in New Issue
Block a user