Skip to content
Merged
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
31 changes: 24 additions & 7 deletions src/cli/primitives/GatewayTargetPrimitive.ts
Original file line number Diff line number Diff line change
Expand Up @@ -283,9 +283,12 @@ export class GatewayTargetPrimitive extends BasePrimitive<AddGatewayTargetOption
}

registerCommands(addCmd: Command, removeCmd: Command): void {
// Hide gated options from `--help` unless ENABLE_GATED_FEATURES is set.
const gate = <T extends Option>(option: T): T => (isGatedFeaturesEnabled() ? option : option.hideHelp());

const typeDescription = isGatedFeaturesEnabled()
? 'Target type (required): mcp-server, api-gateway, open-api-schema, smithy-model, lambda-function-arn, http-runtime, connector, passthrough, web-search [non-interactive]'
: 'Target type (required): mcp-server, api-gateway, open-api-schema, smithy-model, lambda-function-arn, http-runtime, connector, web-search [non-interactive]';
: 'Target type (required): mcp-server, api-gateway, open-api-schema, smithy-model, lambda-function-arn, http-runtime, connector [non-interactive]';

// Reject repeated use of --exclude-domains. Domains must be passed as a
// single comma-separated value.
Expand Down Expand Up @@ -315,10 +318,13 @@ export class GatewayTargetPrimitive extends BasePrimitive<AddGatewayTargetOption
(val: string, acc: string[]) => [...acc, val],
[] as string[]
)
.option(
'--exclude-domains <list>',
'Comma-separated domains to exclude from results (for --type web-search only) [non-interactive]',
excludeDomainsCoercer
.addOption(
gate(
new Option(
'--exclude-domains <list>',
'Comma-separated domains to exclude from results (for --type web-search only) [non-interactive]'
).argParser(excludeDomainsCoercer)
)
)
.option('--endpoint <endpoint>', 'Server endpoint URL (for mcp-server type) [non-interactive]')
.option('--language <lang>', 'Language of target code: Python, TypeScript, Other [non-interactive]')
Expand Down Expand Up @@ -613,6 +619,9 @@ ${

// Handle Amazon Web Search targets (managed-service backed via gateway IAM role)
if (cliOptions.type === 'webSearch') {
if (!isGatedFeaturesEnabled()) {
throw new ValidationError('Web search target type is not yet available.');
}
const excludeDomains =
typeof cliOptions.excludeDomains === 'string'
? cliOptions.excludeDomains
Expand Down Expand Up @@ -902,13 +911,17 @@ ${
// Top-level shortcuts: agentcore add web-search / remove web-search
// ──────────────────────────────────────────────────────────────────
addCmd
.command('web-search')
.command('web-search', { hidden: !isGatedFeaturesEnabled() })
.description('Wire the Amazon Web Search managed connector to a gateway as a target.')
.option('--name <name>', 'Target name (default: web-search) [non-interactive]')
.option('--gateway <name>', 'Gateway to attach this target to [non-interactive]')
.option('--exclude-domains <list>', 'Comma-separated domains to exclude from results [non-interactive]')
.option('--json', 'Output as JSON [non-interactive]')
.action(async (cliOptions: { name?: string; gateway?: string; excludeDomains?: string; json?: boolean }) => {
if (!isGatedFeaturesEnabled()) {
console.error('Error: Web search target type is not yet available.');
process.exit(1);
}
if (!findConfigRoot()) {
console.error('No agentcore project found. Run `agentcore create` first.');
process.exit(1);
Expand Down Expand Up @@ -996,13 +1009,17 @@ ${
});

removeCmd
.command('web-search')
.command('web-search', { hidden: !isGatedFeaturesEnabled() })
.description('Remove an Amazon Web Search gateway target from the project')
.option('--name <name>', 'Name of the web-search target to remove [non-interactive]')
.option('-y, --yes', 'Skip confirmation prompt [non-interactive]')
.option('--json', 'Output as JSON [non-interactive]')
.action(async (cliOptions: { name?: string; yes?: boolean; json?: boolean }) => {
try {
if (!isGatedFeaturesEnabled()) {
console.error('Web search target type is not yet available.');
process.exit(1);
}
if (!findConfigRoot()) {
console.error('No agentcore project found. Run `agentcore create` first.');
process.exit(1);
Expand Down
2 changes: 1 addition & 1 deletion src/cli/tui/screens/add/AddScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ const ADD_RESOURCES: { id: AddResourceType; title: string; description: string }
];

const ADD_RESOURCE_ITEMS: SelectableItem[] = ADD_RESOURCES.map(r => {
const gated = r.id === 'knowledge-base' && !isGatedFeaturesEnabled();
const gated = (r.id === 'knowledge-base' || r.id === 'web-search') && !isGatedFeaturesEnabled();
return {
...r,
disabled: gated,
Expand Down
11 changes: 11 additions & 0 deletions src/cli/tui/screens/add/__tests__/AddScreen.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,15 @@ describe('AddScreen', () => {
expect(lastFrame()).toContain('Payment Manager');
expect(lastFrame()).toContain('Payment Connector');
});

it('Web Search option shows Coming soon when ENABLE_GATED_FEATURES is unset', () => {
delete process.env.ENABLE_GATED_FEATURES;
const onSelect = vi.fn();
const onExit = vi.fn();

const { lastFrame } = render(<AddScreen onSelect={onSelect} onExit={onExit} />);

expect(lastFrame()).toContain('Web Search');
expect(lastFrame()).toContain('Coming soon');
});
});
2 changes: 1 addition & 1 deletion src/cli/tui/screens/mcp/AddGatewayTargetScreen.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ export function AddGatewayTargetScreen({
const targetTypeItems: SelectableItem[] = useMemo(
() =>
TARGET_TYPE_OPTIONS.map(o => {
const gated = o.id === 'passthrough' && !isGatedFeaturesEnabled();
const gated = (o.id === 'passthrough' || o.id === 'webSearch') && !isGatedFeaturesEnabled();
return {
id: o.id,
title: o.title,
Expand Down
Loading