Merge tag 'v0.1.15' into feature/yiheng/sync-gemini-cli-0.1.15

This commit is contained in:
奕桁
2025-08-01 23:06:11 +08:00
340 changed files with 36528 additions and 22931 deletions

View File

@@ -17,7 +17,6 @@ import { start_sandbox } from './utils/sandbox.js';
import {
LoadedSettings,
loadSettings,
USER_SETTINGS_PATH,
SettingScope,
} from './config/settings.js';
import { themeManager } from './ui/themes/theme-manager.js';
@@ -40,6 +39,8 @@ import {
} from '@qwen-code/qwen-code-core';
import { validateAuthMethod } from './config/auth.js';
import { setMaxSizedBoxDebugging } from './ui/components/shared/MaxSizedBox.js';
import { validateNonInteractiveAuth } from './validateNonInterActiveAuth.js';
import { appEvents, AppEvent } from './utils/events.js';
function getNodeMemoryArgs(config: Config): string[] {
const totalMemoryMB = os.totalmem() / (1024 * 1024);
@@ -84,8 +85,32 @@ async function relaunchWithAdditionalArgs(additionalArgs: string[]) {
await new Promise((resolve) => child.on('close', resolve));
process.exit(0);
}
import { runAcpPeer } from './acp/acpPeer.js';
export function setupUnhandledRejectionHandler() {
let unhandledRejectionOccurred = false;
process.on('unhandledRejection', (reason, _promise) => {
const errorMessage = `=========================================
This is an unexpected error. Please file a bug report using the /bug tool.
CRITICAL: Unhandled Promise Rejection!
=========================================
Reason: ${reason}${
reason instanceof Error && reason.stack
? `
Stack trace:
${reason.stack}`
: ''
}`;
appEvents.emit(AppEvent.LogError, errorMessage);
if (!unhandledRejectionOccurred) {
unhandledRejectionOccurred = true;
appEvents.emit(AppEvent.OpenDebugConsole);
}
});
}
export async function main() {
setupUnhandledRejectionHandler();
const workspaceRoot = process.cwd();
const settings = loadSettings(workspaceRoot);
@@ -141,6 +166,9 @@ export async function main() {
await config.initialize();
// Load custom themes from settings
themeManager.loadCustomThemes(settings.merged.customThemes);
if (settings.merged.theme) {
if (!themeManager.setActiveTheme(settings.merged.theme)) {
// If the theme is not found during initial load, log a warning and continue.
@@ -183,12 +211,16 @@ export async function main() {
if (
settings.merged.selectedAuthType === AuthType.LOGIN_WITH_GOOGLE &&
config.getNoBrowser()
config.isBrowserLaunchSuppressed()
) {
// Do oauth before app renders to make copying the link possible.
await getOauthClient(settings.merged.selectedAuthType, config);
}
if (config.getExperimentalAcp()) {
return runAcpPeer(config, settings);
}
let input = config.getQuestion();
const startupWarnings = [
...(await getStartupWarnings()),
@@ -264,21 +296,6 @@ function setWindowTitle(title: string, settings: LoadedSettings) {
}
}
// --- Global Unhandled Rejection Handler ---
process.on('unhandledRejection', (reason, _promise) => {
// Log other unexpected unhandled rejections as critical errors
console.error('=========================================');
console.error('CRITICAL: Unhandled Promise Rejection!');
console.error('=========================================');
console.error('Reason:', reason);
console.error('Stack trace may follow:');
if (!(reason instanceof Error)) {
console.error(reason);
}
// Exit for genuinely unhandled errors
process.exit(1);
});
async function loadNonInteractiveConfig(
config: Config,
extensions: Extension[],
@@ -312,51 +329,8 @@ async function loadNonInteractiveConfig(
await finalConfig.initialize();
}
return await validateNonInterActiveAuth(
return await validateNonInteractiveAuth(
settings.merged.selectedAuthType,
finalConfig,
);
}
async function validateNonInterActiveAuth(
selectedAuthType: AuthType | undefined,
nonInteractiveConfig: Config,
) {
// making a special case for the cli. many headless environments might not have a settings.json set
// so if GEMINI_API_KEY or OPENAI_API_KEY is set, we'll use that. However since the oauth things are interactive anyway, we'll
// still expect that exists
if (
!selectedAuthType &&
!process.env.GEMINI_API_KEY &&
!process.env.OPENAI_API_KEY
) {
console.error(
`Please set an Auth method in your ${USER_SETTINGS_PATH} OR specify GEMINI_API_KEY or OPENAI_API_KEY env variable before running`,
);
process.exit(1);
}
// Determine auth type based on available environment variables
if (!selectedAuthType) {
if (process.env.OPENAI_API_KEY) {
selectedAuthType = AuthType.USE_OPENAI;
} else if (process.env.GEMINI_API_KEY) {
selectedAuthType = AuthType.USE_GEMINI;
}
}
// This should never happen due to the check above, but TypeScript needs assurance
if (!selectedAuthType) {
console.error('No valid authentication method found');
process.exit(1);
}
const err = validateAuthMethod(selectedAuthType);
if (err != null) {
console.error(err);
process.exit(1);
}
await nonInteractiveConfig.refreshAuth(selectedAuthType);
return nonInteractiveConfig;
}