Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions src/cli/commands/config/__tests__/config.test.ts
Original file line number Diff line number Diff line change
@@ -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);
}
}
});
});
7 changes: 6 additions & 1 deletion src/cli/commands/config/actions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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';

Expand Down Expand Up @@ -34,7 +35,11 @@ export async function handleConfigSet(key: string, raw: string): Promise<ConfigR
const validation = validateGlobalConfig(partial);

if (!validation.success) {
return { success: false, error: new ValidationError(`Invalid value "${raw}" for key "${key}".`) };
const validKeys = CONFIG_KEYS.map(k => k.key).join(', ');
return {
success: false,
error: new ValidationError(`Invalid value "${raw}" for key "${key}". Valid keys: ${validKeys}.`),
};
}

const ok = await updateGlobalConfig(partial);
Expand Down
15 changes: 14 additions & 1 deletion src/cli/commands/config/command.ts
Original file line number Diff line number Diff line change
@@ -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';

Expand All @@ -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)')
Expand All @@ -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`
);
}
20 changes: 20 additions & 0 deletions src/cli/commands/config/constants.ts
Original file line number Diff line number Diff line change
@@ -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');
}
Loading