Skip to content

fix: stop web-search TUI early exit when no gateway#1575

Open
nborges-aws wants to merge 1 commit into
mainfrom
fix/web-search-TUI-early-exit
Open

fix: stop web-search TUI early exit when no gateway#1575
nborges-aws wants to merge 1 commit into
mainfrom
fix/web-search-TUI-early-exit

Conversation

@nborges-aws

Copy link
Copy Markdown
Contributor

Description

Fix for issue causing the web-search interactive flow to kill the TUI process early if no gateway is present. Tested via installing tarball, process now stays alive and NoGatewayMessage renders as expected.

image

Related Issue

Closes #

Documentation PR

Type of Change

  • Bug fix
  • New feature
  • Breaking change
  • Documentation update
  • Other (please describe):

Testing

How have you tested the change?

  • I ran npm run test:unit and npm run test:integ
  • I ran npm run typecheck
  • I ran npm run lint
  • If I modified src/assets/, I ran npm run test:update-snapshots and committed the updated snapshots

Checklist

  • I have read the CONTRIBUTING document
  • I have added any necessary tests that prove my fix is effective or my feature works
  • I have updated the documentation accordingly
  • I have added an appropriate example to the documentation to outline the feature, or no new docs are needed
  • My changes generate no new warnings
  • Any dependent changes have been merged and published

By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.

@nborges-aws nborges-aws requested a review from a team June 18, 2026 01:31
@github-actions github-actions Bot added the size/xs PR size: XS label Jun 18, 2026
@github-actions github-actions Bot added the agentcore-harness-reviewing AgentCore Harness review in progress label Jun 18, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 18, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Jun 18, 2026
@github-actions

Copy link
Copy Markdown
Contributor

Package Tarball

aws-agentcore-0.20.1.tgz

How to install

gh release download pr-1575-tarball --repo aws/agentcore-cli --pattern "*.tgz" --dir /tmp/pr-tarball
npm install -g /tmp/pr-tarball/aws-agentcore-0.20.1.tgz

@agentcore-cli-automation agentcore-cli-automation left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the fix! However, I think removing exitEnabled entirely (defaulting it to true) introduces a regression on the other steps. See the inline comment for details.

headerContent={headerContent}
exitEnabled={isNameStep}
>
<Screen title="Add Web Search" onExit={onExit} helpText={helpText} headerContent={headerContent}>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With exitEnabled removed here, it now defaults to true, so the Screen-level useExitHandler is active on every step. Combined with the sub-component handlers below, this causes Escape to fire two handlers on later steps:

  • gateway step (when gateways exist): gatewayNav has onExit: () => setStep('name') and is active. Escape now fires both setStep('name') AND onExit (the prop) → wizard exits to the parent instead of going back to the name step.
  • exclude-domains step: TextInput's onCancel={() => setStep('gateway')} fires AND Screen-level onExit fires → wizard exits instead of going back to gateway.
  • confirm step: the second useListNavigation has onExit: () => setStep('exclude-domains') and is active. Escape fires both → wizard exits instead of going back to exclude-domains.

Note that Ink's useInput invokes all active handlers (it doesn't have DOM-style propagation/stopPropagation), which is why both fire. This is also why the established pattern in sibling screens (AddMemoryScreen, AddDatasetScreen, AddKnowledgeBaseScreen, AddHarnessScreen, AddRuntimeEndpointScreen) is exitEnabled={isNameStep} — to disable the Screen-level handler on steps where sub-components handle their own back navigation.

This is especially bad in the standalone agentcore add web-search entry point (GatewayTargetPrimitive.ts:943-947), where onBack calls process.exit(0). So Escape on the gateway-with-gateways / exclude-domains / confirm steps will now kill the CLI process — the same class of bug this PR set out to fix.

A couple of options to address both the original bug and avoid the regression:

Option 1 — Extend the existing condition to also cover the empty-gateways case:

exitEnabled={isNameStep || (isGatewayStep && noGatewaysAvailable)}

This keeps the established pattern and explicitly handles the no-gateways branch where neither gatewayNav nor the Screen would otherwise listen.

Option 2 — Keep exitEnabled={isNameStep} and let NoGatewaysMessage handle Escape itself, e.g. by accepting an onBack prop and using useExitHandler(onBack) (or a local useInput) inside the component. This keeps the NoGatewaysMessage self-contained and consistent with how other sub-components handle their own back navigation.

Either way, please add a test that covers the regression cases (Escape on gateway-with-gateways/exclude-domains/confirm should setStep back one step, not call onExit) and the no-gateways case (Escape should call onExit). The PR currently has no test coverage for this file.

@github-actions github-actions Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Jun 18, 2026
@github-actions

github-actions Bot commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Coverage Report

Status Category Percentage Covered / Total
🔵 Lines 36.86% 13468 / 36533
🔵 Statements 36.15% 14321 / 39608
🔵 Functions 31.39% 2299 / 7322
🔵 Branches 30.63% 8893 / 29032
Generated in workflow #3694 for commit d558049 by the Vitest Coverage Report Action

@nborges-aws nborges-aws force-pushed the fix/web-search-TUI-early-exit branch from c5da8e5 to d558049 Compare June 18, 2026 01:51
@github-actions github-actions Bot added size/m PR size: M and removed size/xs PR size: XS labels Jun 18, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Jun 18, 2026
@agentcore-devx-automation

Copy link
Copy Markdown
Contributor

Claude Security Review: no high-confidence findings. (run)

@agentcore-devx-automation agentcore-devx-automation Bot removed the claude-security-reviewing Claude Code /security-review in progress label Jun 18, 2026

@Hweinstock Hweinstock left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice fix, verified locally as well since I was initially confused how this fixed it.

helpText={helpText}
headerContent={headerContent}
exitEnabled={isNameStep}
exitEnabled={isNameStep || (isGatewayStep && noGatewaysAvailable)}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pasting my own understanding of why this fixes it, since I don't think its obvious.

So before, exitEnabled was false on that page, meaning this hook was disabled. Therefore, when there were no gateways, that screen in the wizard wasn't listening for any user inputs so nothing was keeping the node event loop alive.

Relevant docs:

An Ink app is a Node.js process, so it stays alive only while there is active work in the event loop (timers, pending promises, useInput listening on stdin, etc.). If your component tree has no async work, the app will render once and exit immediately.
https://github.com/vadimdemedes/ink/blob/master/readme.md#app-lifecycle

As a long term fix (OOS here), I feel like we need to build a common Wizard abstraction that handles this once for us. Exposing exitEnabled directly here will always carry the risk that someone disables exits, and forgets to wire up another hook in its place, causing the process to exit early.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size/m PR size: M

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants