Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions .github/skills/chat-pet-sprite-creation/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,35 @@ Every frame uses the same rectangle. Never shift frame boundaries or add per-fra

Choose a meaningful static pose that communicates the state without motion. Do not assume the first animation frame is automatically the best reduced-motion fallback.

## Layered accessories

Wearable accessories use a body-owned attachment rig and one palette-independent atlas per appearance under `media/chatPet/accessories/`. Do not export copies for individual runtime states or frames. Body animation metadata owns attachment movement; an accessory atlas only contains the few canonical shapes needed when the body geometry changes.

The default atlas is `256×192`, divided into `64×64` cells. A hat whose supplied silhouette genuinely needs the full 12-logical-pixel body width may declare `atlasCellSize: 96` and use a `384×288` atlas with `96×96` cells. Do not choose the wider tier merely to add detail; both tiers still use the same whole `8×8` logical pixels.

```text
columns: upright | sleeping | impact | splat
row 0: head back layers
row 1: head front layers
row 2: right-eye front layers
```

An appearance may leave any cell transparent. For example, a plain hat leaves the eye row empty, while a combined Top Hat & Monocle appearance uses both head rows and the eye row. The airborne rig pose reuses the upright column. Add another canonical column only when an existing pose plus body-owned translation cannot preserve the intended silhouette.

Attachment tracks live in `chatPetAccessoryRig.ts`. Each track uses compressed frame spans with a canonical pose and independent head/right-eye anchors. A slot is omitted while a body-authored expression, prop, or complete silhouette replacement owns the same geometry, such as dizzy eyes, sunglasses, or the rare icon transformation. When frames inside one sheet bake different facing directions, the track marks those frames so the head accessory mirrors with the body before the whole pet's outer facing transform is applied. Update the body-owned track only when body geometry changes. Adding an ordinary accessory must not require editing tracks or renderer code.

Head-slot anchors include a one-logical-pixel wear offset so hats overlap the top of the head rather than resting on its silhouette. The love animation suppresses head accessories because its transformed head/antenna silhouette is the reaction. Treat slot visibility and fit as body-owned behavior, not per-hat exceptions.

Appearances that tuck the antennae under a larger hat opt into `coversAntennae`. The compositor uses body-owned occlusion bounds before drawing the hat front, so the behavior follows animation tracks and mirroring without painting body-colored cover pixels into each atlas.

Directional head accessories are authored for the canonical right-facing body and mirror with the complete pet canvas. A hat with directional structure should stay visually balanced over the head while expressing facing through a restrained one-logical-pixel cue in its brim, visor, lean, nose guard, or other asymmetric detail; do not shift the whole silhouette far off-center. Make asymmetric parts read correctly after mirroring. Identity-bound eye accessories may opt out of mirroring and use a direction-specific eye anchor so they remain on the same eye; the Top Hat & Monocle is the reference. Fixed-eye anchors must include the body origin shift for wide frames (`frameWidth - 96`). Review every appearance in both directions with the facing fixture.

Static reduced-motion art may represent a later frame of its animated sheet. Keep `getChatPetReducedMotionRigFrame()` aligned with the representative body frame; do not assume rig frame zero merely because the static PNG has one image frame.

Author every wearable part on the same `8×8` logical-pixel grid as the body. Brims, crowns, bands, rims, chains, highlights, and shadows must all be composed from whole aligned logical pixels; do not use diagonal polygons or source-pixel stair steps to imply curves. The small-effect exception does not apply to wearable accessories. Use the current Stable body sheets as geometry guides and validate that every alpha value is fully transparent or fully opaque. The runtime mirrors layers with the body; fixed-orientation body decorations are restored without erasing accessory pixels.

When changing the accessory source at runtime, keep the current composite visible until the replacement image loads and passes exact dimension validation. Redraw the current frame without restarting the body animation. A failed or malformed accessory source falls back to the body alone and must not repeatedly retry.

## Animation design

Animate key poses, not noise.
Expand Down Expand Up @@ -330,6 +359,19 @@ Keep the visuals silent: images, canvases, eyes, and effects use empty alt text
- [ ] User-triggered behavior has localized screen-reader output.
- [ ] Visual children are `aria-hidden`; the button owns semantics and tab order.
- [ ] `ChatPetWidget` tests cover state names, exact timings, geometry, state priority, and reduced motion.
- [ ] Every runtime state maps to the intended body-owned attachment track.
- [ ] The atlas matches its declared compact (`256×192`) or wide (`384×288`) cell tier and the documented column/row contract.
- [ ] Every accessory color/alpha block is aligned to the `8×8` logical-pixel grid.
- [ ] Atlas artwork stays within the body canvas after applying the documented pivots and anchors.
- [ ] Head accessories overlap the head by the shared wear offset and are absent during love.
- [ ] Asymmetric artwork reads correctly in both canonical and mirrored facing directions.
- [ ] Adding the accessory requires no state-specific exports or renderer changes.
- [ ] Reduced-motion sources use the rig frame represented by their static body art.
- [ ] Body-authored eye expressions and props suppress incompatible eye-slot accessories.
- [ ] Switching accessories preserves the active body frame and animation timer.
- [ ] Accessory load failure leaves the body visible and does not retry continuously.

Use the `chat/chatPetAccessoryRig/chatPetAccessoryRig/CriticalPoses` component fixture to review critical animated and reduced-motion poses, and `AllAccessoriesFacing` to compare every appearance in both directions.

Run the focused unit tests using the repository's `unit-tests` skill. At minimum, run the `ChatPetWidget` test suite.

Expand Down
2 changes: 1 addition & 1 deletion build/gulpfile.vscode.ts
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ const vscodeResourceIncludes = [
'out-build/vs/workbench/contrib/welcomeOnboarding/browser/media/*.svg',

// Chat Pet
'out-build/vs/workbench/contrib/chat/browser/widget/media/chatPet/*.{gif,png}',
'out-build/vs/workbench/contrib/chat/browser/widget/media/chatPet/**/*.{gif,png}',

// Sessions
'out-build/vs/sessions/contrib/chat/browser/media/*.svg',
Expand Down
2 changes: 1 addition & 1 deletion build/gulpfile.vscode.web.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ export const vscodeWebResourceIncludes = [
'out-build/vs/workbench/contrib/welcomeOnboarding/browser/media/*.svg',

// Chat Pet
'out-build/vs/workbench/contrib/chat/browser/widget/media/chatPet/*.{gif,png}',
'out-build/vs/workbench/contrib/chat/browser/widget/media/chatPet/**/*.{gif,png}',

// Extensions
'out-build/vs/workbench/contrib/extensions/browser/media/{theme-icon.png,language-icon.svg}',
Expand Down
2 changes: 1 addition & 1 deletion build/next/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -249,7 +249,7 @@ const commonResourcePatterns = [
// SVGs referenced from CSS (needed for transpile/dev builds where CSS is copied as-is)
'vs/workbench/browser/media/code-icon.svg',
'vs/workbench/browser/parts/editor/media/letterpress*.svg',
'vs/workbench/contrib/chat/browser/widget/media/chatPet/*.{gif,png}',
'vs/workbench/contrib/chat/browser/widget/media/chatPet/**/*.{gif,png}',
'vs/sessions/contrib/chat/browser/media/*.svg',
'vs/sessions/contrib/welcome/browser/media/themePreviews/*.svg'
];
Expand Down
20 changes: 0 additions & 20 deletions extensions/copilot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -161,7 +161,6 @@
"icon": "$(folder)",
"userDescription": "%copilot.codebase.tool.description%",
"modelDescription": "Run a natural language search for relevant code or documentation comments from the user's current workspace. Returns relevant code snippets from the user's current workspace if it is large, or the full contents of the workspace if it is small.",
"when": "config.github.copilot.chat.semanticSearchTool.mode != disabled",
"tags": [
"codesearch",
"vscode_codesearch"
Expand Down Expand Up @@ -4127,25 +4126,6 @@
"onExp"
]
},
"github.copilot.chat.semanticSearchTool.mode": {
"type": "string",
"default": "enabled",
"enum": [
"enabled",
"disabled",
"preferred"
],
"markdownEnumDescriptions": [
"%github.copilot.config.semanticSearchTool.mode.enabled%",
"%github.copilot.config.semanticSearchTool.mode.disabled%",
"%github.copilot.config.semanticSearchTool.mode.preferred%"
],
"markdownDescription": "%github.copilot.config.semanticSearchTool.mode%",
"tags": [
"experimental",
"onExp"
]
},
"github.copilot.chat.anthropic.tools.websearch.enabled": {
"type": "boolean",
"default": false,
Expand Down
4 changes: 0 additions & 4 deletions extensions/copilot/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -360,10 +360,6 @@
"github.copilot.config.gemini3GetChangedFilesTool.enabled": "Enables the Get Changed Files tool for gemini-3 models.",
"github.copilot.config.gemini3LowReasoningEffort.enabled": "Sets the reasoning effort to low for gemini-3 models.",
"github.copilot.config.gpt55ReadFileTool.enabled": "Enables the Read File tool for gpt-5.5 models.",
"github.copilot.config.semanticSearchTool.mode": "Controls how semantic search is offered to the agent in chat. Used to experiment with the impact of semantic search on agent behavior and token usage.",
"github.copilot.config.semanticSearchTool.mode.enabled": "The `semantic_search` tool and the `#codebase` chat variable are available.",
"github.copilot.config.semanticSearchTool.mode.disabled": "Removes the `semantic_search` tool from the agent and hides the `#codebase` chat variable.",
"github.copilot.config.semanticSearchTool.mode.preferred": "Same as `enabled`, plus instructions telling the agent to prefer `semantic_search` over exploratory file reads and text searches.",
"github.copilot.config.anthropic.tools.websearch.enabled": "Enable Anthropic's native web search tool for BYOK Claude models. When enabled, allows Claude to search the web for current information. \n\n**Note**: This is an experimental feature only available for BYOK Anthropic Claude models.",
"github.copilot.config.anthropic.tools.websearch.maxUses": "Maximum number of web searches allowed per request. Valid range is 1 to 20. Prevents excessive API calls within a single interaction. If Claude exceeds this limit, the response returns an error.",
"github.copilot.config.anthropic.tools.websearch.allowedDomains": "List of domains to restrict web search results to (e.g., `[\"example.com\", \"docs.example.com\"]`). Domains should not include the HTTP/HTTPS scheme. Subdomains are automatically included. Cannot be used together with `#github.copilot.chat.anthropic.tools.websearch.blockedDomains#`; configuring both will cause web search requests to fail.",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ import { AgentConversationHistory, AgentUserMessageInHistory } from './agentConv
import './allAgentPrompts';
import { AlternateGPTPrompt, DefaultReminderInstructions, DefaultToolReferencesHint, ReminderInstructionsProps, ToolReferencesHintProps } from './defaultAgentInstructions';
import { AgentPromptCustomizations, ReminderInstructionsConstructor, ToolReferencesHintConstructor } from './promptRegistry';
import { PreferSemanticSearchInstructions } from './semanticSearchInstructions';
import { SummarizedConversationHistory } from './summarizedConversationHistory';
import { DeferredToolListReminder } from './toolSearchInstructions';

Expand Down Expand Up @@ -117,18 +116,13 @@ export class AgentPrompt extends PromptElement<AgentPromptProps> {

const omitBaseAgentInstructions = this.configurationService.getConfig(ConfigKey.Advanced.OmitBaseAgentInstructions);
const hasMemoryTool = !!this.props.promptContext.tools?.availableTools?.find(tool => tool.name === ToolName.Memory);
const hasSemanticSearchTool = !!this.props.promptContext.tools?.availableTools?.find(tool => tool.name === ToolName.Codebase);
const preferSemanticSearch = hasSemanticSearchTool && this.configurationService.getExperimentBasedConfig(ConfigKey.SemanticSearchToolMode, this.experimentationService) === 'preferred';
const baseAgentInstructions = <>
<SystemMessage>
You are an expert AI programming assistant, working with a user in the VS Code editor.<br />
<CopilotIdentityRules />
<SafetyRules />
</SystemMessage>
{instructions}
{preferSemanticSearch && <SystemMessage>
<PreferSemanticSearchInstructions availableTools={this.props.promptContext.tools?.availableTools} />
</SystemMessage>}
{hasMemoryTool && <SystemMessage>
<MemoryInstructionsPrompt />
</SystemMessage>}
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -243,38 +243,6 @@ testFamilies.forEach(family => {
expect(rendered).not.toContain('repoMemory');
});

test('semantic search preference instructions render only in preferred mode', async () => {
const toolsService = accessor.get(IToolsService);
const configurationService = accessor.get(IConfigurationService);
const promptContext = {
chatVariables: new ChatVariablesCollection(),
history: [],
query: 'hello',
tools: {
availableTools: toolsService.tools,
toolInvocationToken: null as never,
toolReferences: [],
}
};
const withoutSemanticSearch = {
...promptContext,
tools: { ...promptContext.tools, availableTools: toolsService.tools.filter(t => t.name !== ToolName.Codebase) }
};
const rendersBlock = async (context: IBuildPromptContext) => (await agentPromptToString(accessor, context, undefined)).includes('semantic_search_requirements');

try {
const defaultMode = await rendersBlock(promptContext);
await configurationService.setConfig(ConfigKey.SemanticSearchToolMode, 'preferred');
expect({
defaultMode,
preferredMode: await rendersBlock(promptContext),
preferredModeWithoutTool: await rendersBlock(withoutSemanticSearch),
}).toEqual({ defaultMode: false, preferredMode: true, preferredModeWithoutTool: false });
} finally {
await configurationService.setConfig(ConfigKey.SemanticSearchToolMode, 'enabled');
}
});

test('one attachment', async () => {
await expect(await agentPromptToString(accessor, {
chatVariables: new ChatVariablesCollection([{ id: 'vscode.file', name: 'file', value: fileTsUri }]),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -326,14 +326,6 @@ export class ToolsService extends BaseToolsService {
return false;
}

// For semantic_search (codebase) tool, allow experimentally disabling it entirely.
if (
tool.name === ToolName.Codebase
&& this._configurationService.getExperimentBasedConfig(ConfigKey.SemanticSearchToolMode, this._experimentationService) === 'disabled'
) {
return false;
}

// 0. Check if the tool was disabled via the tool picker. If so, it must be disabled here
const toolPickerSelection = requestToolsByName.get(getContributedToolName(tool.name));
if (toolPickerSelection === false) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1007,8 +1007,6 @@ export namespace ConfigKey {
export const EnableGemini3LowReasoningEffort = defineSetting<boolean>('chat.gemini3LowReasoningEffort.enabled', ConfigType.ExperimentBased, false);
/** Enable read_file tool for GPT-5.5 models */
export const EnableGpt55ReadFileTool = defineSetting<boolean>('chat.gpt55ReadFileTool.enabled', ConfigType.ExperimentBased, true);
/** How the semantic_search (codebase) tool is offered to the agent: available, removed entirely, or available with instructions telling the agent to prefer it over exploratory reads and text searches. */
export const SemanticSearchToolMode = defineSetting<'enabled' | 'disabled' | 'preferred'>('chat.semanticSearchTool.mode', ConfigType.ExperimentBased, 'enabled');
export const EnableChatImageUpload = defineSetting<boolean>('chat.imageUpload.enabled', ConfigType.Simple, true);
/** Enable Anthropic web search tool for BYOK Claude models */
export const AnthropicWebSearchToolEnabled = defineSetting<boolean>('chat.anthropic.tools.websearch.enabled', ConfigType.ExperimentBased, false);
Expand Down
Loading
Loading