feat: add cli args

This commit is contained in:
mingholy.lmh
2025-11-19 16:05:01 +08:00
parent e1d6271263
commit e7f61d879e
5 changed files with 117 additions and 4 deletions

View File

@@ -11,6 +11,7 @@ import type {
import { extensionsCommand } from '../commands/extensions.js'; import { extensionsCommand } from '../commands/extensions.js';
import { import {
ApprovalMode, ApprovalMode,
AuthType,
Config, Config,
DEFAULT_QWEN_EMBEDDING_MODEL, DEFAULT_QWEN_EMBEDDING_MODEL,
DEFAULT_MEMORY_FILE_FILTERING_OPTIONS, DEFAULT_MEMORY_FILE_FILTERING_OPTIONS,
@@ -128,6 +129,10 @@ export interface CliArgs {
inputFormat?: string | undefined; inputFormat?: string | undefined;
outputFormat: string | undefined; outputFormat: string | undefined;
includePartialMessages?: boolean; includePartialMessages?: boolean;
maxSessionTurns: number | undefined;
coreTools: string[] | undefined;
excludeTools: string[] | undefined;
authType: string | undefined;
} }
function normalizeOutputFormat( function normalizeOutputFormat(
@@ -395,6 +400,31 @@ export async function parseArguments(settings: Settings): Promise<CliArgs> {
'Include partial assistant messages when using stream-json output.', 'Include partial assistant messages when using stream-json output.',
default: false, default: false,
}) })
.option('max-session-turns', {
type: 'number',
description: 'Maximum number of session turns',
})
.option('core-tools', {
type: 'array',
string: true,
description: 'Core tool paths',
coerce: (tools: string[]) =>
// Handle comma-separated values
tools.flatMap((tool) => tool.split(',').map((t) => t.trim())),
})
.option('exclude-tools', {
type: 'array',
string: true,
description: 'Tools to exclude',
coerce: (tools: string[]) =>
// Handle comma-separated values
tools.flatMap((tool) => tool.split(',').map((t) => t.trim())),
})
.option('auth-type', {
type: 'string',
choices: [AuthType.USE_OPENAI, AuthType.QWEN_OAUTH],
description: 'Authentication type',
})
.deprecateOption( .deprecateOption(
'show-memory-usage', 'show-memory-usage',
'Use the "ui.showMemoryUsage" setting in settings.json instead. This flag will be removed in a future version.', 'Use the "ui.showMemoryUsage" setting in settings.json instead. This flag will be removed in a future version.',
@@ -738,6 +768,7 @@ export async function loadCliConfig(
settings, settings,
activeExtensions, activeExtensions,
extraExcludes.length > 0 ? extraExcludes : undefined, extraExcludes.length > 0 ? extraExcludes : undefined,
argv.excludeTools,
); );
const blockedMcpServers: Array<{ name: string; extensionName: string }> = []; const blockedMcpServers: Array<{ name: string; extensionName: string }> = [];
@@ -793,7 +824,7 @@ export async function loadCliConfig(
debugMode, debugMode,
question, question,
fullContext: argv.allFiles || false, fullContext: argv.allFiles || false,
coreTools: settings.tools?.core || undefined, coreTools: argv.coreTools || settings.tools?.core || undefined,
allowedTools: argv.allowedTools || settings.tools?.allowed || undefined, allowedTools: argv.allowedTools || settings.tools?.allowed || undefined,
excludeTools, excludeTools,
toolDiscoveryCommand: settings.tools?.discoveryCommand, toolDiscoveryCommand: settings.tools?.discoveryCommand,
@@ -826,13 +857,16 @@ export async function loadCliConfig(
model: resolvedModel, model: resolvedModel,
extensionContextFilePaths, extensionContextFilePaths,
sessionTokenLimit: settings.model?.sessionTokenLimit ?? -1, sessionTokenLimit: settings.model?.sessionTokenLimit ?? -1,
maxSessionTurns: settings.model?.maxSessionTurns ?? -1, maxSessionTurns:
argv.maxSessionTurns ?? settings.model?.maxSessionTurns ?? -1,
experimentalZedIntegration: argv.experimentalAcp || false, experimentalZedIntegration: argv.experimentalAcp || false,
listExtensions: argv.listExtensions || false, listExtensions: argv.listExtensions || false,
extensions: allExtensions, extensions: allExtensions,
blockedMcpServers, blockedMcpServers,
noBrowser: !!process.env['NO_BROWSER'], noBrowser: !!process.env['NO_BROWSER'],
authType: settings.security?.auth?.selectedType, authType:
(argv.authType as AuthType | undefined) ||
settings.security?.auth?.selectedType,
inputFormat, inputFormat,
outputFormat, outputFormat,
includePartialMessages, includePartialMessages,
@@ -941,8 +975,10 @@ function mergeExcludeTools(
settings: Settings, settings: Settings,
extensions: Extension[], extensions: Extension[],
extraExcludes?: string[] | undefined, extraExcludes?: string[] | undefined,
cliExcludeTools?: string[] | undefined,
): string[] { ): string[] {
const allExcludeTools = new Set([ const allExcludeTools = new Set([
...(cliExcludeTools || []),
...(settings.tools?.exclude || []), ...(settings.tools?.exclude || []),
...(extraExcludes || []), ...(extraExcludes || []),
]); ]);

View File

@@ -73,6 +73,10 @@ export function query({
abortController, abortController,
debug: options.debug, debug: options.debug,
stderr: options.stderr, stderr: options.stderr,
maxSessionTurns: options.maxSessionTurns,
coreTools: options.coreTools,
excludeTools: options.excludeTools,
authType: options.authType,
}); });
// Build query options with abortController // Build query options with abortController

View File

@@ -166,6 +166,22 @@ export class ProcessTransport implements Transport {
} }
} }
if (this.options.maxSessionTurns !== undefined) {
args.push('--max-session-turns', String(this.options.maxSessionTurns));
}
if (this.options.coreTools && this.options.coreTools.length > 0) {
args.push('--core-tools', this.options.coreTools.join(','));
}
if (this.options.excludeTools && this.options.excludeTools.length > 0) {
args.push('--exclude-tools', this.options.excludeTools.join(','));
}
if (this.options.authType) {
args.push('--auth-type', this.options.authType);
}
return args; return args;
} }

View File

@@ -77,7 +77,7 @@ export type CreateQueryOptions = {
/** Permission mode ('default' | 'plan' | 'auto-edit' | 'yolo') */ /** Permission mode ('default' | 'plan' | 'auto-edit' | 'yolo') */
permissionMode?: PermissionMode; permissionMode?: PermissionMode;
/** Callback invoked before each tool execution */ /** Callback invoked before each tool execution */
canUseTool?: PermissionCallback; canUseTool?: CanUseTool;
// Hook system // Hook system
/** Hook configuration for tool execution lifecycle */ /** Hook configuration for tool execution lifecycle */
@@ -107,6 +107,14 @@ export type CreateQueryOptions = {
debug?: boolean; debug?: boolean;
/** Callback for stderr output */ /** Callback for stderr output */
stderr?: (message: string) => void; stderr?: (message: string) => void;
/** Maximum number of session turns */
maxSessionTurns?: number;
/** Core tool paths */
coreTools?: string[];
/** Tools to exclude */
excludeTools?: string[];
/** Authentication type */
authType?: string;
}; };
/** /**
@@ -131,4 +139,49 @@ export type TransportOptions = {
debug?: boolean; debug?: boolean;
/** Callback for stderr output */ /** Callback for stderr output */
stderr?: (message: string) => void; stderr?: (message: string) => void;
/** Maximum number of session turns */
maxSessionTurns?: number;
/** Core tool paths */
coreTools?: string[];
/** Tools to exclude */
excludeTools?: string[];
/** Authentication type */
authType?: string;
};
/**
* Tool input type
* TODO: align this type with actual tool inputs
*/
type ToolInput = Record<string, unknown>;
/**
* Permission callback function
* Called before each tool execution to determine if it should be allowed
*
* @param toolName - Name of the tool being executed
* @param input - Input parameters for the tool
* @param options - Options including abort signal
* @returns Promise with permission result
*/
type CanUseTool = (
toolName: string,
input: ToolInput,
options: {
signal: AbortSignal;
},
) => Promise<PermissionResult>;
/**
* Result of permission check
*/
type PermissionResult =
| {
behavior: 'allow';
updatedInput: ToolInput;
}
| {
behavior: 'deny';
message: string;
interrupt?: boolean;
}; };

View File

@@ -48,6 +48,10 @@ export const QueryOptionsSchema = z
(message: string) => void (message: string) => void
>((val) => typeof val === 'function', { message: 'stderr must be a function' }) >((val) => typeof val === 'function', { message: 'stderr must be a function' })
.optional(), .optional(),
maxSessionTurns: z.number().optional(),
coreTools: z.array(z.string()).optional(),
excludeTools: z.array(z.string()).optional(),
authType: z.enum(['openai', 'qwen-oauth']).optional(),
}) })
.strict(); .strict();