kimi-code/apps/kimi-code/scripts/dev.mjs
liruifengv 8d58d6ad4c
chore(dev): open monorepo root when running make dev (#1458)
* chore(dev): open monorepo root when running make dev

The dev runner spawned the tsx child process with cwd pinned to
apps/kimi-code, so the TUI always opened apps/kimi-code as its working
directory. Switch the child cwd to the monorepo root and pass the
tsconfig, raw-text loader, and entry point as absolute paths so their
resolution does not depend on cwd.

This only affects the local dev runner; the published CLI is unchanged.

* fix(dev): pass --import preload as a file URL

Node resolves `--import` preloads as ESM specifiers. On Windows, the
absolute path produced by path.resolve() looks like a `c:` URL scheme
and crashes the dev CLI with ERR_UNSUPPORTED_ESM_URL_SCHEME before
src/main.ts loads. Convert the preload to a file:// URL via
pathToFileURL so it resolves on every platform.

Addresses codex review on PR #1458.
2026-07-07 13:37:40 +08:00

79 lines
3 KiB
JavaScript

#!/usr/bin/env node
import { spawn } from 'node:child_process';
import { createRequire } from 'node:module';
import { dirname, resolve } from 'node:path';
import { fileURLToPath, pathToFileURL } from 'node:url';
import { startPluginMarketplaceServer } from './dev-plugin-marketplace-server.mjs';
const require = createRequire(import.meta.url);
const SCRIPT_DIR = dirname(fileURLToPath(import.meta.url));
const APP_ROOT = resolve(SCRIPT_DIR, '..');
// Monorepo root. Used as the dev CLI's working directory so `make dev` opens
// the whole repo instead of just apps/kimi-code.
const REPO_ROOT = resolve(APP_ROOT, '../..');
// Runtime variable the CLI reads to locate the marketplace JSON.
const MARKETPLACE_ENV = 'KIMI_CODE_PLUGIN_MARKETPLACE_URL';
// Opt-in for dev: point this run at an external marketplace instead of a local one.
const EXTERNAL_MARKETPLACE_ENV = 'KIMI_CODE_DEV_MARKETPLACE_URL';
let marketplaceServer;
const env = { ...process.env };
const externalUrl = process.env[EXTERNAL_MARKETPLACE_ENV]?.trim();
if (externalUrl !== undefined && externalUrl.length > 0) {
// Explicitly asked to use an external marketplace; don't start a local server.
env[MARKETPLACE_ENV] = externalUrl;
console.error(`Using external plugin marketplace: ${externalUrl}`);
} else {
// Default: every `pnpm run dev:cli` runs its own isolated marketplace server on a
// random port, so multiple concurrent dev instances never collide. Overwrite any
// inherited MARKETPLACE_ENV so a stale URL from a dead instance can't break this run.
const inherited = process.env[MARKETPLACE_ENV]?.trim();
marketplaceServer = await startPluginMarketplaceServer();
env[MARKETPLACE_ENV] = marketplaceServer.marketplaceUrl;
console.error(`Plugin marketplace dev server: ${marketplaceServer.marketplaceUrl}`);
if (inherited !== undefined && inherited.length > 0 && inherited !== marketplaceServer.marketplaceUrl) {
console.error(
`(ignored inherited ${MARKETPLACE_ENV}=${inherited}; set ${EXTERNAL_MARKETPLACE_ENV} to use an external marketplace)`,
);
}
}
const tsxCli = require.resolve('tsx/cli');
const cliArgs = process.argv.slice(2);
if (cliArgs[0] === '--') cliArgs.shift();
const child = spawn(
process.execPath,
[
tsxCli,
// Use the dev tsconfig whose `include` covers packages/*/src, so tsx's
// esbuild transform sees `experimentalDecorators: true` for DI parameter
// decorators in agent-core. Mirrors `dev:server` in package.json.
'--tsconfig',
resolve(APP_ROOT, 'tsconfig.dev.json'),
'--import',
pathToFileURL(resolve(REPO_ROOT, 'build/register-raw-text-loader.mjs')).href,
resolve(APP_ROOT, 'src/main.ts'),
...cliArgs,
],
{
cwd: REPO_ROOT,
env,
stdio: 'inherit',
},
);
child.on('error', async (error) => {
console.error(`Failed to start Kimi Code dev CLI: ${error.message}`);
await marketplaceServer?.close();
process.exit(1);
});
child.on('exit', async (code, signal) => {
await marketplaceServer?.close();
if (signal !== null) {
process.exit(1);
}
process.exit(code ?? 0);
});