kimi-code/apps/vscode/scripts/watch-extension.mjs
qer d1ca65e1de
feat(vscode): migrate extension to Node SDK (#1769)
* feat(vscode): migrate extension to Node SDK

* fix(vscode): address CI failures

* fix(vis): handle token count records

* fix(vscode): keep chat toolbar and header readable at narrow widths

* fix(vscode): map yolo to core yolo permission and honor the global yolo setting

* docs(vscode): record Node SDK migration design

* docs(vscode): split breaking changes out of the 0.6.0 changelog

* fix(vscode): keep a resumed session's thinking effort instead of reapplying the default

* fix(vscode): announce session status when a view attaches so the display matches it

* fix(vscode): align webview thinking effort handling with the TUI
2026-07-16 17:27:21 +08:00

97 lines
2.9 KiB
JavaScript

#!/usr/bin/env node
import { existsSync } from 'node:fs';
import { readdir, stat } from 'node:fs/promises';
import { extname, join, resolve } from 'node:path';
import { runLocalCli } from './local-cli.mjs';
import { extensionRoot, isMainModule } from './vsix-targets.mjs';
const sourceDirectories = [
join(extensionRoot, 'src'),
join(extensionRoot, 'shared'),
...[
'agent-core',
'kaos',
'kosong',
'migration-legacy',
'node-sdk',
'oauth',
'protocol',
'telemetry',
].map((name) => resolve(extensionRoot, `../../packages/${name}/src`)),
].filter(existsSync);
const rootConfigFiles = ['package.json', 'tsconfig.json', 'tsdown.config.ts'].map((name) =>
join(extensionRoot, name),
);
const watchedExtensions = new Set(['.cts', '.js', '.json', '.md', '.mjs', '.mts', '.ts', '.tsx']);
const pollIntervalMs = 1_500;
function buildExtension() {
runLocalCli(
'tsdown',
'tsdown',
['--config', join(extensionRoot, 'tsdown.config.ts'), '--sourcemap'],
{ cwd: extensionRoot },
);
}
async function main() {
buildExtension();
let snapshot = await sourceSnapshot();
let checking = false;
const poll = async () => {
if (checking) return;
checking = true;
try {
const nextSnapshot = await sourceSnapshot();
if (nextSnapshot === snapshot) return;
snapshot = nextSnapshot;
console.log('\nExtension source changed; rebuilding with sourcemaps...');
buildExtension();
console.log('Extension rebuild complete.');
} catch (error) {
console.error(`Extension watch check failed: ${error instanceof Error ? error.message : String(error)}`);
} finally {
checking = false;
}
};
const interval = setInterval(() => void poll(), pollIntervalMs);
const close = () => {
clearInterval(interval);
process.exit(0);
};
process.once('SIGINT', close);
process.once('SIGTERM', close);
console.log('Extension dev build complete; watching for changes.');
}
async function sourceSnapshot() {
const records = [];
for (const directory of sourceDirectories) await collectSourceRecords(directory, records);
for (const file of rootConfigFiles) await addFileRecord(file, records);
return records.sort().join('\n');
}
async function collectSourceRecords(directory, records) {
for (const entry of await readdir(directory, { withFileTypes: true })) {
const path = join(directory, entry.name);
if (entry.isDirectory()) {
await collectSourceRecords(path, records);
} else if (entry.isFile() && watchedExtensions.has(extname(entry.name))) {
await addFileRecord(path, records);
}
}
}
async function addFileRecord(path, records) {
const info = await stat(path);
records.push(`${path}:${info.size}:${info.mtimeMs}`);
}
if (isMainModule(import.meta.url)) {
main().catch((error) => {
console.error(`Extension watch failed: ${error instanceof Error ? error.message : String(error)}`);
process.exitCode = 1;
});
}