mirror of
https://github.com/QwenLM/qwen-code.git
synced 2025-12-19 09:33:53 +00:00
Sync upstream Gemini-CLI v0.8.2 (#838)
This commit is contained in:
@@ -5,16 +5,16 @@
|
||||
*/
|
||||
|
||||
import type {
|
||||
ConfigParameters,
|
||||
FileFilteringOptions,
|
||||
MCPServerConfig,
|
||||
TelemetryTarget,
|
||||
OutputFormat,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import { extensionsCommand } from '../commands/extensions.js';
|
||||
import {
|
||||
ApprovalMode,
|
||||
Config,
|
||||
DEFAULT_GEMINI_EMBEDDING_MODEL,
|
||||
DEFAULT_GEMINI_MODEL,
|
||||
DEFAULT_QWEN_MODEL,
|
||||
DEFAULT_QWEN_EMBEDDING_MODEL,
|
||||
DEFAULT_MEMORY_FILE_FILTERING_OPTIONS,
|
||||
EditTool,
|
||||
FileDiscoveryService,
|
||||
@@ -23,24 +23,26 @@ import {
|
||||
setGeminiMdFilename as setServerGeminiMdFilename,
|
||||
ShellTool,
|
||||
WriteFileTool,
|
||||
resolveTelemetrySettings,
|
||||
FatalConfigError,
|
||||
} from '@qwen-code/qwen-code-core';
|
||||
import * as fs from 'node:fs';
|
||||
import { homedir } from 'node:os';
|
||||
import * as path from 'node:path';
|
||||
import process from 'node:process';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
import yargs from 'yargs/yargs';
|
||||
import { extensionsCommand } from '../commands/extensions.js';
|
||||
import { mcpCommand } from '../commands/mcp.js';
|
||||
import type { Settings } from './settings.js';
|
||||
import yargs, { type Argv } from 'yargs';
|
||||
import { hideBin } from 'yargs/helpers';
|
||||
import * as fs from 'node:fs';
|
||||
import * as path from 'node:path';
|
||||
import { homedir } from 'node:os';
|
||||
|
||||
import { resolvePath } from '../utils/resolvePath.js';
|
||||
import { getCliVersion } from '../utils/version.js';
|
||||
import type { Extension } from './extension.js';
|
||||
import { annotateActiveExtensions } from './extension.js';
|
||||
import { loadSandboxConfig } from './sandboxConfig.js';
|
||||
import { appEvents } from '../utils/events.js';
|
||||
import { mcpCommand } from '../commands/mcp.js';
|
||||
|
||||
import { isWorkspaceTrusted } from './trustedFolders.js';
|
||||
import type { ExtensionEnablementManager } from './extensions/extensionEnablement.js';
|
||||
|
||||
// Simple console logger for now - replace with actual logger if available
|
||||
const logger = {
|
||||
@@ -86,6 +88,7 @@ function parseApprovalModeValue(value: string): ApprovalMode {
|
||||
}
|
||||
|
||||
export interface CliArgs {
|
||||
query: string | undefined;
|
||||
model: string | undefined;
|
||||
sandbox: boolean | string | undefined;
|
||||
sandboxImage: string | undefined;
|
||||
@@ -116,23 +119,98 @@ export interface CliArgs {
|
||||
tavilyApiKey: string | undefined;
|
||||
screenReader: boolean | undefined;
|
||||
vlmSwitchMode: string | undefined;
|
||||
useSmartEdit: boolean | undefined;
|
||||
outputFormat: string | undefined;
|
||||
}
|
||||
|
||||
export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
const yargsInstance = yargs(hideBin(process.argv))
|
||||
// Set locale to English for consistent output, especially in tests
|
||||
const rawArgv = hideBin(process.argv);
|
||||
const yargsInstance = yargs(rawArgv)
|
||||
.locale('en')
|
||||
.scriptName('qwen')
|
||||
.usage(
|
||||
'Usage: qwen [options] [command]\n\nQwen Code - Launch an interactive CLI, use -p/--prompt for non-interactive mode',
|
||||
)
|
||||
.command('$0', 'Launch Qwen Code', (yargsInstance) =>
|
||||
.option('telemetry', {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Enable telemetry? This flag specifically controls if telemetry is sent. Other --telemetry-* flags set specific values but do not enable telemetry on their own.',
|
||||
})
|
||||
.option('telemetry-target', {
|
||||
type: 'string',
|
||||
choices: ['local', 'gcp'],
|
||||
description:
|
||||
'Set the telemetry target (local or gcp). Overrides settings files.',
|
||||
})
|
||||
.option('telemetry-otlp-endpoint', {
|
||||
type: 'string',
|
||||
description:
|
||||
'Set the OTLP endpoint for telemetry. Overrides environment variables and settings files.',
|
||||
})
|
||||
.option('telemetry-otlp-protocol', {
|
||||
type: 'string',
|
||||
choices: ['grpc', 'http'],
|
||||
description:
|
||||
'Set the OTLP protocol for telemetry (grpc or http). Overrides settings files.',
|
||||
})
|
||||
.option('telemetry-log-prompts', {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Enable or disable logging of user prompts for telemetry. Overrides settings files.',
|
||||
})
|
||||
.option('telemetry-outfile', {
|
||||
type: 'string',
|
||||
description: 'Redirect all telemetry output to the specified file.',
|
||||
})
|
||||
.deprecateOption(
|
||||
'telemetry',
|
||||
'Use the "telemetry.enabled" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.deprecateOption(
|
||||
'telemetry-target',
|
||||
'Use the "telemetry.target" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.deprecateOption(
|
||||
'telemetry-otlp-endpoint',
|
||||
'Use the "telemetry.otlpEndpoint" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.deprecateOption(
|
||||
'telemetry-otlp-protocol',
|
||||
'Use the "telemetry.otlpProtocol" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.deprecateOption(
|
||||
'telemetry-log-prompts',
|
||||
'Use the "telemetry.logPrompts" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.deprecateOption(
|
||||
'telemetry-outfile',
|
||||
'Use the "telemetry.outfile" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.option('debug', {
|
||||
alias: 'd',
|
||||
type: 'boolean',
|
||||
description: 'Run in debug mode?',
|
||||
default: false,
|
||||
})
|
||||
.option('proxy', {
|
||||
type: 'string',
|
||||
description:
|
||||
'Proxy for gemini client, like schema://user:password@host:port',
|
||||
})
|
||||
.deprecateOption(
|
||||
'proxy',
|
||||
'Use the "proxy" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.command('$0 [query..]', 'Launch Gemini CLI', (yargsInstance: Argv) =>
|
||||
yargsInstance
|
||||
.positional('query', {
|
||||
description:
|
||||
'Positional prompt. Defaults to one-shot; use -i/--prompt-interactive for interactive.',
|
||||
})
|
||||
.option('model', {
|
||||
alias: 'm',
|
||||
type: 'string',
|
||||
description: `Model`,
|
||||
default: process.env['GEMINI_MODEL'],
|
||||
})
|
||||
.option('prompt', {
|
||||
alias: 'p',
|
||||
@@ -154,12 +232,6 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
type: 'string',
|
||||
description: 'Sandbox image URI.',
|
||||
})
|
||||
.option('debug', {
|
||||
alias: 'd',
|
||||
type: 'boolean',
|
||||
description: 'Run in debug mode?',
|
||||
default: false,
|
||||
})
|
||||
.option('all-files', {
|
||||
alias: ['a'],
|
||||
type: 'boolean',
|
||||
@@ -184,37 +256,6 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
description:
|
||||
'Set the approval mode: plan (plan only), default (prompt for approval), auto-edit (auto-approve edit tools), yolo (auto-approve all tools)',
|
||||
})
|
||||
.option('telemetry', {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Enable telemetry? This flag specifically controls if telemetry is sent. Other --telemetry-* flags set specific values but do not enable telemetry on their own.',
|
||||
})
|
||||
.option('telemetry-target', {
|
||||
type: 'string',
|
||||
choices: ['local', 'gcp'],
|
||||
description:
|
||||
'Set the telemetry target (local or gcp). Overrides settings files.',
|
||||
})
|
||||
.option('telemetry-otlp-endpoint', {
|
||||
type: 'string',
|
||||
description:
|
||||
'Set the OTLP endpoint for telemetry. Overrides environment variables and settings files.',
|
||||
})
|
||||
.option('telemetry-otlp-protocol', {
|
||||
type: 'string',
|
||||
choices: ['grpc', 'http'],
|
||||
description:
|
||||
'Set the OTLP protocol for telemetry (grpc or http). Overrides settings files.',
|
||||
})
|
||||
.option('telemetry-log-prompts', {
|
||||
type: 'boolean',
|
||||
description:
|
||||
'Enable or disable logging of user prompts for telemetry. Overrides settings files.',
|
||||
})
|
||||
.option('telemetry-outfile', {
|
||||
type: 'string',
|
||||
description: 'Redirect all telemetry output to the specified file.',
|
||||
})
|
||||
.option('checkpointing', {
|
||||
alias: 'c',
|
||||
type: 'boolean',
|
||||
@@ -229,11 +270,19 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
type: 'array',
|
||||
string: true,
|
||||
description: 'Allowed MCP server names',
|
||||
coerce: (mcpServerNames: string[]) =>
|
||||
// Handle comma-separated values
|
||||
mcpServerNames.flatMap((mcpServerName) =>
|
||||
mcpServerName.split(',').map((m) => m.trim()),
|
||||
),
|
||||
})
|
||||
.option('allowed-tools', {
|
||||
type: 'array',
|
||||
string: true,
|
||||
description: 'Tools that are allowed to run without confirmation',
|
||||
coerce: (tools: string[]) =>
|
||||
// Handle comma-separated values
|
||||
tools.flatMap((tool) => tool.split(',').map((t) => t.trim())),
|
||||
})
|
||||
.option('extensions', {
|
||||
alias: 'e',
|
||||
@@ -241,17 +290,17 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
string: true,
|
||||
description:
|
||||
'A list of extensions to use. If not provided, all extensions are used.',
|
||||
coerce: (extensions: string[]) =>
|
||||
// Handle comma-separated values
|
||||
extensions.flatMap((extension) =>
|
||||
extension.split(',').map((e) => e.trim()),
|
||||
),
|
||||
})
|
||||
.option('list-extensions', {
|
||||
alias: 'l',
|
||||
type: 'boolean',
|
||||
description: 'List all available extensions and exit.',
|
||||
})
|
||||
.option('proxy', {
|
||||
type: 'string',
|
||||
description:
|
||||
'Proxy for qwen client, like schema://user:password@host:port',
|
||||
})
|
||||
.option('include-directories', {
|
||||
type: 'array',
|
||||
string: true,
|
||||
@@ -281,7 +330,6 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
.option('screen-reader', {
|
||||
type: 'boolean',
|
||||
description: 'Enable screen reader mode for accessibility.',
|
||||
default: false,
|
||||
})
|
||||
.option('vlm-switch-mode', {
|
||||
type: 'string',
|
||||
@@ -290,16 +338,54 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
'Default behavior when images are detected in input. Values: once (one-time switch), session (switch for entire session), persist (continue with current model). Overrides settings files.',
|
||||
default: process.env['VLM_SWITCH_MODE'],
|
||||
})
|
||||
.check((argv) => {
|
||||
if (argv.prompt && argv['promptInteractive']) {
|
||||
throw new Error(
|
||||
'Cannot use both --prompt (-p) and --prompt-interactive (-i) together',
|
||||
);
|
||||
.option('output-format', {
|
||||
alias: 'o',
|
||||
type: 'string',
|
||||
description: 'The format of the CLI output.',
|
||||
choices: ['text', 'json'],
|
||||
})
|
||||
.deprecateOption(
|
||||
'show-memory-usage',
|
||||
'Use the "ui.showMemoryUsage" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.deprecateOption(
|
||||
'sandbox-image',
|
||||
'Use the "tools.sandbox" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.deprecateOption(
|
||||
'checkpointing',
|
||||
'Use the "general.checkpointing.enabled" setting in settings.json instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.deprecateOption(
|
||||
'all-files',
|
||||
'Use @ includes in the application instead. This flag will be removed in a future version.',
|
||||
)
|
||||
.deprecateOption(
|
||||
'prompt',
|
||||
'Use the positional prompt instead. This flag will be removed in a future version.',
|
||||
)
|
||||
// Ensure validation flows through .fail() for clean UX
|
||||
.fail((msg: string, err: Error | undefined, yargs: Argv) => {
|
||||
console.error(msg || err?.message || 'Unknown error');
|
||||
yargs.showHelp();
|
||||
process.exit(1);
|
||||
})
|
||||
.check((argv: { [x: string]: unknown }) => {
|
||||
// The 'query' positional can be a string (for one arg) or string[] (for multiple).
|
||||
// This guard safely checks if any positional argument was provided.
|
||||
const query = argv['query'] as string | string[] | undefined;
|
||||
const hasPositionalQuery = Array.isArray(query)
|
||||
? query.length > 0
|
||||
: !!query;
|
||||
|
||||
if (argv['prompt'] && hasPositionalQuery) {
|
||||
return 'Cannot use both a positional prompt and the --prompt (-p) flag together';
|
||||
}
|
||||
if (argv.yolo && argv['approvalMode']) {
|
||||
throw new Error(
|
||||
'Cannot use both --yolo (-y) and --approval-mode together. Use --approval-mode=yolo instead.',
|
||||
);
|
||||
if (argv['prompt'] && argv['promptInteractive']) {
|
||||
return 'Cannot use both --prompt (-p) and --prompt-interactive (-i) together';
|
||||
}
|
||||
if (argv['yolo'] && argv['approvalMode']) {
|
||||
return 'Cannot use both --yolo (-y) and --approval-mode together. Use --approval-mode=yolo instead.';
|
||||
}
|
||||
return true;
|
||||
}),
|
||||
@@ -307,7 +393,7 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
// Register MCP subcommands
|
||||
.command(mcpCommand);
|
||||
|
||||
if (settings?.experimental?.extensionManagement ?? false) {
|
||||
if (settings?.experimental?.extensionManagement ?? true) {
|
||||
yargsInstance.command(extensionsCommand);
|
||||
}
|
||||
|
||||
@@ -322,6 +408,8 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
yargsInstance.wrap(yargsInstance.terminalWidth());
|
||||
const result = await yargsInstance.parse();
|
||||
|
||||
// If yargs handled --help/--version it will have exited; nothing to do here.
|
||||
|
||||
// Handle case where MCP subcommands are executed - they should exit the process
|
||||
// and not return to main CLI logic
|
||||
if (
|
||||
@@ -332,6 +420,26 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
// Normalize query args: handle both quoted "@path file" and unquoted @path file
|
||||
const queryArg = (result as { query?: string | string[] | undefined }).query;
|
||||
const q: string | undefined = Array.isArray(queryArg)
|
||||
? queryArg.join(' ')
|
||||
: queryArg;
|
||||
|
||||
// Route positional args: explicit -i flag -> interactive; else -> one-shot (even for @commands)
|
||||
if (q && !result['prompt']) {
|
||||
const hasExplicitInteractive =
|
||||
result['promptInteractive'] === '' || !!result['promptInteractive'];
|
||||
if (hasExplicitInteractive) {
|
||||
result['promptInteractive'] = q;
|
||||
} else {
|
||||
result['prompt'] = q;
|
||||
}
|
||||
}
|
||||
|
||||
// Keep CliArgs.query as a string for downstream typing
|
||||
(result as Record<string, unknown>)['query'] = q || undefined;
|
||||
|
||||
// The import format is now only controlled by settings.memoryImportFormat
|
||||
// We no longer accept it as a CLI argument
|
||||
return result as unknown as CliArgs;
|
||||
@@ -347,6 +455,7 @@ export async function loadHierarchicalGeminiMemory(
|
||||
fileService: FileDiscoveryService,
|
||||
settings: Settings,
|
||||
extensionContextFilePaths: string[] = [],
|
||||
folderTrust: boolean,
|
||||
memoryImportFormat: 'flat' | 'tree' = 'tree',
|
||||
fileFilteringOptions?: FileFilteringOptions,
|
||||
): Promise<{ memoryContent: string; fileCount: number }> {
|
||||
@@ -372,58 +481,48 @@ export async function loadHierarchicalGeminiMemory(
|
||||
debugMode,
|
||||
fileService,
|
||||
extensionContextFilePaths,
|
||||
folderTrust,
|
||||
memoryImportFormat,
|
||||
fileFilteringOptions,
|
||||
settings.context?.discoveryMaxDirs,
|
||||
);
|
||||
}
|
||||
|
||||
export function isDebugMode(argv: CliArgs): boolean {
|
||||
return (
|
||||
argv.debug ||
|
||||
[process.env['DEBUG'], process.env['DEBUG_MODE']].some(
|
||||
(v) => v === 'true' || v === '1',
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
export async function loadCliConfig(
|
||||
settings: Settings,
|
||||
extensions: Extension[],
|
||||
extensionEnablementManager: ExtensionEnablementManager,
|
||||
sessionId: string,
|
||||
argv: CliArgs,
|
||||
cwd: string = process.cwd(),
|
||||
): Promise<Config> {
|
||||
const debugMode =
|
||||
argv.debug ||
|
||||
[process.env['DEBUG'], process.env['DEBUG_MODE']].some(
|
||||
(v) => v === 'true' || v === '1',
|
||||
) ||
|
||||
false;
|
||||
const debugMode = isDebugMode(argv);
|
||||
|
||||
const memoryImportFormat = settings.context?.importFormat || 'tree';
|
||||
|
||||
const ideMode = settings.ide?.enabled ?? false;
|
||||
|
||||
const folderTrustFeature =
|
||||
settings.security?.folderTrust?.featureEnabled ?? false;
|
||||
const folderTrustSetting = settings.security?.folderTrust?.enabled ?? true;
|
||||
const folderTrust = folderTrustFeature && folderTrustSetting;
|
||||
const trustedFolder = isWorkspaceTrusted(settings);
|
||||
const folderTrust = settings.security?.folderTrust?.enabled ?? false;
|
||||
const trustedFolder = isWorkspaceTrusted(settings)?.isTrusted ?? true;
|
||||
|
||||
const allExtensions = annotateActiveExtensions(
|
||||
extensions,
|
||||
argv.extensions || [],
|
||||
cwd,
|
||||
extensionEnablementManager,
|
||||
);
|
||||
|
||||
const activeExtensions = extensions.filter(
|
||||
(_, i) => allExtensions[i].isActive,
|
||||
);
|
||||
// Handle OpenAI API key from command line
|
||||
if (argv.openaiApiKey) {
|
||||
process.env['OPENAI_API_KEY'] = argv.openaiApiKey;
|
||||
}
|
||||
|
||||
// Handle OpenAI base URL from command line
|
||||
if (argv.openaiBaseUrl) {
|
||||
process.env['OPENAI_BASE_URL'] = argv.openaiBaseUrl;
|
||||
}
|
||||
|
||||
// Handle Tavily API key from command line
|
||||
if (argv.tavilyApiKey) {
|
||||
process.env['TAVILY_API_KEY'] = argv.tavilyApiKey;
|
||||
}
|
||||
|
||||
// Set the context filename in the server's memoryTool module BEFORE loading memory
|
||||
// TODO(b/343434939): This is a bit of a hack. The contextFileName should ideally be passed
|
||||
@@ -461,6 +560,7 @@ export async function loadCliConfig(
|
||||
fileService,
|
||||
settings,
|
||||
extensionContextFilePaths,
|
||||
trustedFolder,
|
||||
memoryImportFormat,
|
||||
fileFiltering,
|
||||
);
|
||||
@@ -474,8 +574,8 @@ export async function loadCliConfig(
|
||||
approvalMode = parseApprovalModeValue(argv.approvalMode);
|
||||
} else if (argv.yolo) {
|
||||
approvalMode = ApprovalMode.YOLO;
|
||||
} else if (settings.approvalMode) {
|
||||
approvalMode = parseApprovalModeValue(settings.approvalMode);
|
||||
} else if (settings.tools?.approvalMode) {
|
||||
approvalMode = parseApprovalModeValue(settings.tools.approvalMode);
|
||||
} else {
|
||||
approvalMode = ApprovalMode.DEFAULT;
|
||||
}
|
||||
@@ -492,8 +592,27 @@ export async function loadCliConfig(
|
||||
approvalMode = ApprovalMode.DEFAULT;
|
||||
}
|
||||
|
||||
let telemetrySettings;
|
||||
try {
|
||||
telemetrySettings = await resolveTelemetrySettings({
|
||||
argv,
|
||||
env: process.env as unknown as Record<string, string | undefined>,
|
||||
settings: settings.telemetry,
|
||||
});
|
||||
} catch (err) {
|
||||
if (err instanceof FatalConfigError) {
|
||||
throw new FatalConfigError(
|
||||
`Invalid telemetry configuration: ${err.message}.`,
|
||||
);
|
||||
}
|
||||
throw err;
|
||||
}
|
||||
|
||||
// Interactive mode: explicit -i flag or (TTY + no args + no -p flag)
|
||||
const hasQuery = !!argv.query;
|
||||
const interactive =
|
||||
!!argv.promptInteractive || (process.stdin.isTTY && question.length === 0);
|
||||
!!argv.promptInteractive ||
|
||||
(process.stdin.isTTY && !hasQuery && !argv.prompt);
|
||||
// In non-interactive mode, exclude tools that require a prompt.
|
||||
const extraExcludes: string[] = [];
|
||||
if (!interactive && !argv.experimentalAcp) {
|
||||
@@ -550,9 +669,15 @@ export async function loadCliConfig(
|
||||
);
|
||||
}
|
||||
|
||||
const sandboxConfig = await loadSandboxConfig(settings, argv);
|
||||
const cliVersion = await getCliVersion();
|
||||
const defaultModel = DEFAULT_QWEN_MODEL;
|
||||
const resolvedModel: string =
|
||||
argv.model ||
|
||||
process.env['OPENAI_MODEL'] ||
|
||||
process.env['QWEN_MODEL'] ||
|
||||
settings.model?.name ||
|
||||
defaultModel;
|
||||
|
||||
const sandboxConfig = await loadSandboxConfig(settings, argv);
|
||||
const screenReader =
|
||||
argv.screenReader !== undefined
|
||||
? argv.screenReader
|
||||
@@ -562,7 +687,7 @@ export async function loadCliConfig(
|
||||
argv.vlmSwitchMode || settings.experimental?.vlmSwitchMode;
|
||||
return new Config({
|
||||
sessionId,
|
||||
embeddingModel: DEFAULT_GEMINI_EMBEDDING_MODEL,
|
||||
embeddingModel: DEFAULT_QWEN_EMBEDDING_MODEL,
|
||||
sandbox: sandboxConfig,
|
||||
targetDir: cwd,
|
||||
includeDirectories,
|
||||
@@ -587,31 +712,9 @@ export async function loadCliConfig(
|
||||
...settings.ui?.accessibility,
|
||||
screenReader,
|
||||
},
|
||||
telemetry: {
|
||||
enabled: argv.telemetry ?? settings.telemetry?.enabled,
|
||||
target: (argv.telemetryTarget ??
|
||||
settings.telemetry?.target) as TelemetryTarget,
|
||||
otlpEndpoint:
|
||||
argv.telemetryOtlpEndpoint ??
|
||||
process.env['OTEL_EXPORTER_OTLP_ENDPOINT'] ??
|
||||
settings.telemetry?.otlpEndpoint,
|
||||
otlpProtocol: (['grpc', 'http'] as const).find(
|
||||
(p) =>
|
||||
p ===
|
||||
(argv.telemetryOtlpProtocol ?? settings.telemetry?.otlpProtocol),
|
||||
),
|
||||
logPrompts: argv.telemetryLogPrompts ?? settings.telemetry?.logPrompts,
|
||||
outfile: argv.telemetryOutfile ?? settings.telemetry?.outfile,
|
||||
},
|
||||
telemetry: telemetrySettings,
|
||||
usageStatisticsEnabled: settings.privacy?.usageStatisticsEnabled ?? true,
|
||||
// Git-aware file filtering settings
|
||||
fileFiltering: {
|
||||
respectGitIgnore: settings.context?.fileFiltering?.respectGitIgnore,
|
||||
respectGeminiIgnore: settings.context?.fileFiltering?.respectGeminiIgnore,
|
||||
enableRecursiveFileSearch:
|
||||
settings.context?.fileFiltering?.enableRecursiveFileSearch,
|
||||
disableFuzzySearch: settings.context?.fileFiltering?.disableFuzzySearch,
|
||||
},
|
||||
fileFiltering: settings.context?.fileFiltering,
|
||||
checkpointing:
|
||||
argv.checkpointing || settings.general?.checkpointing?.enabled,
|
||||
proxy:
|
||||
@@ -623,50 +726,51 @@ export async function loadCliConfig(
|
||||
cwd,
|
||||
fileDiscoveryService: fileService,
|
||||
bugCommand: settings.advanced?.bugCommand,
|
||||
model: argv.model || settings.model?.name || DEFAULT_GEMINI_MODEL,
|
||||
model: resolvedModel,
|
||||
extensionContextFilePaths,
|
||||
sessionTokenLimit: settings.sessionTokenLimit ?? -1,
|
||||
sessionTokenLimit: settings.model?.sessionTokenLimit ?? -1,
|
||||
maxSessionTurns: settings.model?.maxSessionTurns ?? -1,
|
||||
experimentalZedIntegration: argv.experimentalAcp || false,
|
||||
listExtensions: argv.listExtensions || false,
|
||||
extensions: allExtensions,
|
||||
blockedMcpServers,
|
||||
noBrowser: !!process.env['NO_BROWSER'],
|
||||
enableOpenAILogging:
|
||||
(typeof argv.openaiLogging === 'undefined'
|
||||
? settings.enableOpenAILogging
|
||||
: argv.openaiLogging) ?? false,
|
||||
systemPromptMappings: (settings.systemPromptMappings ?? [
|
||||
{
|
||||
baseUrls: [
|
||||
'https://dashscope.aliyuncs.com/compatible-mode/v1/',
|
||||
'https://dashscope-intl.aliyuncs.com/compatible-mode/v1/',
|
||||
],
|
||||
modelNames: ['qwen3-coder-plus'],
|
||||
template:
|
||||
'SYSTEM_TEMPLATE:{"name":"qwen3_coder","params":{"is_git_repository":{RUNTIME_VARS_IS_GIT_REPO},"sandbox":"{RUNTIME_VARS_SANDBOX}"}}',
|
||||
},
|
||||
]) as ConfigParameters['systemPromptMappings'],
|
||||
authType: settings.security?.auth?.selectedType,
|
||||
contentGenerator: settings.contentGenerator,
|
||||
cliVersion,
|
||||
generationConfig: {
|
||||
...(settings.model?.generationConfig || {}),
|
||||
model: resolvedModel,
|
||||
apiKey: argv.openaiApiKey || process.env['OPENAI_API_KEY'],
|
||||
baseUrl: argv.openaiBaseUrl || process.env['OPENAI_BASE_URL'],
|
||||
enableOpenAILogging:
|
||||
(typeof argv.openaiLogging === 'undefined'
|
||||
? settings.model?.enableOpenAILogging
|
||||
: argv.openaiLogging) ?? false,
|
||||
},
|
||||
cliVersion: await getCliVersion(),
|
||||
tavilyApiKey:
|
||||
argv.tavilyApiKey ||
|
||||
settings.tavilyApiKey ||
|
||||
settings.advanced?.tavilyApiKey ||
|
||||
process.env['TAVILY_API_KEY'],
|
||||
summarizeToolOutput: settings.model?.summarizeToolOutput,
|
||||
ideMode,
|
||||
chatCompression: settings.model?.chatCompression,
|
||||
folderTrustFeature,
|
||||
folderTrust,
|
||||
interactive,
|
||||
trustedFolder,
|
||||
useRipgrep: settings.tools?.useRipgrep,
|
||||
shouldUseNodePtyShell: settings.tools?.usePty,
|
||||
shouldUseNodePtyShell: settings.tools?.shell?.enableInteractiveShell,
|
||||
skipNextSpeakerCheck: settings.model?.skipNextSpeakerCheck,
|
||||
enablePromptCompletion: settings.general?.enablePromptCompletion ?? false,
|
||||
skipLoopDetection: settings.skipLoopDetection ?? false,
|
||||
skipLoopDetection: settings.model?.skipLoopDetection ?? false,
|
||||
vlmSwitchMode,
|
||||
truncateToolOutputThreshold: settings.tools?.truncateToolOutputThreshold,
|
||||
truncateToolOutputLines: settings.tools?.truncateToolOutputLines,
|
||||
enableToolOutputTruncation: settings.tools?.enableToolOutputTruncation,
|
||||
eventEmitter: appEvents,
|
||||
useSmartEdit: argv.useSmartEdit ?? settings.useSmartEdit,
|
||||
output: {
|
||||
format: (argv.outputFormat ?? settings.output?.format) as OutputFormat,
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user