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
Expand Up @@ -10,3 +10,9 @@ AHP clients communicate with any conforming Agent Host, not only the local VS Co
Use standard AHP fields and negotiated capabilities for shared behavior. If VS Code needs an optional extension, use a namespaced `_meta` value with a typed reader that validates its shape before use. Do not make the extension a requirement for other hosts, and do not use `_meta` to replace a standard protocol field or to justify assuming a particular host implementation.

When changing an AHP client, cover a conforming host that advertises valid but different URIs and identifiers, as well as absent optional extensions. Test the behavior at the client boundary, not only against the local VS Code host.

## Native session identity

Follow the [Agent Host session identity contract](../../src/vs/sessions/contrib/providers/agentHost/AGENT_HOST_SESSIONS_PROVIDER.md#identity). Backend identities are mixed and immutable: negotiate addressing only for new allocations, never rewrite restored, discovered, adopted, or continued conversations. Keep frontend resources, session IDs, and chat fragments stable; carry the advertised provider and exact backend resource through caches and owning-connection resolution. `ahp-session` carries no provider identity and must never imply Copilot.

Back changes with boundary tests for both version-skew directions, mixed legacy/standard resources, reconnects, opaque advertised chats, and cache reloads. Restart tests must use fresh provider instances, and discovery/deletion tests must preserve provider/backing identity rather than equating raw IDs across providers. Scope legacy visibility to positively identified legacy VS Code connections; unmarked conforming peers must not be classified as legacy.
2 changes: 2 additions & 0 deletions .github/skills/component-fixtures/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,8 @@ The render promise must resolve only when the fixture represents its named state
- Supply deterministic display data through existing services/options, such as a single custom thinking phrase. A seeded random generator alone does not make labels independent of render order or async callback order.
- Use bounded, condition-based waits that throw on failure, not fixed sleeps or extra frames that silently accept an incomplete state.

Design fixtures as **state + local inputs + an explicit readiness condition**. Supply local account icons instead of letting a mock fall back to a live avatar URL, and await decoding; `waitForFixtureCondition` polls native browser frames while preserving the virtual clock. Prefer shared DOM spinners over animated SVG backgrounds: ancestor CSS cannot stop animations inside an image. Wait for auto-hiding scrollbars to reach their intended idle state, not merely for content height to stabilize.

Fixtures that depend on native browser image decoding or resize/scroll callbacks can use `virtualTime: { enabled: false }` and explicitly await those operations. Virtual JavaScript time does not advance the browser's image decoder or layout pipeline.

For async fixtures with paint-order-sensitive edges, `deferPaint: true` keeps the headless fixture transparent until rendering has finished, without changing its layout or interactive preview. It prevents intermediate paints from affecting the final rasterization; it does **not** replace awaiting readiness.
Expand Down
4 changes: 4 additions & 0 deletions build/lib/stylelint/vscode-known-variables.json
Original file line number Diff line number Diff line change
Expand Up @@ -1261,6 +1261,10 @@
"--monaco-editor-warning-decoration",
"--animation-angle",
"--animation-opacity",
"--chat-generated-image-max-height",
"--chat-image-reveal-frame",
"--chat-image-reveal-frame-width",
"--chat-image-reveal-image",
"--chat-input-anim-angle",
"--chat-input-anim-duration",
"--chat-input-control-height",
Expand Down
35 changes: 35 additions & 0 deletions eslint.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,40 @@ export default defineConfig(
]
}
},
{
files: [
'src/vs/platform/agentHost/test/**/missionControl*.test.ts',
'src/vs/platform/agentHost/test/**/protocolServerHandler.test.ts',
'src/vs/platform/agentHost/test/**/agentHostProtocolClient.test.ts',
'src/vs/platform/agentHost/test/**/webPubSubRelayTransport.test.ts',
'src/vs/platform/agentHost/test/common/webPubSub/*.test.ts',
'src/vs/workbench/contrib/chat/test/browser/remoteAgentHost/cloudSandbox*.test.ts',
'src/vs/sessions/contrib/providers/remoteAgentHost/test/browser/remoteAgentHost.contribution.test.ts',
],
plugins: {
'agent-host-test': {
rules: {
'no-nested-tests': {
meta: {
type: 'problem',
schema: [],
messages: { nested: 'Declare tests in the suite, not inside another test; Mocha does not execute nested declarations.' },
},
create(context) {
return {
'CallExpression[callee.name="test"] CallExpression[callee.name="test"]'(node) {
context.report({ node, messageId: 'nested' });
},
};
},
},
},
},
},
rules: {
'agent-host-test/no-nested-tests': 'error',
},
},
// Disallow common telemetry properties in event data
{
files: [
Expand Down Expand Up @@ -1716,6 +1750,7 @@ export default defineConfig(
'@modelcontextprotocol/sdk/**/*', // used by agentHost for Claude client-tool MCP result types (Phase 10)
'@github/copilot-sdk',
'zod', // used by agentHost for Claude client-tool MCP input schemas
{ 'when': 'hasNode', 'pattern': 'libsodium-wrappers' },
{
'when': 'test',
'pattern': 'events'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,41 @@ describe('CopilotAssignmentsFilterProvider', () => {
]);
});

it('preserves VS Code team targeting and internal organization precedence across token changes', () => {
const { tokenStore, provider } = createProvider();
const organizations = [
['a5db0bcaae94032fe715fb34a5e4bce2'],
['4535c7beffc844b46bb1ed4aa04d759a'],
['551cca60ce19654d894e786220822482'],
['a5db0bcaae94032fe715fb34a5e4bce2', '4535c7beffc844b46bb1ed4aa04d759a', '551cca60ce19654d894e786220822482'],
['unrecognized-org'],
[],
];
const tokens = [
...organizations.map(organization_list => new CopilotToken(createTestExtendedTokenInfo({ organization_list }))),
new CopilotToken(createTestExtendedTokenInfo({ isVscodeTeamMember: true })),
undefined,
];

expect(tokens.map(token => {
tokenStore.copilotToken = token;
const filters = provider.getFilters();
return [
filters.get('github_core_ghmsftorexternal'),
filters.get('github_core_isghormsftstaff'),
];
})).toEqual([
['microsoft', '1'],
['github', '1'],
['vscode', '1'],
['vscode', '1'],
['external', '0'],
['external', '0'],
['vscode', '1'],
['external', '0'],
]);
});

it('preserves legacy CLS user-kind values and precedence', () => {
const { tokenStore, provider } = createProvider();
const knownOrganizations = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ export class CopilotAssignmentsFilterProvider implements IExperimentationFilterP
filters.set('github_core_organizationid', token?.organizationList.join(','));
filters.set('github_core_businessid', token?.enterpriseList.join(','));
filters.set('github_core_isghormsftstaff', internalOrg ? '1' : '0');
filters.set('github_core_ghmsftorexternal', internalOrg === 'github' ? 'github' : (internalOrg === 'microsoft' || internalOrg === 'vscode') ? 'microsoft' : 'external');
filters.set('github_core_ghmsftorexternal', internalOrg ?? 'external');
filters.set('github_core_userkind', token?.userKind || undefined);
filters.set('github_core_copilotsku', token?.sku);
filters.set('github_core_issn', token?.isSn() ? '1' : '0');
Expand Down
88 changes: 52 additions & 36 deletions package-lock.json

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

5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@
"dependencies": {
"@anthropic-ai/sdk": "^0.82.0",
"@devcontainers/cli": "0.88.0",
"@github/copilot-sdk": "1.0.17-preview.4",
"@github/copilot-sdk": "1.0.17-preview.5",
"@microsoft/1ds-core-js": "^3.2.13",
"@microsoft/1ds-post-js": "^3.2.13",
"@microsoft/dev-tunnels-connections": "^1.3.41",
Expand Down Expand Up @@ -151,6 +151,7 @@
"jschardet": "3.1.4",
"katex": "^0.16.22",
"kerberos": "2.1.1",
"libsodium-wrappers": "^0.8.4",
"minimist": "^1.2.8",
"native-is-elevated": "0.9.0",
"native-keymap": "^3.3.5",
Expand Down Expand Up @@ -325,5 +326,5 @@
"@vscode/windows-ca-certs@0.3.4": true,
"@vscode/windows-process-tree@0.8.0": true
},
"copilotRuntimeVersion": "1.0.92-4"
"copilotRuntimeVersion": "1.0.92-5"
}
Loading