bundle cli in vscode

This commit is contained in:
tanzhenxin
2025-12-13 20:56:18 +08:00
parent 65796e2799
commit 8e29cc88f9
16 changed files with 369 additions and 1143 deletions

View File

@@ -0,0 +1,67 @@
/**
* @license
* Copyright 2025 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*/
/**
* Copy the already-built root dist/ folder into the extension dist/qwen-cli/.
*
* Assumes repoRoot/dist already exists (e.g. produced by `npm run bundle` and
* optionally `npm run prepare:package`).
*/
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import fs from 'node:fs/promises';
import { existsSync } from 'node:fs';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const extensionRoot = path.resolve(__dirname, '..');
const repoRoot = path.resolve(extensionRoot, '..', '..');
const rootDistDir = path.join(repoRoot, 'dist');
const extensionDistDir = path.join(extensionRoot, 'dist');
const bundledCliDir = path.join(extensionDistDir, 'qwen-cli');
async function main() {
const cliJs = path.join(rootDistDir, 'cli.js');
const vendorDir = path.join(rootDistDir, 'vendor');
if (!existsSync(cliJs) || !existsSync(vendorDir)) {
throw new Error(
`[copy-bundled-cli] Missing root dist artifacts. Expected:\n- ${cliJs}\n- ${vendorDir}\n\nRun root "npm run bundle" first.`,
);
}
await fs.mkdir(extensionDistDir, { recursive: true });
const existingNodeModules = path.join(bundledCliDir, 'node_modules');
const tmpNodeModules = path.join(
extensionDistDir,
'qwen-cli.node_modules.tmp',
);
const keepNodeModules = existsSync(existingNodeModules);
// Preserve destination node_modules if it exists (e.g. after packaging install).
if (keepNodeModules) {
await fs.rm(tmpNodeModules, { recursive: true, force: true });
await fs.rename(existingNodeModules, tmpNodeModules);
}
await fs.rm(bundledCliDir, { recursive: true, force: true });
await fs.mkdir(bundledCliDir, { recursive: true });
await fs.cp(rootDistDir, bundledCliDir, { recursive: true });
if (keepNodeModules) {
await fs.rename(tmpNodeModules, existingNodeModules);
}
console.log(`[copy-bundled-cli] Copied ${rootDistDir} -> ${bundledCliDir}`);
}
main().catch((err) => {
console.error(err);
process.exit(1);
});

View File

@@ -0,0 +1,98 @@
/**
* @license
* Copyright 2025 Qwen Team
* SPDX-License-Identifier: Apache-2.0
*/
/**
* VS Code extension packaging orchestration.
*
* We bundle the CLI into the extension so users don't need a global install.
* To match the published CLI layout, we need to:
* - build root bundle (dist/cli.js + vendor/ + sandbox profiles)
* - run root prepare:package (dist/package.json + locales + README/LICENSE)
* - install production deps into root dist/ (dist/node_modules) so runtime deps
* like optional node-pty are present inside the VSIX payload.
*
* Then we generate notices and build the extension.
*/
import path from 'node:path';
import { fileURLToPath } from 'node:url';
import { spawnSync } from 'node:child_process';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const extensionRoot = path.resolve(__dirname, '..');
const repoRoot = path.resolve(extensionRoot, '..', '..');
const bundledCliDir = path.join(extensionRoot, 'dist', 'qwen-cli');
function npmBin() {
return process.platform === 'win32' ? 'npm.cmd' : 'npm';
}
function run(cmd, args, opts = {}) {
const res = spawnSync(cmd, args, {
stdio: 'inherit',
shell: false,
...opts,
});
if (res.error) {
throw res.error;
}
if (typeof res.status === 'number' && res.status !== 0) {
throw new Error(
`Command failed (${res.status}): ${cmd} ${args.map((a) => JSON.stringify(a)).join(' ')}`,
);
}
}
function main() {
const npm = npmBin();
console.log('[prepackage] Bundling root CLI...');
run(npm, ['--prefix', repoRoot, 'run', 'bundle'], { cwd: repoRoot });
console.log('[prepackage] Preparing root dist/ package metadata...');
run(npm, ['--prefix', repoRoot, 'run', 'prepare:package'], { cwd: repoRoot });
console.log('[prepackage] Generating notices...');
run(npm, ['run', 'generate:notices'], { cwd: extensionRoot });
console.log('[prepackage] Typechecking...');
run(npm, ['run', 'check-types'], { cwd: extensionRoot });
console.log('[prepackage] Linting...');
run(npm, ['run', 'lint'], { cwd: extensionRoot });
console.log('[prepackage] Building extension (production)...');
run(npm, ['run', 'build:prod'], { cwd: extensionRoot });
console.log('[prepackage] Copying bundled CLI dist/ into extension...');
run(
process.execPath,
[path.join(extensionRoot, 'scripts', 'copy-bundled-cli.js')],
{
cwd: extensionRoot,
},
);
console.log(
'[prepackage] Installing production deps into extension dist/qwen-cli...',
);
run(
npm,
[
'--prefix',
bundledCliDir,
'install',
'--omit=dev',
'--no-audit',
'--no-fund',
],
{ cwd: bundledCliDir },
);
}
main();