Skip to content

azure.ai.agents - adopt SDK root command and remove reserved flag conflicts#7947

Merged
JeffreyCA merged 3 commits into
Azure:mainfrom
JeffreyCA:jeffreyca/7796/ext-agents-rootcmd
May 6, 2026
Merged

azure.ai.agents - adopt SDK root command and remove reserved flag conflicts#7947
JeffreyCA merged 3 commits into
Azure:mainfrom
JeffreyCA:jeffreyca/7796/ext-agents-rootcmd

Conversation

@JeffreyCA
Copy link
Copy Markdown
Contributor

@JeffreyCA JeffreyCA commented Apr 28, 2026

Fixes #7796

This PR migrates the azure.ai.agents extension to the new azd extension SDK command helpers — azdext.NewExtensionRootCommand, azdext.NewListenCommand, and azdext.NewMetadataCommand — and consolidates per-command boilerplate that was duplicated across the cobra command tree.

Why

Each azd extension previously hand-rolled its own root command, which meant manually registering the standard global flags (--debug, --no-prompt, --cwd, -e/--environment, -o/--output), wiring the env-var fallback for those flags (AZD_*), threading the access token onto the command context, and constructing the ExtensionHost/AzdClient lifecycle in listen. This duplication caused several real problems in the existing code:

  • Three commands (show, files list, files stat) and the addSessionFlags helper redeclared --output/-o, conflicting with the SDK's reserved global flag and producing flag redefined: "o" panics when the SDK began enforcing its global registration.
  • The sessions command group manually chained PersistentPreRunE to its parent and carried a long warning comment about an infinite-recursion footgun if the wrong Parent() reference was used.
  • setupDebugLogging was called explicitly from every command's RunE (≈14 sites), and it was easy for a new command to forget to call it.
  • Metadata generation and the listen command's setup were ~50 lines of boilerplate that drifted from the equivalent code in other extensions.

Changes

The root command is now built via azdext.NewExtensionRootCommand, which provides the standard global flags, env-var fallback, trace context, and access token wiring. Per-subcommand customization of --output (default value, allowed values, completion) flows through azdext.RegisterFlagOptions instead of redeclaring the inherited flag. Commands that need flag values now read them from the typed *azdext.ExtensionContext passed into their constructors, replacing the previous rootFlags global; a small ensureExtensionContext helper makes it safe to construct commands with nil context in tests that don't exercise RunE.

The listen command is now created by azdext.NewListenCommand, with extension-specific service target and event handler registration moved into a configureExtensionHost callback. The metadata command is created inline via azdext.NewMetadataCommand, deleting the equivalent local implementation. Debug logging setup (setupDebugLogging) is hoisted to the root command's PersistentPreRunE so every subcommand inherits it via cobra's EnableTraverseRunHooks, removing the per-command setup/cleanup pairs.

The previous fragile PersistentPreRunE chaining on the sessions group is no longer needed and has been deleted along with its warning comment.

Scope notes

NewVersionCommand was evaluated but not adopted in this PR: the SDK helper exposes only name and version, while the current command also surfaces Commit and BuildDate (populated at build time via -ldflags).

Testing

go build, go vet, go test ./..., and golangci-lint run ./... all pass cleanly. Existing tests were updated to read flag values from extCtx.OutputFormat instead of poking at cobra flag internals, and a new flag_options_test.go asserts that per-command output overrides are registered via the SDK's annotation contract.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR updates the azure.ai.agents extension command tree to rely on the azd extension SDK’s root command and inherited reserved global flags, eliminating collisions with azd’s reserved flag registry and aligning output/environment/no-prompt handling with the SDK.

Changes:

  • Switch root command creation to azdext.NewExtensionRootCommand and thread *azdext.ExtensionContext through subcommand constructors.
  • Remove subcommand redeclarations of reserved flags (--output/-o, --environment) and use azdext.RegisterFlagOptions + extCtx.OutputFormat instead.
  • Remove manual PersistentPreRunE chaining on intermediate commands (files, sessions) now that traverse hooks are enabled by the SDK.

Reviewed changes

Copilot reviewed 21 out of 22 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
cli/azd/extensions/azure.ai.agents/internal/cmd/root.go Adopt SDK root command and pass ExtensionContext to subcommands.
cli/azd/extensions/azure.ai.agents/internal/cmd/extension_context.go Add ensureExtensionContext helper to allow nil context in tests.
cli/azd/extensions/azure.ai.agents/internal/cmd/show.go Use RegisterFlagOptions for --output and read extCtx.NoPrompt/OutputFormat.
cli/azd/extensions/azure.ai.agents/internal/cmd/show_test.go Update constructor signature + validate output flag options via annotations.
cli/azd/extensions/azure.ai.agents/internal/cmd/files.go Remove pre-run chaining; use extCtx.NoPrompt + RegisterFlagOptions for output.
cli/azd/extensions/azure.ai.agents/internal/cmd/files_test.go Remove recursion regression test; update constructors and output assertions.
cli/azd/extensions/azure.ai.agents/internal/cmd/session.go Remove pre-run chaining; use extCtx.NoPrompt/OutputFormat and RegisterFlagOptions.
cli/azd/extensions/azure.ai.agents/internal/cmd/session_test.go Update constructors and output assertions.
cli/azd/extensions/azure.ai.agents/internal/cmd/run.go Thread NoPrompt via ExtensionContext instead of global flags.
cli/azd/extensions/azure.ai.agents/internal/cmd/monitor.go Use extCtx.NoPrompt instead of global flags.
cli/azd/extensions/azure.ai.agents/internal/cmd/monitor_test.go Update constructors to accept ExtensionContext.
cli/azd/extensions/azure.ai.agents/internal/cmd/invoke.go Thread NoPrompt via action field sourced from ExtensionContext.
cli/azd/extensions/azure.ai.agents/internal/cmd/invoke_test.go Update constructor signature to accept ExtensionContext.
cli/azd/extensions/azure.ai.agents/internal/cmd/init.go Remove local --environment; source environment + no-prompt from ExtensionContext.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_*.go Replace flags.NoPrompt usage with flags.noPrompt.
cli/azd/extensions/azure.ai.agents/internal/cmd/init_test.go Update tests for new initFlags shape (noPrompt field).
cli/azd/extensions/azure.ai.agents/internal/cmd/flag_options_test.go Add helper asserting RegisterFlagOptions annotations for output.
cli/azd/extensions/azure.ai.agents/go.mod Bump azd SDK dependency version.
cli/azd/extensions/azure.ai.agents/go.sum Update sums for the azd SDK bump.
cli/azd/extensions/azure.ai.agents/extension.yaml Bump requiredAzdVersion to a version that contains reserved-flag + flag-options support.

Comment thread cli/azd/extensions/azure.ai.agents/go.mod Outdated
Copy link
Copy Markdown
Member

@jongio jongio left a comment

Choose a reason for hiding this comment

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

Clean migration to azdext.NewExtensionRootCommand. Traced the full flag-threading path from SDK root through every subcommand - no stale rootFlags references survive and all noPrompt/OutputFormat reads happen after PersistentPreRunE populates ExtensionContext.

A few things I verified:

  • EnableTraverseRunHooks = true (set by the SDK) means the manual PersistentPreRunE chains in files.go and session.go would double-fire if kept. Removing them is correct.
  • RegisterFlagOptions stores config as cobra annotations, so the old cmd.Flags().GetString("output") assertions in tests correctly migrated to assertOutputFlagOptions checking cmd.Annotations.
  • ensureExtensionContext returning a zero-value context for nil input keeps test constructors simple without risk - the SDK populates the real context before any RunE executes.
  • The --environment removal from init is safe since the SDK's root persistent flag covers it, and init's RunE reads extCtx.Environment before proceeding.

Pseudo-version in go.mod is expected per the existing conversation - just needs the semver tag bump before merge.

No blocking issues found.

…flicts

 Switch the azure.ai.agents extension to azdext.NewExtensionRootCommand
 so it stops registering flags that conflict with azd's reserved global
 flag set (--debug, --no-prompt, --environment, --output/-o).
@JeffreyCA JeffreyCA force-pushed the jeffreyca/7796/ext-agents-rootcmd branch from a9ee765 to 18109be Compare May 5, 2026 21:48
@JeffreyCA JeffreyCA force-pushed the jeffreyca/7796/ext-agents-rootcmd branch from 2e14fbb to a34ac8b Compare May 5, 2026 22:12
@JeffreyCA JeffreyCA marked this pull request as ready for review May 5, 2026 22:14
@JeffreyCA JeffreyCA marked this pull request as draft May 5, 2026 22:24
Copy link
Copy Markdown
Contributor

@wbreza wbreza left a comment

Choose a reason for hiding this comment

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

✅ Approved — Clean SDK Migration

The migration from manual flag registration to azdext.NewExtensionRootCommand is correct, complete, and maintains full backward compatibility. No merge-blocking issues found. Confirms jongio's prior review.

Advisory Findings (P2-Medium — non-blocking)

  1. RegisterFlagOptions duplication — The same 5-line output flag registration block is repeated 6+ times across files.go, session.go, and show.go. Consider extracting a shared helper like registerOutputFlagOptions(cmd).

  2. Missing ensureExtensionContext(nil) unit test — The nil → zero-value contract in extension_context.go is intentional but undocumented by tests. A single test pinning this behavior would prevent accidental regressions.

  3. No integration test for extCtx threading — Tests verify command structure but none exercise the PersistentPreRunE → RunE pipeline to confirm extCtx is populated at execution time.

  4. PersistentPreRunE recursion test removed without replacement — Justified since the SDK now owns this via EnableTraverseRunHooks, but a brief comment or replacement test would document that assumption.

Verified Clean

Dimension Result
Correctness Migration complete — no stale rootFlags references
Backward Compat All CLI flags still work identically for users
Security Posture improved — input validation strengthened via AllowedValues
Description Alignment All 7 PR claims verified against actual diff
Concurrency Improved — global mutable state eliminated

@JeffreyCA JeffreyCA marked this pull request as ready for review May 5, 2026 22:46
Comment thread cli/azd/extensions/azure.ai.agents/internal/cmd/root.go
@JeffreyCA
Copy link
Copy Markdown
Contributor Author

/check-enforcer evaluate

@JeffreyCA
Copy link
Copy Markdown
Contributor Author

/check-enforcer override

@JeffreyCA JeffreyCA merged commit 526fe96 into Azure:main May 6, 2026
24 of 26 checks passed
@JeffreyCA JeffreyCA deleted the jeffreyca/7796/ext-agents-rootcmd branch May 6, 2026 00:30
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ext-agents azure.ai.agents extension

Projects

None yet

Development

Successfully merging this pull request may close these issues.

azure.ai.agents: adopt NewExtensionRootCommand and remove reserved global flag conflicts

5 participants