diff --git a/src/cli/commands/config/__tests__/config.test.ts b/src/cli/commands/config/__tests__/config.test.ts new file mode 100644 index 000000000..bc0f3c3fb --- /dev/null +++ b/src/cli/commands/config/__tests__/config.test.ts @@ -0,0 +1,29 @@ +import { handleConfigSet } from '../actions'; +import { registerConfig } from '../command'; +import { CONFIG_KEYS } from '../constants'; +import { Command } from '@commander-js/extra-typings'; +import { describe, expect, it } from 'vitest'; + +describe('config command discoverability', () => { + it('enumerates every valid config key in --help output', () => { + const program = new Command(); + registerConfig(program); + const config = program.commands.find(c => c.name() === 'config')!; + let help = ''; + config.configureOutput({ writeOut: s => (help += s) }); + config.outputHelp(); + for (const { key } of CONFIG_KEYS) { + expect(help).toContain(key); + } + }); + + it('lists valid keys in the invalid-set error', async () => { + const result = await handleConfigSet('notARealKey', 'x'); + expect(result.success).toBe(false); + if (!result.success) { + for (const { key } of CONFIG_KEYS) { + expect(result.error.message).toContain(key); + } + } + }); +}); diff --git a/src/cli/commands/config/actions.ts b/src/cli/commands/config/actions.ts index d34f113fd..3ddcdbc6b 100644 --- a/src/cli/commands/config/actions.ts +++ b/src/cli/commands/config/actions.ts @@ -4,6 +4,7 @@ import { updateGlobalConfig, validateGlobalConfig, } from '../../../lib/schemas/io/global-config.js'; +import { CONFIG_KEYS } from './constants.js'; import type { ConfigResult } from './types.js'; import { ValidationError } from '@/lib/index.js'; @@ -34,7 +35,11 @@ export async function handleConfigSet(key: string, raw: string): Promise k.key).join(', '); + return { + success: false, + error: new ValidationError(`Invalid value "${raw}" for key "${key}". Valid keys: ${validKeys}.`), + }; } const ok = await updateGlobalConfig(partial); diff --git a/src/cli/commands/config/command.ts b/src/cli/commands/config/command.ts index 8120fd806..9a0a14e24 100644 --- a/src/cli/commands/config/command.ts +++ b/src/cli/commands/config/command.ts @@ -1,5 +1,6 @@ import { COMMAND_DESCRIPTIONS } from '../../constants.js'; import { handleConfigGet, handleConfigList, handleConfigSet } from './actions.js'; +import { formatConfigKeys } from './constants.js'; import type { ConfigResult } from './types.js'; import type { Command } from '@commander-js/extra-typings'; @@ -18,7 +19,7 @@ function printResult(result: ConfigResult): void { } export function registerConfig(program: Command) { - program + const config = program .command('config') .description(COMMAND_DESCRIPTIONS.config) .argument('[key]', 'Config key in dot notation (e.g. telemetry.enabled)') @@ -28,4 +29,16 @@ export function registerConfig(program: Command) { printResult(result); if (!result.success) process.exit(1); }); + + config.addHelpText( + 'after', + ` +Valid config keys: +${formatConfigKeys()} + +Examples: + List config: agentcore config + Get a value: agentcore config telemetry.enabled + Set a value: agentcore config telemetry.enabled true` + ); } diff --git a/src/cli/commands/config/constants.ts b/src/cli/commands/config/constants.ts new file mode 100644 index 000000000..a2e79cb5f --- /dev/null +++ b/src/cli/commands/config/constants.ts @@ -0,0 +1,20 @@ +/** + * Valid global-config keys in dot notation, mirroring the shape of + * GlobalConfigSchemaStrict in src/lib/schemas/io/global-config.ts. Hand-written + * so each key can carry a human-readable hint the schema alone cannot provide. + */ +export const CONFIG_KEYS: readonly { key: string; description: string }[] = [ + { key: 'installationId', description: 'Anonymous installation identifier (UUID)' }, + { key: 'uvDefaultIndex', description: 'Default package index URL passed to uv' }, + { key: 'uvIndex', description: 'Additional package index URL passed to uv' }, + { key: 'disableTransactionSearch', description: 'Disable transaction search (boolean)' }, + { key: 'transactionSearchIndexPercentage', description: 'Transaction search index percentage (integer 0-100)' }, + { key: 'telemetry.enabled', description: 'Enable anonymous usage analytics (boolean)' }, + { key: 'telemetry.endpoint', description: 'Telemetry collection endpoint URL' }, + { key: 'telemetry.audit', description: 'Log every telemetry event locally (boolean)' }, +] as const; + +export function formatConfigKeys(): string { + const width = Math.max(...CONFIG_KEYS.map(k => k.key.length)); + return CONFIG_KEYS.map(({ key, description }) => ` ${key.padEnd(width)} ${description}`).join('\n'); +}