fix: 修复 Windows + Node.js 环境下启动卡死及 TDZ 错误

- cli.tsx: shebang 改为 node,添加 Bun polyfill 和全局错误处理器,避免静默挂起
- openaiAdapter.ts: 修复 providerId 在声明前使用的 TDZ 错误(Node.js 严格模式报错)
- build.ts: 构建后处理增强,注入 Node.js 兼容性 shim 和 shebang 替换

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
weiqianpu
2026-04-01 23:44:25 +00:00
co-authored by Claude Opus 4.6
parent 3b0a5e484d
commit 5d0bc60cce
3 changed files with 742 additions and 13 deletions
+50 -4
View File
@@ -1,4 +1,4 @@
#!/usr/bin/env bun
#!/usr/bin/env node
// Runtime polyfill for bun:bundle (build-time macros)
const feature = (_name: string) => false;
if (typeof globalThis.MACRO === "undefined") {
@@ -17,6 +17,12 @@ if (typeof globalThis.MACRO === "undefined") {
(globalThis as any).BUILD_ENV = "production";
(globalThis as any).INTERFACE_TYPE = "stdio";
// ── Windows + Node.js compatibility shims ──
// Polyfill Bun globals for Node.js runtime
if (typeof globalThis.Bun === "undefined") {
(globalThis as any).Bun = undefined;
}
// Bugfix for corepack auto-pinning, which adds yarnpkg to peoples' package.jsons
// eslint-disable-next-line custom-rules/no-top-level-side-effects
process.env.COREPACK_ENABLE_AUTO_PIN = "0";
@@ -66,11 +72,34 @@ async function main(): Promise<void> {
(args[0] === "--version" || args[0] === "-v" || args[0] === "-V")
) {
// MACRO.VERSION is inlined at build time
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(`${MACRO.VERSION} (Claude Code)`);
console.log(`${MACRO.VERSION} (嘉陵江-code)`);
return;
}
// ── 嘉陵江-code setup wizard ──
// Run on first launch or with --setup flag
{
const { loadConfig, hasConfig, runSetupWizard, applyConfig } = await import("../services/api/setupWizard.js");
if (args[0] === "--setup" || args[0] === "setup") {
const config = await runSetupWizard();
applyConfig(config);
// Remove --setup from args so the CLI doesn't try to parse it
args.shift();
if (args.length === 0) {
// Continue to normal REPL
}
} else if (!hasConfig() && !process.env.ANTHROPIC_API_KEY && args[0] !== '-p' && args[0] !== '--print') {
// First run, no config, no Anthropic key, interactive mode → show wizard
const config = await runSetupWizard();
applyConfig(config);
} else if (hasConfig()) {
// Load saved config and apply to environment
const config = loadConfig();
if (config) applyConfig(config);
}
}
// For all other paths, load the startup profiler
const { profileCheckpoint } = await import("../utils/startupProfiler.js");
profileCheckpoint("cli_entry");
@@ -88,7 +117,6 @@ async function main(): Promise<void> {
(modelIdx !== -1 && args[modelIdx + 1]) || getMainLoopModel();
const { getSystemPrompt } = await import("../constants/prompts.js");
const prompt = await getSystemPrompt([], model);
// biome-ignore lint/suspicious/noConsole:: intentional console output
console.log(prompt.join("\n"));
return;
}
@@ -316,5 +344,23 @@ async function main(): Promise<void> {
profileCheckpoint("cli_after_main_complete");
}
// Global error handlers to surface silent failures (especially on Windows + Node.js)
process.on("uncaughtException", (err) => {
process.stderr.write(`\n嘉陵江-code 启动异常: ${err?.message || err}\n`);
if (err?.stack) {
process.stderr.write(`${err.stack}\n`);
}
process.exit(1);
});
process.on("unhandledRejection", (reason) => {
const msg = reason instanceof Error ? reason.message : String(reason);
const stack = reason instanceof Error ? reason.stack : undefined;
process.stderr.write(`\n嘉陵江-code 启动异常 (unhandledRejection): ${msg}\n`);
if (stack) {
process.stderr.write(`${stack}\n`);
}
process.exit(1);
});
// eslint-disable-next-line custom-rules/no-top-level-side-effects
void main();