Skip to content
Open
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
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
---
description: Use when writing or reviewing model-facing language model tool descriptions.
applyTo: "src/vs/**/*Tool.ts,src/vs/**/*Tools.ts"
---

# Language model tool descriptions

Apply these rules only when adding or changing a model-facing tool description, such as `modelDescription`. They do not govern display names, user-facing messages, confirmation text, or routine schema property descriptions.

- Begin with a direct imperative statement of the tool's capability.
- When tool selection could be ambiguous, state the positive invocation criteria explicitly.
- Place exclusions for likely near-neighbor requests immediately after the positive criteria.
- Describe persistent, external, costly, or otherwise consequential side effects.
- State meaningful defaults, cross-field requirements, and prerequisite tool calls that are not obvious from the input schema.
- Put approval, cancellation, retry, repeat-call, and polling guidance last.
- Do not repeat the complete input schema in prose.
- Keep descriptions concise and scale their detail with the ambiguity and cost of incorrect selection.
- Preserve terminology and formatting conventions used by related tools.
- Reserve `MUST`, `ONLY`, `CRITICAL`, and direct "Do not" language for likely, consequential misuse.

When correctness depends on specific model-facing guidance, add a focused test for the required semantic clauses. Prefer checking a small set of meaningful phrases or conditions over snapshotting the entire description. Do not test routine descriptive prose.
2 changes: 2 additions & 0 deletions .github/instructions/source-code-organization.instructions.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,4 +64,6 @@ class MyComponent {
}
```

Decorated service parameters must use their canonical service interface. Do not invent local subset interfaces or `Pick<...>` aliases in production to simplify tests; keep partial stubs, adapters, and other test-only conveniences in test code.

Services are provided via `registerSingleton(IMyService, MyServiceImpl, InstantiationType.Delayed)`.
138 changes: 105 additions & 33 deletions .github/skills/agent-host-chat-contributions/SKILL.md

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions .github/skills/policy-and-managed-settings/local-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,11 @@ Choose the client setup in the GUI:
proxy mapping and enable Proxyman's platform proxy toggle (**Tools > macOS
Proxy** or **Tools > Override Windows Proxy**). VS Code clients must also add
the displayed `http.proxy` property to `settings.json`.
- **File-based settings (no proxy):** expand **Deploy as a file** under the
Managed Settings response body and run the copied per-platform command to write
the current body to `managed-settings.json` on the device. Restart the client to
load it. Use it to skip proxying or to test precedence against a server-managed
response. See [Deploying file-based settings](https://docs.github.com/en/copilot/how-tos/administer-copilot/manage-for-enterprise/manage-agents/configure-enterprise-managed-settings#deploying-file-based-settings).

Use **Clear SDK Policy Cache**, expand the macOS or Windows section, and run the
copied command when the runtime's fresh managed-settings cache prevents a network
Expand Down
72 changes: 36 additions & 36 deletions build/agent-sdk/agents/claude/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion build/agent-sdk/agents/claude/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,6 @@
"private": true,
"comment": "Pinned dependency set for the build/agent-sdk claude tarball. The package-lock.json alongside is the source of truth for transitive deps — produce.ts runs `npm ci` against this directory to get byte-deterministic output across pipeline runs.",
"dependencies": {
"@anthropic-ai/claude-agent-sdk": "0.3.220"
"@anthropic-ai/claude-agent-sdk": "0.3.239"
}
}
3 changes: 3 additions & 0 deletions build/lib/preLaunch.ts
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,9 @@ async function ensureCompiled() {
async function main() {
await ensureNodeModules();
await getElectron();
if (process.argv.includes('--only-electron')) {
return;
}
await ensureCompiled();

// Can't require this until after dependencies are installed
Expand Down
9 changes: 9 additions & 0 deletions extensions/copilot/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4024,6 +4024,15 @@
],
"description": "%github.copilot.config.gemini35FlashReducedToolUsePrompt.enabled%"
},
"github.copilot.chat.geminiFlashPromptAdditions.enabled": {
"type": "boolean",
"default": false,
"tags": [
"experimental",
"onExp"
],
"description": "%github.copilot.config.geminiFlashPromptAdditions.enabled%"
},
"github.copilot.chat.anthropic.contextEditing.mode": {
"type": "string",
"default": "off",
Expand Down
1 change: 1 addition & 0 deletions extensions/copilot/package.nls.json
Original file line number Diff line number Diff line change
Expand Up @@ -163,6 +163,7 @@
"github.copilot.config.alternateGptPrompt.enabled": "Enables an experimental alternate prompt for GPT models instead of the default prompt.",
"github.copilot.config.alternateGeminiModelFPrompt.enabled": "Enables an experimental alternate prompt for Gemini Model F instead of the default prompt.",
"github.copilot.config.gemini35FlashReducedToolUsePrompt.enabled": "Enables an experimental prompt for Gemini 3.5 Flash that instructs the model to minimize tool calls to reduce token usage.",
"github.copilot.config.geminiFlashPromptAdditions.enabled": "Enables experimental additional prompt guidance for Gemini Flash 3.6 and 3.7 models.",
"github.copilot.config.gpt5CodexAlternatePrompt": "Specifies an experimental alternate prompt to use for the GPT-5-Codex model.",
"github.copilot.command.fixTestFailure": "Fix Test Failure",
"copilot.description": "Ask or edit in context",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,25 @@ const OPEN_PULL_REQUEST_COMMAND_ID = 'github.copilot.chat.cloudSessions.openPull
const CLEAR_CACHES_COMMAND_ID = 'github.copilot.chat.cloudSessions.clearCaches';
const CREATE_PULL_REQUEST_FOR_TASK_COMMAND_ID = 'github.copilot.chat.cloudSessions.createPullRequestForTask';
const OPEN_PULL_REQUEST_FOR_TASK_COMMAND_ID = 'github.copilot.chat.cloudSessions.openPullRequestForTask';

export function parseGitHubContextUrl(value: string, kind: 'issue' | 'pullRequest'): { readonly repoId: string; readonly url: string; readonly label: string } | undefined {
const match = /^https:\/\/(?:www\.)?github\.com\/(?<owner>[^/?#]+)\/(?<repository>[^/?#]+)\/(?<resource>issues|pull)\/(?<number>[1-9]\d*)\/?(?:[?#].*)?$/i.exec(value.trim());
if (!match?.groups) {
return undefined;
}
const resource = match.groups.resource.toLowerCase();
if ((resource === 'issues') !== (kind === 'issue')) {
return undefined;
}

const repoId = `${match.groups.owner}/${match.groups.repository}`;
return {
repoId,
url: `https://github.com/${repoId}/${resource}/${match.groups.number}`,
label: `${repoId}#${match.groups.number}`,
};
}

/** Context key gating the chat-input "Create pull request" toolbar action: true while the viewed cloud task is settled and has no PR yet. */
const CAN_CREATE_PULL_REQUEST_CONTEXT_KEY = 'github.copilot.chat.cloudTaskCanCreatePullRequest';
/** Context key gating the chat-input "Open pull request" toolbar action: true once the viewed cloud task has a pull request. */
Expand Down Expand Up @@ -706,6 +725,18 @@ export class CopilotCloudSessionsProvider extends Disposable implements vscode.C
clearTimeout(searchTimeout);
}
const query = value.trim();
const pastedSelection = parseGitHubContextUrl(query, kind);
if (pastedSelection) {
searchGeneration++;
quickPick.busy = false;
quickPick.items = [{
label: pastedSelection.label,
description: pastedSelection.repoId,
alwaysShow: true,
selection: pastedSelection,
}];
return;
}
if (query.length < 2) {
if (query.length === 0) {
void search('', ++searchGeneration);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ import { mock } from '../../../../util/common/test/simpleMock';
import { ChatRequestTurn2, ChatResponseMarkdownPart, ChatResponseTurn2, ChatToolInvocationPart } from '../../../../vscodeTypes';
import { ITaskApiClient, ListTaskEventsOptions, ListTasksOptions } from '../../common/taskApiTypes';
import { ChatSessionContentBuilder, extractTaskErrorDetail, formatTaskStoppedMessage } from '../copilotCloudSessionContentBuilder';
import { formatNewSessionContextReference, getCloudSessionItemMetadata, getCloudSessionResources, normalizeInitialSessionOptions, taskStateToChatSessionStatus } from '../copilotCloudSessionsProvider';
import { formatNewSessionContextReference, getCloudSessionItemMetadata, getCloudSessionResources, normalizeInitialSessionOptions, parseGitHubContextUrl, taskStateToChatSessionStatus } from '../copilotCloudSessionsProvider';
import { TaskApiBackend, parseRepoFromTaskUrl, isCloudCodingAgentTask } from '../taskApiBackend';
import { isActiveTaskState, isFailedTaskState } from '../../vscode/copilotCodingAgentUtils';
import { NullCloudBackendInstrumentation } from '../cloudBackendTelemetry';
Expand Down Expand Up @@ -60,6 +60,28 @@ describe('copilotCloudSessionsProvider helpers', () => {
]);
});

it('parses pasted GitHub issue and pull request URLs for the matching picker', () => {
expect({
issue: parseGitHubContextUrl(' https://github.com/microsoft/vscode/ISSUES/333149#issuecomment-1 ', 'issue'),
pullRequest: parseGitHubContextUrl('https://www.github.com/microsoft/vscode/pull/333149/', 'pullRequest'),
wrongPicker: parseGitHubContextUrl('https://github.com/microsoft/vscode/pull/333149', 'issue'),
unrelated: parseGitHubContextUrl('https://example.com/microsoft/vscode/issues/333149', 'issue'),
}).toEqual({
issue: {
repoId: 'microsoft/vscode',
url: 'https://github.com/microsoft/vscode/issues/333149',
label: 'microsoft/vscode#333149',
},
pullRequest: {
repoId: 'microsoft/vscode',
url: 'https://github.com/microsoft/vscode/pull/333149',
label: 'microsoft/vscode#333149',
},
wrongPicker: undefined,
unrelated: undefined,
});
});

it('coerces object-shaped initialSessionOptions into option entries', () => {
const logService = new RecordingLogService();
const sessionResource = vscode.Uri.parse('copilot-cloud-agent:/1');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { ConfigKey, IConfigurationService } from '../../../platform/configuratio
import { IEnvService } from '../../../platform/env/common/envService';
import { IVSCodeExtensionContext } from '../../../platform/extContext/common/extensionContext';
import { InlineEditRequestLogContext } from '../../../platform/inlineEdits/common/inlineEditLogContext';
import { IInlineEditsModelService } from '../../../platform/inlineEdits/common/inlineEditsModelService';
import { ObservableGit } from '../../../platform/inlineEdits/common/observableGit';
import { NesHistoryContextProvider } from '../../../platform/inlineEdits/common/workspaceEditTracker/nesHistoryContextProvider';
import { ILogService } from '../../../platform/log/common/logService';
Expand Down Expand Up @@ -63,6 +64,9 @@ export class InlineEditProviderFeature {
private readonly _yieldToCopilot = this._configurationService.getExperimentBasedConfigObservable(ConfigKey.TeamInternal.InlineEditsYieldToCopilot, this._expService);
private readonly _excludedProviders = this._configurationService.getExperimentBasedConfigObservable(ConfigKey.TeamInternal.InlineEditsExcludedProviders, this._expService).map(v => v ? v.split(',').map(v => v.trim()).filter(v => v !== '') : []);
private readonly _copilotToken = observableFromEvent(this, this._authenticationService.onDidCopilotTokenChange, () => this._authenticationService.copilotToken);
// Read reactively: on a fetched `/models` deployment this resolves async, so a brief cold-start
// window can emit completions until `onModelListUpdated` fires and re-registers with the excludes.
private readonly _supportsUnifiedCompletions = observableFromEvent(this, this._modelService.onModelListUpdated, () => this._modelService.selectedModelConfiguration().supportsUnifiedCompletions ?? false);

public readonly inlineEditsEnabled = derived(this, (reader) => {
const copilotToken = this._copilotToken.read(reader);
Expand Down Expand Up @@ -92,6 +96,7 @@ export class InlineEditProviderFeature {
@IExperimentationService private readonly _expService: IExperimentationService,
@IEnvService private readonly _envService: IEnvService,
@IInstantiationService private readonly _instantiationService: IInstantiationService,
@IInlineEditsModelService private readonly _modelService: IInlineEditsModelService,
) {
}

Expand Down Expand Up @@ -158,8 +163,11 @@ export class InlineEditProviderFeature {
const provider = this._instantiationService.createInstance(InlineCompletionProviderImpl, model, logger, logContextRecorder, inlineEditDebugComponent, telemetrySender, expectedEditCaptureController);

const unificationStateValue = unificationState.read(reader);
// Unify when the selected model's strategy bakes in `supportsUnifiedCompletions`, or when the
// core deployment/ExP `modelUnification` toggle is set.
const modelUnification = this._supportsUnifiedCompletions.read(reader) || (unificationStateValue?.modelUnification ?? false);
let excludes = this._excludedProviders.read(reader);
if (unificationStateValue?.modelUnification) {
if (modelUnification) {
excludes = excludes.slice(0);
if (!excludes.includes('completions')) {
excludes.push('completions');
Expand Down
Loading
Loading