fix: stop web-search TUI early exit when no gateway#1575
Conversation
|
Claude Security Review: no high-confidence findings. (run) |
Package TarballHow to installgh 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
left a comment
There was a problem hiding this comment.
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}> |
There was a problem hiding this comment.
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:
gatewaystep (when gateways exist):gatewayNavhasonExit: () => setStep('name')and is active. Escape now fires bothsetStep('name')ANDonExit(the prop) → wizard exits to the parent instead of going back to the name step.exclude-domainsstep:TextInput'sonCancel={() => setStep('gateway')}fires AND Screen-levelonExitfires → wizard exits instead of going back to gateway.confirmstep: the seconduseListNavigationhasonExit: () => 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.
Coverage Report
|
c5da8e5 to
d558049
Compare
|
Claude Security Review: no high-confidence findings. (run) |
Hweinstock
left a comment
There was a problem hiding this comment.
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)} |
There was a problem hiding this comment.
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.
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
NoGatewayMessagerenders as expected.Related Issue
Closes #
Documentation PR
Type of Change
Testing
How have you tested the change?
npm run test:unitandnpm run test:integnpm run typechecknpm run lintsrc/assets/, I rannpm run test:update-snapshotsand committed the updated snapshotsChecklist
By submitting this pull request, I confirm that you can use, modify, copy, and redistribute this contribution, under the
terms of your choice.