diff --git a/packages/cli/src/commands/extensions/configure.ts b/packages/cli/src/commands/extensions/configure.ts index a2136968b3..4d3dcb2177 100644 --- a/packages/cli/src/commands/extensions/configure.ts +++ b/packages/cli/src/commands/extensions/configure.ts @@ -5,7 +5,7 @@ */ import type { CommandModule } from 'yargs'; -import type { ExtensionSettingScope } from '../../config/extensions/extensionSettings.js'; +import { ExtensionSettingScope } from '../../config/extensions/extensionSettings.js'; import { configureAllExtensions, configureExtension, @@ -64,6 +64,10 @@ export const configureCommand: CommandModule = { } const extensionManager = await getExtensionManager(); + const effectiveScope = + scope === 'workspace' + ? ExtensionSettingScope.WORKSPACE + : ExtensionSettingScope.USER; // Case 1: Configure specific setting for an extension if (name && setting) { @@ -71,26 +75,16 @@ export const configureCommand: CommandModule = { extensionManager, name, setting, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - scope as ExtensionSettingScope, + effectiveScope, ); } // Case 2: Configure all settings for an extension else if (name) { - await configureExtension( - extensionManager, - name, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - scope as ExtensionSettingScope, - ); + await configureExtension(extensionManager, name, effectiveScope); } // Case 3: Configure all extensions else { - await configureAllExtensions( - extensionManager, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - scope as ExtensionSettingScope, - ); + await configureAllExtensions(extensionManager, effectiveScope); } await exitCli(); diff --git a/packages/cli/src/commands/extensions/disable.ts b/packages/cli/src/commands/extensions/disable.ts index dae97ea584..95ce838241 100644 --- a/packages/cli/src/commands/extensions/disable.ts +++ b/packages/cli/src/commands/extensions/disable.ts @@ -77,11 +77,11 @@ export const disableCommand: CommandModule = { return true; }), handler: async (argv) => { + const name = argv['name']; + const scope = argv['scope']; await handleDisable({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - name: argv['name'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - scope: argv['scope'] as string, + name: typeof name === 'string' ? name : '', + scope: typeof scope === 'string' ? scope : undefined, }); await exitCli(); }, diff --git a/packages/cli/src/commands/extensions/enable.ts b/packages/cli/src/commands/extensions/enable.ts index e0976aa10a..81d86422b4 100644 --- a/packages/cli/src/commands/extensions/enable.ts +++ b/packages/cli/src/commands/extensions/enable.ts @@ -104,11 +104,11 @@ export const enableCommand: CommandModule = { return true; }), handler: async (argv) => { + const name = argv['name']; + const scope = argv['scope']; await handleEnable({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - name: argv['name'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - scope: argv['scope'] as string, + name: typeof name === 'string' ? name : '', + scope: typeof scope === 'string' ? scope : undefined, }); await exitCli(); }, diff --git a/packages/cli/src/commands/extensions/install.ts b/packages/cli/src/commands/extensions/install.ts index cf135a9366..ed97b2b93c 100644 --- a/packages/cli/src/commands/extensions/install.ts +++ b/packages/cli/src/commands/extensions/install.ts @@ -209,19 +209,23 @@ export const installCommand: CommandModule = { return true; }), handler: async (argv) => { + const source = argv['source']; + const ref = argv['ref']; + const autoUpdate = argv['auto-update']; + const allowPreRelease = argv['pre-release']; + const consent = argv['consent']; + await handleInstall({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - source: argv['source'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - ref: argv['ref'] as string | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - autoUpdate: argv['auto-update'] as boolean | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - allowPreRelease: argv['pre-release'] as boolean | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - consent: argv['consent'] as boolean | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - skipSettings: argv['skip-settings'] as boolean | undefined, + source: typeof source === 'string' ? source : '', + ref: typeof ref === 'string' ? ref : undefined, + autoUpdate: typeof autoUpdate === 'boolean' ? autoUpdate : undefined, + allowPreRelease: + typeof allowPreRelease === 'boolean' ? allowPreRelease : undefined, + consent: typeof consent === 'boolean' ? consent : undefined, + skipSettings: + typeof argv['skip-settings'] === 'boolean' + ? argv['skip-settings'] + : undefined, }); await exitCli(); }, diff --git a/packages/cli/src/commands/extensions/link.ts b/packages/cli/src/commands/extensions/link.ts index 0f419c5cad..410acf8bb2 100644 --- a/packages/cli/src/commands/extensions/link.ts +++ b/packages/cli/src/commands/extensions/link.ts @@ -78,11 +78,11 @@ export const linkCommand: CommandModule = { }) .check((_) => true), handler: async (argv) => { + const path = argv['path']; + const consent = argv['consent']; await handleLink({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - path: argv['path'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - consent: argv['consent'] as boolean | undefined, + path: typeof path === 'string' ? path : '', + consent: typeof consent === 'boolean' ? consent : undefined, }); await exitCli(); }, diff --git a/packages/cli/src/commands/extensions/list.ts b/packages/cli/src/commands/extensions/list.ts index e477ce3c21..df4b9c2d57 100644 --- a/packages/cli/src/commands/extensions/list.ts +++ b/packages/cli/src/commands/extensions/list.ts @@ -60,9 +60,12 @@ export const listCommand: CommandModule = { default: 'text', }), handler: async (argv) => { + const outputFormat = argv['output-format']; await handleList({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - outputFormat: argv['output-format'] as 'text' | 'json', + outputFormat: + outputFormat === 'text' || outputFormat === 'json' + ? outputFormat + : undefined, }); await exitCli(); }, diff --git a/packages/cli/src/commands/extensions/new.ts b/packages/cli/src/commands/extensions/new.ts index 2ff97834c3..4adf554cad 100644 --- a/packages/cli/src/commands/extensions/new.ts +++ b/packages/cli/src/commands/extensions/new.ts @@ -97,11 +97,11 @@ export const newCommand: CommandModule = { }); }, handler: async (args) => { + const path = args['path']; + const template = args['template']; await handleNew({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - path: args['path'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - template: args['template'] as string | undefined, + path: typeof path === 'string' ? path : '', + template: typeof template === 'string' ? template : undefined, }); await exitCli(); }, diff --git a/packages/cli/src/commands/extensions/uninstall.ts b/packages/cli/src/commands/extensions/uninstall.ts index 3a63602149..5ddcf50dfe 100644 --- a/packages/cli/src/commands/extensions/uninstall.ts +++ b/packages/cli/src/commands/extensions/uninstall.ts @@ -91,11 +91,14 @@ export const uninstallCommand: CommandModule = { return true; }), handler: async (argv) => { + const names = argv['names']; + let namesArray: string[] = []; + if (Array.isArray(names)) { + namesArray = names.filter((n): n is string => typeof n === 'string'); + } await handleUninstall({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - names: argv['names'] as string[] | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - all: argv['all'] as boolean, + names: namesArray, + all: typeof argv['all'] === 'boolean' ? argv['all'] : false, }); await exitCli(); }, diff --git a/packages/cli/src/commands/extensions/update.ts b/packages/cli/src/commands/extensions/update.ts index 2459b5d7c4..56131fc100 100644 --- a/packages/cli/src/commands/extensions/update.ts +++ b/packages/cli/src/commands/extensions/update.ts @@ -157,11 +157,11 @@ export const updateCommand: CommandModule = { return true; }), handler: async (argv) => { + const name = argv['name']; + const all = argv['all']; await handleUpdate({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - name: argv['name'] as string | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - all: argv['all'] as boolean | undefined, + name: typeof name === 'string' ? name : undefined, + all: typeof all === 'boolean' ? all : undefined, }); await exitCli(); }, diff --git a/packages/cli/src/commands/extensions/validate.ts b/packages/cli/src/commands/extensions/validate.ts index e122b279dc..674c227127 100644 --- a/packages/cli/src/commands/extensions/validate.ts +++ b/packages/cli/src/commands/extensions/validate.ts @@ -98,9 +98,9 @@ export const validateCommand: CommandModule = { demandOption: true, }), handler: async (args) => { + const path = args['path']; await handleValidate({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - path: args['path'] as string, + path: typeof path === 'string' ? path : '', }); await exitCli(); }, diff --git a/packages/cli/src/commands/hooks/migrate.ts b/packages/cli/src/commands/hooks/migrate.ts index 36bb2cf9aa..620cc8da42 100644 --- a/packages/cli/src/commands/hooks/migrate.ts +++ b/packages/cli/src/commands/hooks/migrate.ts @@ -12,10 +12,6 @@ import { loadSettings, SettingScope } from '../../config/settings.js'; import { exitCli } from '../utils.js'; import stripJsonComments from 'strip-json-comments'; -interface MigrateArgs { - fromClaude: boolean; -} - /** * Mapping from Claude Code event names to Gemini event names */ @@ -62,16 +58,19 @@ function transformMatcher(matcher: string | undefined): string | undefined { return transformed; } +function isRecord(obj: unknown): obj is Record { + return typeof obj === 'object' && obj !== null && !Array.isArray(obj); +} + /** * Migrate a Claude Code hook configuration to Gemini format */ function migrateClaudeHook(claudeHook: unknown): unknown { - if (!claudeHook || typeof claudeHook !== 'object') { + if (!isRecord(claudeHook)) { return claudeHook; } - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - const hook = claudeHook as Record; + const hook = claudeHook; const migrated: Record = {}; // Map command field @@ -106,18 +105,15 @@ function migrateClaudeHook(claudeHook: unknown): unknown { * Migrate Claude Code hooks configuration to Gemini format */ function migrateClaudeHooks(claudeConfig: unknown): Record { - if (!claudeConfig || typeof claudeConfig !== 'object') { + if (!isRecord(claudeConfig)) { return {}; } - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - const config = claudeConfig as Record; const geminiHooks: Record = {}; // Check if there's a hooks section - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - const hooksSection = config['hooks'] as Record | undefined; - if (!hooksSection || typeof hooksSection !== 'object') { + const hooksSection = claudeConfig['hooks']; + if (!isRecord(hooksSection)) { return {}; } @@ -131,31 +127,25 @@ function migrateClaudeHooks(claudeConfig: unknown): Record { // Migrate each hook definition const migratedDefinitions = eventConfig.map((def: unknown) => { - if (!def || typeof def !== 'object') { + if (!isRecord(def)) { return def; } - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - const definition = def as Record; const migratedDef: Record = {}; // Transform matcher - if ( - 'matcher' in definition && - // eslint-disable-next-line no-restricted-syntax - typeof definition['matcher'] === 'string' - ) { - migratedDef['matcher'] = transformMatcher(definition['matcher']); + if ('matcher' in def && typeof def['matcher'] === 'string') { + migratedDef['matcher'] = transformMatcher(def['matcher']); } // Copy sequential flag - if ('sequential' in definition) { - migratedDef['sequential'] = definition['sequential']; + if ('sequential' in def) { + migratedDef['sequential'] = def['sequential']; } // Migrate hooks array - if ('hooks' in definition && Array.isArray(definition['hooks'])) { - migratedDef['hooks'] = definition['hooks'].map(migrateClaudeHook); + if ('hooks' in def && Array.isArray(def['hooks'])) { + migratedDef['hooks'] = def['hooks'].map(migrateClaudeHook); } return migratedDef; @@ -186,11 +176,11 @@ export async function handleMigrateFromClaude() { sourceFile = claudeLocalSettingsPath; try { const content = fs.readFileSync(claudeLocalSettingsPath, 'utf-8'); - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - claudeSettings = JSON.parse(stripJsonComments(content)) as Record< - string, - unknown - >; + const parsed = JSON.parse(stripJsonComments(content)); + if (isRecord(parsed)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion + claudeSettings = parsed as any; + } } catch (error) { debugLogger.error( `Error reading ${claudeLocalSettingsPath}: ${getErrorMessage(error)}`, @@ -200,11 +190,11 @@ export async function handleMigrateFromClaude() { sourceFile = claudeSettingsPath; try { const content = fs.readFileSync(claudeSettingsPath, 'utf-8'); - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - claudeSettings = JSON.parse(stripJsonComments(content)) as Record< - string, - unknown - >; + const parsed = JSON.parse(stripJsonComments(content)); + if (isRecord(parsed)) { + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment, @typescript-eslint/no-explicit-any, @typescript-eslint/no-unsafe-type-assertion + claudeSettings = parsed as any; + } } catch (error) { debugLogger.error( `Error reading ${claudeSettingsPath}: ${getErrorMessage(error)}`, @@ -268,9 +258,8 @@ export const migrateCommand: CommandModule = { default: false, }), handler: async (argv) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - const args = argv as unknown as MigrateArgs; - if (args.fromClaude) { + const fromClaude = argv['from-claude']; + if (typeof fromClaude === 'boolean' && fromClaude) { await handleMigrateFromClaude(); } else { debugLogger.log( diff --git a/packages/cli/src/commands/mcp/add.ts b/packages/cli/src/commands/mcp/add.ts index 98e6a70879..89ae6668d7 100644 --- a/packages/cli/src/commands/mcp/add.ts +++ b/packages/cli/src/commands/mcp/add.ts @@ -211,40 +211,56 @@ export const addCommand: CommandModule = { }) .middleware((argv) => { // Handle -- separator args as server args if present - if (argv['--']) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - const existingArgs = (argv['args'] as Array) || []; - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - argv['args'] = [...existingArgs, ...(argv['--'] as string[])]; + if (argv['--'] && Array.isArray(argv['--'])) { + const args = argv['args']; + const existingArgs = Array.isArray(args) ? args : []; + // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment + argv['args'] = [...existingArgs, ...argv['--']]; } }), handler: async (argv) => { + const name = argv['name']; + const commandOrUrl = argv['commandOrUrl']; + const args = argv['args']; + const scope = argv['scope']; + const transport = argv['transport']; + const env = argv['env']; + const header = argv['header']; + const timeout = argv['timeout']; + const trust = argv['trust']; + const description = argv['description']; + const includeTools = argv['includeTools']; + const excludeTools = argv['excludeTools']; + + const argsVal = Array.isArray(args) + ? args.filter( + (a): a is string | number => + typeof a === 'string' || typeof a === 'number', + ) + : undefined; + await addMcpServer( - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - argv['name'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - argv['commandOrUrl'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - argv['args'] as Array, + typeof name === 'string' ? name : '', + typeof commandOrUrl === 'string' ? commandOrUrl : '', + argsVal, { - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - scope: argv['scope'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - transport: argv['transport'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - env: argv['env'] as string[], - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - header: argv['header'] as string[], - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - timeout: argv['timeout'] as number | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - trust: argv['trust'] as boolean | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - description: argv['description'] as string | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - includeTools: argv['includeTools'] as string[] | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - excludeTools: argv['excludeTools'] as string[] | undefined, + scope: typeof scope === 'string' ? scope : 'project', + transport: typeof transport === 'string' ? transport : 'stdio', + env: Array.isArray(env) + ? env.filter((e): e is string => typeof e === 'string') + : undefined, + header: Array.isArray(header) + ? header.filter((h): h is string => typeof h === 'string') + : undefined, + timeout: typeof timeout === 'number' ? timeout : undefined, + trust: typeof trust === 'boolean' ? trust : undefined, + description: typeof description === 'string' ? description : undefined, + includeTools: Array.isArray(includeTools) + ? includeTools.filter((t): t is string => typeof t === 'string') + : undefined, + excludeTools: Array.isArray(excludeTools) + ? excludeTools.filter((t): t is string => typeof t === 'string') + : undefined, }, ); await exitCli(); diff --git a/packages/cli/src/commands/mcp/enableDisable.ts b/packages/cli/src/commands/mcp/enableDisable.ts index b47e259eca..1af329fb6d 100644 --- a/packages/cli/src/commands/mcp/enableDisable.ts +++ b/packages/cli/src/commands/mcp/enableDisable.ts @@ -112,7 +112,12 @@ export const enableCommand: CommandModule = { default: false, }), handler: async (argv) => { - await handleEnable(argv as Args); + const name = argv['name']; + const session = argv['session']; + await handleEnable({ + name: typeof name === 'string' ? name : '', + session: typeof session === 'boolean' ? session : undefined, + }); await exitCli(); }, }; @@ -133,7 +138,12 @@ export const disableCommand: CommandModule = { default: false, }), handler: async (argv) => { - await handleDisable(argv as Args); + const name = argv['name']; + const session = argv['session']; + await handleDisable({ + name: typeof name === 'string' ? name : '', + session: typeof session === 'boolean' ? session : undefined, + }); await exitCli(); }, }; diff --git a/packages/cli/src/commands/mcp/remove.ts b/packages/cli/src/commands/mcp/remove.ts index 8c5bd1efab..fa9c5ecfab 100644 --- a/packages/cli/src/commands/mcp/remove.ts +++ b/packages/cli/src/commands/mcp/remove.ts @@ -55,10 +55,10 @@ export const removeCommand: CommandModule = { choices: ['user', 'project'], }), handler: async (argv) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - await removeMcpServer(argv['name'] as string, { - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - scope: argv['scope'] as string, + const name = argv['name']; + const scope = argv['scope']; + await removeMcpServer(typeof name === 'string' ? name : '', { + scope: typeof scope === 'string' ? scope : 'project', }); await exitCli(); }, diff --git a/packages/cli/src/commands/skills/disable.ts b/packages/cli/src/commands/skills/disable.ts index 59a74fd3c5..411c261b4e 100644 --- a/packages/cli/src/commands/skills/disable.ts +++ b/packages/cli/src/commands/skills/disable.ts @@ -48,13 +48,13 @@ export const disableCommand: CommandModule = { choices: ['user', 'workspace'], }), handler: async (argv) => { + const name = argv['name']; const scope = argv['scope'] === 'workspace' ? SettingScope.Workspace : SettingScope.User; await handleDisable({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - name: argv['name'] as string, + name: typeof name === 'string' ? name : '', scope, }); await exitCli(); diff --git a/packages/cli/src/commands/skills/enable.ts b/packages/cli/src/commands/skills/enable.ts index 6f58cf471e..8f94c58a21 100644 --- a/packages/cli/src/commands/skills/enable.ts +++ b/packages/cli/src/commands/skills/enable.ts @@ -39,9 +39,9 @@ export const enableCommand: CommandModule = { demandOption: true, }), handler: async (argv) => { + const name = argv['name']; await handleEnable({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - name: argv['name'] as string, + name: typeof name === 'string' ? name : '', }); await exitCli(); }, diff --git a/packages/cli/src/commands/skills/install.ts b/packages/cli/src/commands/skills/install.ts index 75dad58f0f..72028943d1 100644 --- a/packages/cli/src/commands/skills/install.ts +++ b/packages/cli/src/commands/skills/install.ts @@ -104,15 +104,16 @@ export const installCommand: CommandModule = { return true; }), handler: async (argv) => { + const source = argv['source']; + const scope = argv['scope']; + const path = argv['path']; + const consent = argv['consent']; + await handleInstall({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - source: argv['source'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - scope: argv['scope'] as 'user' | 'workspace', - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - path: argv['path'] as string | undefined, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - consent: argv['consent'] as boolean | undefined, + source: typeof source === 'string' ? source : '', + scope: scope === 'user' || scope === 'workspace' ? scope : undefined, + path: typeof path === 'string' ? path : undefined, + consent: typeof consent === 'boolean' ? consent : undefined, }); await exitCli(); }, diff --git a/packages/cli/src/commands/skills/link.ts b/packages/cli/src/commands/skills/link.ts index 3a03b93e6b..d5927f552f 100644 --- a/packages/cli/src/commands/skills/link.ts +++ b/packages/cli/src/commands/skills/link.ts @@ -82,13 +82,14 @@ export const linkCommand: CommandModule = { return true; }), handler: async (argv) => { + const path = argv['path']; + const scope = argv['scope']; + const consent = argv['consent']; + await handleLink({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - path: argv['path'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - scope: argv['scope'] as 'user' | 'workspace', - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - consent: argv['consent'] as boolean | undefined, + path: typeof path === 'string' ? path : '', + scope: scope === 'user' || scope === 'workspace' ? scope : undefined, + consent: typeof consent === 'boolean' ? consent : undefined, }); await exitCli(); }, diff --git a/packages/cli/src/commands/skills/list.ts b/packages/cli/src/commands/skills/list.ts index bc05c6c2af..685f5de5d0 100644 --- a/packages/cli/src/commands/skills/list.ts +++ b/packages/cli/src/commands/skills/list.ts @@ -20,7 +20,7 @@ export async function handleList(args: { all?: boolean }) { // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion { debug: false, - } as Partial as CliArgs, + } as unknown as CliArgs, { cwd: workspaceDir }, ); @@ -72,8 +72,8 @@ export const listCommand: CommandModule = { default: false, }), handler: async (argv) => { - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - await handleList({ all: argv['all'] as boolean }); + const all = argv['all']; + await handleList({ all: typeof all === 'boolean' ? all : false }); await exitCli(); }, }; diff --git a/packages/cli/src/commands/skills/uninstall.ts b/packages/cli/src/commands/skills/uninstall.ts index cfcb67da21..6dbfe3f945 100644 --- a/packages/cli/src/commands/skills/uninstall.ts +++ b/packages/cli/src/commands/skills/uninstall.ts @@ -62,11 +62,12 @@ export const uninstallCommand: CommandModule = { return true; }), handler: async (argv) => { + const name = argv['name']; + const scope = argv['scope']; + await handleUninstall({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - name: argv['name'] as string, - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - scope: argv['scope'] as 'user' | 'workspace', + name: typeof name === 'string' ? name : '', + scope: scope === 'user' || scope === 'workspace' ? scope : undefined, }); await exitCli(); }, diff --git a/packages/cli/src/ui/hooks/slashCommandProcessor.ts b/packages/cli/src/ui/hooks/slashCommandProcessor.ts index f55503ad25..3a1f0b4616 100644 --- a/packages/cli/src/ui/hooks/slashCommandProcessor.ts +++ b/packages/cli/src/ui/hooks/slashCommandProcessor.ts @@ -64,6 +64,10 @@ import { } from '../components/LogoutConfirmationDialog.js'; import { runExitCleanup } from '../../utils/cleanup.js'; +function isRecord(obj: unknown): obj is Record { + return typeof obj === 'object' && obj !== null && !Array.isArray(obj); +} + interface SlashCommandProcessorActions { openAuthDialog: () => void; openThemeDialog: () => void; @@ -501,17 +505,14 @@ export const useSlashCommandProcessor = ( actions.openModelDialog(); return { type: 'handled' }; case 'agentConfig': { - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - const props = result.props as Record; + const props = result.props; if ( - !props || - // eslint-disable-next-line no-restricted-syntax + !isRecord(props) || typeof props['name'] !== 'string' || // eslint-disable-next-line no-restricted-syntax typeof props['displayName'] !== 'string' || !props['definition'] - ) { - throw new Error( + ) { throw new Error( 'Received invalid properties for agentConfig dialog action.', ); } @@ -524,12 +525,15 @@ export const useSlashCommandProcessor = ( ); return { type: 'handled' }; } - case 'permissions': + case 'permissions': { + const props = result.props; actions.openPermissionsDialog( - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - result.props as { targetDirectory?: string }, + isRecord(props) + ? (props as { targetDirectory?: string }) + : undefined, ); return { type: 'handled' }; + } case 'help': return { type: 'handled' }; default: { diff --git a/packages/cli/src/ui/hooks/useGeminiStream.ts b/packages/cli/src/ui/hooks/useGeminiStream.ts index eee0241a58..ad46cea682 100644 --- a/packages/cli/src/ui/hooks/useGeminiStream.ts +++ b/packages/cli/src/ui/hooks/useGeminiStream.ts @@ -92,7 +92,6 @@ import { type TrackedCompletedToolCall, type TrackedCancelledToolCall, type TrackedWaitingToolCall, - type TrackedExecutingToolCall, } from './useToolScheduler.js'; import { theme } from '../semantic-colors.js'; import { getToolGroupBorderAppearance } from '../utils/borderStyles.js'; @@ -102,6 +101,10 @@ import { useSessionStats } from '../contexts/SessionContext.js'; import { useKeypress } from './useKeypress.js'; import type { LoadedSettings } from '../../config/settings.js'; +function isRecord(obj: unknown): obj is Record { + return typeof obj === 'object' && obj !== null && !Array.isArray(obj); +} + type ToolResponseWithParts = ToolCallResponseInfo & { llmContent?: PartListUnion; }; @@ -842,9 +845,11 @@ export const useGeminiStream = ( // If it is a shell command, we update the status to Canceled and clear the output // to avoid artifacts, then add it to history immediately. - if (isShellCommand) { - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - const toolGroup = pendingHistoryItemRef.current as HistoryItemToolGroup; + if ( + isShellCommand && + pendingHistoryItemRef.current.type === 'tool_group' + ) { + const toolGroup = pendingHistoryItemRef.current; const updatedTools = toolGroup.tools.map((tool) => { if (tool.name === SHELL_COMMAND_NAME) { return { @@ -855,7 +860,7 @@ export const useGeminiStream = ( } return tool; }); - addItem({ ...toolGroup, tools: updatedTools } as HistoryItemWithoutId); + addItem({ ...toolGroup, tools: updatedTools }); } else { addItem(pendingHistoryItemRef.current); } @@ -1069,11 +1074,15 @@ export const useGeminiStream = ( const splitPoint = findLastSafeSplitPoint(newGeminiMessageBuffer); if (splitPoint === newGeminiMessageBuffer.length) { // Update the existing message with accumulated content - setPendingHistoryItem((item) => ({ - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - type: item?.type as 'gemini' | 'gemini_content', - text: newGeminiMessageBuffer, - })); + setPendingHistoryItem((item) => { + if (item?.type === 'gemini' || item?.type === 'gemini_content') { + return { + type: item.type, + text: newGeminiMessageBuffer, + }; + } + return item; + }); } else { // This indicates that we need to split up this Gemini Message. // Splitting a message is primarily a performance consideration. There is a @@ -1086,16 +1095,16 @@ export const useGeminiStream = ( const beforeText = newGeminiMessageBuffer.substring(0, splitPoint); const afterText = newGeminiMessageBuffer.substring(splitPoint); if (beforeText.length > 0) { - addItem( - { - // eslint-disable-next-line @typescript-eslint/no-unsafe-type-assertion - type: pendingHistoryItemRef.current?.type as - | 'gemini' - | 'gemini_content', - text: beforeText, - }, - userMessageTimestamp, - ); + const type = pendingHistoryItemRef.current?.type; + if (type === 'gemini' || type === 'gemini_content') { + addItem( + { + type, + text: beforeText, + }, + userMessageTimestamp, + ); + } } setPendingHistoryItem({ type: 'gemini_content', text: afterText }); newGeminiMessageBuffer = afterText;