Skip to content

fix(router): allow required flags in handlers - #2283

Open
Hweinstock wants to merge 7 commits into
aws:refactorfrom
Hweinstock:decouple-tui-validation
Open

fix(router): allow required flags in handlers#2283
Hweinstock wants to merge 7 commits into
aws:refactorfrom
Hweinstock:decouple-tui-validation

Conversation

@Hweinstock

@Hweinstock Hweinstock commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

Problem

Flags are not able to be marked as required in the flag schema because it broke the default handler behavior on the TUI.

Ex. if a flag was marked required, the default handler to open the TUI would never trigger, since commander rejected the input first.

Solution

  • Avoid marking flags as required at the commander level and instead rely on zod parsing for this enforcement.
  • move flag parsing to a middleware layer, such that we can redirect to TUI before flag validation.
  • use harness get as an example of required flags now working e2e.

Note: this does change the behavior of custom middleware such it is executed BEFORE flags/args are coerced and validated. Since flags/args are typed as any in middleware, this is unlikely to have a significant effect.

Testing/Verification

Migrated the get harness handler and tested a few cases:

$ agentcore harness get 
--> opens TUI
$ agentcore harness get --id <HARNESS_ID>
--> returns JSON
$ agentcore harness get --region us-west-2
--> opens TUI

Help page:

$ agentcore harness get --help                                                       
Usage: agentcore harness get [options]

get a harness

Options:
  --id <id>                      the ID of the harness (required)
  -h, --help                     display help for command

Global Options:
  --region <region>              AWS region
  --debug                        debug logging (default: false)
  --json                         JSON output (default: false)
  --endpoint-url <endpoint-url>  endpoint URL override

note that it now shows required.

Alternatives Considered

  • add a special case in the routing layer to skip parsing when empty flags/args => smaller change, but leads to lots of edge cases + requires router to know about application logic (tui opening).
  • move TUI into routing layer => couples the core framework to a business logic decision.
  • move validation middleware out of the routing layer => might be more explicit, but leads to commander specific logic outside of the routing layer, which breaks the current abstraction.

Future Work

  • we can migrate all the handlers to use required flags, not manual checks.
  • we can clean up the error message as a follow-up.

@github-actions github-actions Bot added the size/m PR size: M label Sep 11, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added agentcore-harness-reviewing AgentCore Harness review in progress claude-security-reviewing Claude Code /security-review in progress labels Sep 11, 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 Sep 11, 2026

@agentcore-devx-automation agentcore-devx-automation Bot 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.

AgentCore Harness Review

Verdict: Changes requested

The refactor is well-structured: moving parseFlags/parseArguments into an inner withValidation middleware, and letting handlers declare their own middlewares, cleanly solves the "required flag but bare invocation should open the TUI" problem and lets you delete the awkward *Dispatch wrappers in handlers/project/index.ts. A couple of user-facing regressions I think need attention before merging, though:

1. Missing-required-flag error message regressed

Because option.makeOptionMandatory(true) was removed from toOption (src/router/flags.tsx), a missing required flag no longer produces Commander's clean message; it falls through to validateFlag and surfaces Zod internals. The test update in src/handlers/runtime/logs/logs.test.tsx:110 captures the new message:

Invalid value for option '--id': Invalid input: expected string, received undefined

That's a worse UX than the previous required option '--id <id>' not specified, and every handler you later migrate to the "required schema" pattern (e.g. harness get in this PR) inherits it. Options:

  • In validateFlag (src/router/flags.tsx), special-case the undefined input for a non-optional schema and throw InputValidationError(\required option '--${flag.name}' not specified`)before callingsafeParse`.
  • Or teach formatZodError to translate the received undefined issue into a friendlier "required option not specified" phrasing.

Either way, worth doing here rather than leaving the regression in tree.

2. --help no longer marks required options

Same root cause: without makeOptionMandatory, Commander no longer appends (required) next to the option in --help output. Users lose the visual signal of which flags they must provide. If you go with option 1 above, consider also calling option.mandatory = true (or keeping makeOptionMandatory but overriding missingMandatoryOptionValue) purely so the help text stays honest — you just need to ensure the TUI path still runs on a bare invocation.

Minor (not blocking)

  • src/router/router.test.ts:377 comment still says "Commander reject before the handler runs"; it's now Zod inside withValidation that rejects. Worth updating so the test's intent stays clear.
  • withLogging now logs raw pre-coercion flag values (e.g. "7" instead of 7 for a z.coerce.number()), because middleware around withValidation sees namedFlags built directly from optsWithGlobals(). Debug-only, but a behavior change worth being aware of.
  • Consider a direct unit test for the new createHandler({ middlewares }) wiring in router.test.ts — currently it's only exercised transitively through project/index.ts.

@agentcore-devx-automation agentcore-devx-automation Bot removed the agentcore-harness-reviewing AgentCore Harness review in progress label Sep 11, 2026
@codecov-commenter

codecov-commenter commented Sep 11, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.63014% with 1 line in your changes missing coverage. Please review.
✅ Project coverage is 97.06%. Comparing base (551ab96) to head (c29f33b).
⚠️ Report is 5 commits behind head on refactor.

Files with missing lines Patch % Lines
src/router/args.tsx 66.66% 1 Missing ⚠️
Additional details and impacted files
@@            Coverage Diff            @@
##           refactor    #2283   +/-   ##
=========================================
  Coverage     97.05%   97.06%           
=========================================
  Files           566      566           
  Lines         39228    39223    -5     
=========================================
- Hits          38073    38072    -1     
+ Misses         1155     1151    -4     

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Sep 11, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Sep 11, 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 Sep 11, 2026
@Hweinstock

Hweinstock commented Sep 11, 2026

Copy link
Copy Markdown
Contributor Author

Harness reviewer called out two valid consequences of this change that I think we can address as follow-ups:

Missing-required-flag error message regressed

This is actually good, because we now control the error message, and the error type so we not get InputValidationError instead of CommanderError. We can fix up this message as we see fit.

--help no longer marks required options

By marking flags as required in commander, any missing required flags will halt the execution before any of our code runs. We can wire this ourselves as part of the description. Note: this is the existing behavior since we didn't have any required flags.

@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Sep 11, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Sep 11, 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 Sep 11, 2026
@Hweinstock
Hweinstock marked this pull request as ready for review September 11, 2026 19:21
@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Sep 11, 2026

@notgitika notgitika 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.

added some comments + I think harness reviewer comments are good as well!

Comment thread src/handlers/runtime/logs/logs.test.tsx Outdated
try {
await expect(route(["runtime", "logs", "--since", `${SINCE_MS}`])).rejects.toThrow(
"required option '--id <id>' not specified",
"Invalid value for option '--id': Invalid input: expected string, received undefined",

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.

are we sure we want this error message instead?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

This is the existing error message for when a flag does not match the schema, which this now fallsthrough to instead of hitting the commander error. I was originally going to update this and some other error messages as a follow-up but I can pull it in here.

Comment thread src/router/flags.tsx
Comment on lines +25 to +27
const description =
info.required && !info.boolean ? `${flag.description} (required)` : flag.description;
const option = new Option(token, description);

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.

what do we think about using commander's helpGroup? ref: https://github.com/tj/commander.js/blob/master/examples/help-groups.js

output would look like:

  Required Options:
    --id <id>          the ID of the harness

  Options:
    -h, --help         display help

this would render required flags in a dedicated section while keeping presentation separate from validation. also, we should avoid makeOptionMandatory(), since it rejects missing flags before the TUI middleware can run

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

I like that idea! I think @jariy17 is working on something similar about grouping flags, so I think we can revisit this once that lands.

@github-actions github-actions Bot added size/m PR size: M and removed size/m PR size: M labels Sep 11, 2026
@agentcore-devx-automation agentcore-devx-automation Bot added the claude-security-reviewing Claude Code /security-review in progress label Sep 11, 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 Sep 11, 2026
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