Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/extensions/copilot/script/postinstall.ts
13383 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
import * as fs from 'fs';
7
import * as path from 'path';
8
import { compressTikToken } from './build/compressTikToken';
9
import { copyStaticAssets } from './build/copyStaticAssets';
10
11
export interface ITreeSitterGrammar {
12
name: string;
13
/**
14
* A custom .wasm filename if the grammar node module doesn't follow the standard naming convention
15
*/
16
filename?: string;
17
/**
18
* The path where we should spawn `tree-sitter build-wasm`
19
*/
20
projectPath?: string;
21
}
22
23
const treeSitterGrammars: ITreeSitterGrammar[] = [
24
{
25
name: 'tree-sitter-c-sharp',
26
filename: 'tree-sitter-c_sharp.wasm' // non-standard filename
27
},
28
{
29
name: 'tree-sitter-cpp',
30
},
31
{
32
name: 'tree-sitter-go',
33
},
34
{
35
name: 'tree-sitter-javascript', // Also includes jsx support
36
},
37
{
38
name: 'tree-sitter-python',
39
},
40
{
41
name: 'tree-sitter-ruby',
42
},
43
{
44
name: 'tree-sitter-typescript',
45
projectPath: 'tree-sitter-typescript/typescript', // non-standard path
46
},
47
{
48
name: 'tree-sitter-tsx',
49
projectPath: 'tree-sitter-typescript/tsx', // non-standard path
50
},
51
{
52
name: 'tree-sitter-java',
53
},
54
{
55
name: 'tree-sitter-rust',
56
},
57
{
58
name: 'tree-sitter-php'
59
}
60
];
61
62
const REPO_ROOT = path.join(__dirname, '..');
63
64
async function removeCopilotCLIShim() {
65
const shimsPath = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'shims.txt');
66
await fs.promises.rm(shimsPath, { force: true }).catch(() => { /* ignore */ });
67
}
68
69
/**
70
* @github/copilot/sdk/index.js depends on @github/copilot/worker/*.js files.
71
* We need to copy these files into the sdk directory to ensure they are available at runtime.
72
*/
73
async function copyCopilotCliWorkerFiles() {
74
const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'worker');
75
const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'worker');
76
77
await copyCopilotCLIFolders(sourceDir, targetDir);
78
}
79
80
async function copyCopilotCliSharpFiles() {
81
const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sharp');
82
const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'sharp');
83
84
await copyCopilotCLIFolders(sourceDir, targetDir);
85
}
86
87
async function copyCopilotCliDefinitionFiles() {
88
const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'definitions');
89
const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'definitions');
90
91
await copyCopilotCLIFolders(sourceDir, targetDir);
92
}
93
94
async function copyCopilotCliSkillsFiles() {
95
const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'builtin-skills');
96
const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'builtin-skills');
97
98
await copyCopilotCLIFolders(sourceDir, targetDir);
99
}
100
101
async function copyCopilotCliQueryFiles() {
102
const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'queries');
103
const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'queries');
104
105
await copyCopilotCLIFolders(sourceDir, targetDir);
106
}
107
108
async function copyCopilotCliPrebuildFiles() {
109
const sourceDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'prebuilds');
110
const targetDir = path.join(REPO_ROOT, 'node_modules', '@github', 'copilot', 'sdk', 'prebuilds');
111
112
await fs.promises.rm(targetDir, { recursive: true, force: true });
113
await fs.promises.mkdir(targetDir, { recursive: true });
114
await fs.promises.cp(sourceDir, targetDir, {
115
recursive: true, force: true, filter: (src) => {
116
try {
117
// Only copy computer.node and win32.node files
118
if (fs.statSync(src).isFile()) {
119
return src.endsWith('computer.node') || src.endsWith('win32.node');
120
}
121
return true;
122
} catch {
123
return true;
124
}
125
}
126
});
127
}
128
129
async function copyCopilotCLIFolders(sourceDir: string, targetDir: string) {
130
await fs.promises.rm(targetDir, { recursive: true, force: true });
131
await fs.promises.mkdir(targetDir, { recursive: true });
132
await fs.promises.cp(sourceDir, targetDir, { recursive: true, force: true });
133
}
134
135
/**
136
* Creates symlinks so that `.claude/` mirrors canonical locations (for testing Claude Agent harness):
137
* .claude/CLAUDE.md → .github/copilot-instructions.md
138
* .claude/skills → .agents/skills
139
*/
140
async function createClaudeSymlinks() {
141
if (process.platform === 'win32') {
142
// Creating symlinks on Windows may fail without Developer Mode or admin privileges.
143
// Skip this step to avoid postinstall failures on environments where symlinks are not available.
144
return;
145
}
146
147
console.log('Creating symlinks for Claude session storage and instructions...');
148
const claudeDir = path.join(REPO_ROOT, '.claude');
149
await fs.promises.mkdir(claudeDir, { recursive: true });
150
151
const symlinks: { link: string; target: string }[] = [
152
{ link: path.join(claudeDir, 'CLAUDE.md'), target: path.join('..', '.github', 'copilot-instructions.md') },
153
{ link: path.join(claudeDir, 'skills'), target: path.join('..', '.agents', 'skills') },
154
];
155
156
for (const { link, target } of symlinks) {
157
if (!fs.existsSync(link)) {
158
await fs.promises.symlink(target, link);
159
}
160
}
161
}
162
163
async function main() {
164
await fs.promises.mkdir(path.join(REPO_ROOT, '.build'), { recursive: true });
165
166
await createClaudeSymlinks();
167
168
const vendoredTiktokenFiles = ['src/platform/tokenizer/node/cl100k_base.tiktoken', 'src/platform/tokenizer/node/o200k_base.tiktoken'];
169
170
for (const tokens of vendoredTiktokenFiles) {
171
await compressTikToken(tokens, `dist/${path.basename(tokens)}`);
172
}
173
174
// copy static assets to dist
175
await copyStaticAssets([
176
...treeSitterGrammars.map(grammar => `node_modules/@vscode/tree-sitter-wasm/wasm/${grammar.name}.wasm`),
177
'node_modules/@vscode/tree-sitter-wasm/wasm/tree-sitter.wasm',
178
'node_modules/@github/blackbird-external-ingest-utils/pkg/nodejs/external_ingest_utils_bg.wasm',
179
], 'dist');
180
181
await removeCopilotCLIShim();
182
await copyCopilotCliWorkerFiles();
183
await copyCopilotCliSharpFiles();
184
await copyCopilotCliDefinitionFiles();
185
await copyCopilotCliSkillsFiles();
186
await copyCopilotCliQueryFiles();
187
await copyCopilotCliPrebuildFiles();
188
189
// Check if the base cache file exists (dev-only sanity check, non-fatal in CI)
190
const baseCachePath = path.join('test', 'simulation', 'cache', 'base.sqlite');
191
if (!fs.existsSync(baseCachePath)) {
192
console.warn(`Warning: Base cache file does not exist at ${baseCachePath}. Please ensure that you have git lfs installed and initialized before the repository is cloned.`);
193
}
194
195
await copyStaticAssets([
196
`node_modules/@anthropic-ai/claude-agent-sdk/cli.js`,
197
], 'dist');
198
}
199
200
main();
201
202