Skip to content

Commit 201fe5e

Browse files
authored
Merge branch 'main' into eli/copilot-ext-string
2 parents af2936a + a5c4ecf commit 201fe5e

729 files changed

Lines changed: 82680 additions & 11290 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.esbuild.ts

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const baseNodeBuildOptions = {
4545
mainFields: ["module", "main"], // needed for jsonc-parser,
4646
define: {
4747
'process.env.APPLICATIONINSIGHTS_CONFIGURATION_CONTENT': '"{}"'
48-
}
48+
},
4949
} satisfies esbuild.BuildOptions;
5050

5151
const nodeExtHostTestGlobs = [
@@ -65,7 +65,7 @@ const testBundlePlugin: esbuild.Plugin = {
6565
return { path: path.resolve(args.path) };
6666
});
6767
build.onLoad({ filter: /[\/\\]test-extension\.ts$/ }, async args => {
68-
let files = await glob(nodeExtHostTestGlobs, { cwd: REPO_ROOT, posix: true });
68+
let files = await glob(nodeExtHostTestGlobs, { cwd: REPO_ROOT, posix: true, ignore: ['src/extension/completions-core/**/*'] });
6969
files = files.map(f => path.posix.relative('src', f));
7070
if (files.length === 0) {
7171
throw new Error('No extension tests found');
@@ -95,7 +95,7 @@ const sanityTestBundlePlugin: esbuild.Plugin = {
9595
return { path: path.resolve(args.path) };
9696
});
9797
build.onLoad({ filter: /[\/\\]sanity-test-extension\.ts$/ }, async args => {
98-
let files = await glob(nodeExtHostSanityTestGlobs, { cwd: REPO_ROOT, posix: true });
98+
let files = await glob(nodeExtHostSanityTestGlobs, { cwd: REPO_ROOT, posix: true, ignore: ['src/extension/completions-core/**/*'] });
9999
files = files.map(f => path.posix.relative('src', f));
100100
if (files.length === 0) {
101101
throw new Error('No extension tests found');
@@ -111,6 +111,23 @@ const sanityTestBundlePlugin: esbuild.Plugin = {
111111
}
112112
};
113113

114+
const importMetaPlugin: esbuild.Plugin = {
115+
name: 'claudeCodeImportMetaPlugin',
116+
setup(build) {
117+
// Handle import.meta.url in @anthropic-ai/claude-code package
118+
build.onLoad({ filter: /node_modules[\/\\]@anthropic-ai[\/\\]claude-code[\/\\].*\.mjs$/ }, async (args) => {
119+
const contents = await fs.promises.readFile(args.path, 'utf8');
120+
return {
121+
contents: contents.replace(
122+
/import\.meta\.url/g,
123+
'require("url").pathToFileURL(__filename).href'
124+
),
125+
loader: 'js'
126+
};
127+
});
128+
}
129+
};
130+
114131
const shimVsCodeTypesPlugin: esbuild.Plugin = {
115132
name: 'shimVsCodeTypesPlugin',
116133
setup(build) {
@@ -157,7 +174,7 @@ const nodeExtHostBuildOptions = {
157174
{ in: './src/sanity-test-extension.ts', out: 'sanity-test-extension' },
158175
],
159176
loader: { '.ps1': 'text' },
160-
plugins: [testBundlePlugin, sanityTestBundlePlugin],
177+
plugins: [testBundlePlugin, sanityTestBundlePlugin, importMetaPlugin],
161178
external: [
162179
...baseNodeBuildOptions.external,
163180
'vscode'
@@ -218,7 +235,7 @@ const nodeSimulationWorkbenchUIBuildOptions = {
218235
'child_process',
219236
'http',
220237
'assert',
221-
]
238+
],
222239
} satisfies esbuild.BuildOptions;
223240

224241
async function typeScriptServerPluginPackageJsonInstall(): Promise<void> {
@@ -323,6 +340,7 @@ async function main() {
323340
`**/*.w.json`,
324341
'**/*.sqlite',
325342
'**/*.sqlite-journal',
343+
'test/aml/out/**'
326344
]
327345
});
328346
rebuild();

.eslint-ignore

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ test/simulation/fixtures/**
1010
test/scenarios/**
1111
.simulation/**
1212
.eslintplugin/**
13+
chat-lib/**
14+
test/aml/out/**
1315

1416
# ignore vs
1517
src/util/vs/**
@@ -26,3 +28,6 @@ src/extension/typescriptContext/serverPlugin/dist/**
2628

2729
# Ignore Built test-extension
2830
.vscode/extensions/test-extension/dist/**
31+
32+
# Ignore completions-core
33+
src/extension/completions-core/**

.github/copilot-instructions.md

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,19 @@ This is the **GitHub Copilot Chat** extension for Visual Studio Code - a VS Code
2323
- **Vitest**: Unit testing framework
2424
- **Python**: For notebooks integration and ML evaluation scripts
2525

26+
## Validating changes
27+
28+
You MUST check compilation output before running ANY script or declaring work complete!
29+
30+
1. **ALWAYS** check the `start-watch-tasks` watch task output for compilation errors
31+
2. **NEVER** use the `compile` task as a way to check if everything is working properly
32+
3. **FIX** all compilation errors before moving forward
33+
34+
### TypeScript compilation steps
35+
- Monitor the `start-watch-tasks` task outputs for real-time compilation errors as you make changes
36+
- This task runs `npm: watch:tsc-extension`,`npm: watch:tsc-extension-web`, `npm: watch:tsc-simulation-workbench`, and `npm: watch:esbuild` to incrementally compile the project
37+
- Start the task if it's not already running in the background
38+
2639
## Project Architecture
2740

2841
### Top-Level Directory Structure
@@ -225,6 +238,7 @@ x => x + x // ✓ Correct
225238
### Code Structure
226239
- Always surround loop and conditional bodies with curly braces
227240
- Open curly braces always go on the same line as whatever necessitates them
241+
- An open curly brace MUST be followed by a newline, with the body indented on the next line
228242
- Parenthesized constructs should have no surrounding whitespace
229243
- Single space follows commas, colons, and semicolons
230244

@@ -241,6 +255,8 @@ function f(x: number, y: string): void { }
241255
### Type Management
242256
- Do not export `types` or `functions` unless you need to share it across multiple components
243257
- Do not introduce new `types` or `values` to the global namespace
258+
- Use proper types. Do not use `any` unless absolutely necessary.
259+
- Use `readonly` whenever possible.
244260

245261
## Key APIs and Integrations
246262

@@ -319,3 +335,7 @@ The extension uses numerous proposed VS Code APIs for advanced functionality:
319335
- **Configuration**: Modify `package.json` contributions for VS Code integration
320336

321337
This extension is a complex, multi-layered system that provides comprehensive AI assistance within VS Code. Understanding the service architecture, contribution system, and separation between platform and extension layers is crucial for making effective changes.
338+
339+
## Best Practices
340+
- Use services and dependency injection whenever possible instead of using node or vscode APIs directly. For example, use `IFileService` instead of node's `fs`.
341+
- Always use the URI type instead of using string file paths. There are many helpers available for working with URIs.
Lines changed: 167 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,167 @@
1+
---
2+
applyTo: '**/*.tsx'
3+
description: Prompt-TSX coding guidelines
4+
---
5+
6+
Guidelines for TSX files using [prompt-tsx](https://github.com/microsoft/vscode-prompt-tsx) focusing on specific patterns and token budget management for AI prompt engineering.
7+
8+
## Component Structure
9+
10+
### Base Pattern
11+
- Extend `PromptElement<Props>` or `PromptElement<Props, State>` for all prompt components
12+
- Props interfaces must extend `BasePromptElementProps`
13+
14+
```tsx
15+
interface MyPromptProps extends BasePromptElementProps {
16+
readonly userQuery: string;
17+
}
18+
19+
class MyPrompt extends PromptElement<MyPromptProps> {
20+
render() {
21+
return (
22+
<>
23+
<SystemMessage priority={1000}>...</SystemMessage>
24+
<UserMessage priority={900}>{this.props.userQuery}</UserMessage>
25+
</>
26+
);
27+
}
28+
}
29+
```
30+
31+
### Async Components
32+
- The `render` method can be async for components that need to perform async operations
33+
- All async work should be done directly in the `render` method
34+
35+
```tsx
36+
class FileContextPrompt extends PromptElement<FileContextProps> {
37+
async render() {
38+
const fileContent = await readFileAsync(this.props.filePath);
39+
return (
40+
<>
41+
<SystemMessage priority={1000}>File content:</SystemMessage>
42+
<UserMessage priority={900}>{fileContent}</UserMessage>
43+
</>
44+
);
45+
}
46+
}
47+
```
48+
49+
## Prompt-Specific JSX
50+
51+
### Line Breaks
52+
- **CRITICAL**: Use `<br />` for line breaks - newlines are NOT preserved in JSX
53+
- Never rely on whitespace or string literal newlines
54+
55+
```tsx
56+
// ✅ Correct
57+
<SystemMessage>
58+
You are an AI assistant.<br />
59+
Follow these guidelines.<br />
60+
</SystemMessage>
61+
62+
// ❌ Wrong - newlines will be collapsed
63+
<SystemMessage>
64+
You are an AI assistant.
65+
Follow these guidelines.
66+
</SystemMessage>
67+
```
68+
69+
## Priority System
70+
71+
### Priority Values
72+
- Higher numbers = higher priority (like z-index)
73+
- Use consistent ranges:
74+
- System messages: 1000
75+
- User queries: 900
76+
- Recent history: 700-800
77+
- Context/attachments: 600-700
78+
- Background info: 0-500
79+
80+
```tsx
81+
<SystemMessage priority={1000}>...</SystemMessage>
82+
<UserMessage priority={900}>{query}</UserMessage>
83+
<HistoryMessages priority={700} />
84+
<ContextualData priority={500} />
85+
```
86+
87+
### Flex Properties for Token Budget
88+
- `flexGrow={1}` - expand to fill remaining token space
89+
- `flexReserve` - reserve tokens before rendering
90+
- `passPriority` - pass-through containers that don't affect child priorities
91+
92+
```tsx
93+
<FileContext priority={70} flexGrow={1} files={this.props.files} />
94+
<History passPriority older={0} newer={80} flexGrow={2} flexReserve="/5" />
95+
```
96+
97+
## Content Handling
98+
99+
### TextChunk for Truncation
100+
- Use `TextChunk` for content that may exceed token budget
101+
- Set `breakOn` patterns for intelligent truncation
102+
103+
```tsx
104+
<TextChunk breakOnWhitespace priority={100}>
105+
{longUserQuery}
106+
</TextChunk>
107+
108+
<TextChunk breakOn=" " priority={80}>
109+
{documentContent}
110+
</TextChunk>
111+
```
112+
113+
### Tag Component for Structured Content
114+
- Use `Tag` for XML-like structured content with attributes
115+
- Validates tag names and properly formats attributes
116+
117+
```tsx
118+
<Tag name="attachments" attrs={{ id: variableName, type: "file" }}>
119+
{content}
120+
</Tag>
121+
```
122+
123+
## References and Metadata
124+
125+
### Prompt References
126+
- Use `<references>` for tracking variable usage
127+
- Use `<meta>` for metadata that survives pruning
128+
129+
```tsx
130+
<references value={[new PromptReference({ variableName })]} />
131+
<meta value={new ToolResultMetadata(id, result)} />
132+
```
133+
134+
### Keep-With Pattern
135+
- Use `useKeepWith()` for content that should be pruned together
136+
137+
```tsx
138+
const KeepWith = useKeepWith();
139+
return (
140+
<>
141+
<KeepWith priority={2}>
142+
<ToolCallRequest>...</ToolCallRequest>
143+
</KeepWith>
144+
<KeepWith priority={1}>
145+
<ToolCallResponse>...</ToolCallResponse>
146+
</KeepWith>
147+
</>
148+
);
149+
```
150+
151+
## Token Budget Management
152+
153+
### Sizing-Aware Rendering
154+
- Use `PromptSizing` parameter for budget-aware content generation
155+
- Implement cooperative token usage
156+
157+
```tsx
158+
async render(sizing: PromptSizing): Promise<PromptPiece> {
159+
const content = await this.generateContent(sizing.tokenBudget);
160+
return <>{content}</>;
161+
}
162+
```
163+
164+
### Performance
165+
- Avoid expensive work in `render` methods when possible
166+
- Cache computations when appropriate
167+
- Use async `render` for all async operations
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
---
2+
applyTo: '**/*.spec.ts'
3+
description: Vitest unit testing guidelines
4+
---
5+
6+
Please follow these guidelines when writing unit tests using Vitest. These tests are `*.spec.ts`
7+
8+
## Best Practices
9+
10+
- Prefer explicit Test/Mock classes over mutating real instances or creating adhoc one-off mocks.
11+
- Never use `as any` to override private methods or assign properties on real objects.
12+
- Mock versions of services are typically named `Mock*` or `Test*`, you can search to find whether one already exists.
13+
- Some examples: `MockFileSystemService`, `MockChatResponseStream`, `TestTasksService`.
14+
15+
- If there is no preexisting implementation of a service that is appropriate to reuse in the test, then you can create a simple mock or stub implementation in a file under a `test/` folder near the interface definition.
16+
- A mock class should be configurable so that it can be shared and set up for different test scenarios.
17+
18+
- The helper `createExtensionUnitTestingServices` returns a `TestingServiceCollection` preconfigured with some common mock services, use `IInstantiationService` to create instances with those mocks. Here's an example of using it properly
19+
20+
```ts
21+
const serviceCollection = store.add(createExtensionUnitTestingServices());
22+
instantiationService = serviceCollection.createTestingAccessor().get(IInstantiationService);
23+
const mockFs = accessor.get(IFileSystemService) as MockFileSystemService;
24+
const testService = instantiationService.createInstance(SomeServiceToTest);
25+
```
26+
27+
- When asked to write new tests, add tests to cover the behavior of the code under test, especially things that are interesting, unexpected, or edge cases.
28+
- Avoid adding tests that simply repeat existing tests or cover trivial code paths.
29+
30+
- If available, prefer the runTests tool to run tests over a terminal command.
31+
32+
- Keep tests deterministic and fast.
33+
- Avoid starting real servers or performing network I/O.
34+
35+
- Avoid excessive repetition in tests, use `beforeEach` to set up common state.
36+
- Use helper functions to encapsulate common test logic.

0 commit comments

Comments
 (0)