feat(cli): wire up ACMS context sub-app to main CLI entry point
CI / status-check (pull_request) Blocked by required conditions
CI / coverage (pull_request) Blocked by required conditions
CI / docker (pull_request) Blocked by required conditions
CI / push-validation (pull_request) Successful in 21s
CI / helm (pull_request) Successful in 34s
CI / build (pull_request) Successful in 54s
CI / lint (pull_request) Successful in 1m7s
CI / typecheck (pull_request) Successful in 1m21s
CI / quality (pull_request) Successful in 1m30s
CI / e2e_tests (pull_request) Successful in 4m17s
CI / unit_tests (pull_request) Failing after 5m1s
CI / integration_tests (pull_request) Failing after 5m20s
CI / security (pull_request) Failing after 11m55s

The ACMS context CLI commands ('context show' / 'context clear') were fully
implemented in 'acms_context.py' with comprehensive tests, mocks, benchmarks,
and documentation — but the module was never imported or registered in
'cli/main.py'. This commit wires up the 'acms_context.app' Typer sub-app
so that 'agents acms context show' and 'agents acms context clear' are
actually accessible from the CLI.

Changes:
- Import acms_context in _register_subcommands()
- Register acms_context.app as the 'acms' sub-app on the main Typer app
- Add 'acms' to valid_cmds list in main() for fast-path validation
- Add 'acms context' entry to _print_basic_help() output
- Minor formatting cleanup applied by ruff

ISSUES CLOSED: #9586
Refs: #9675
This commit is contained in:
2026-04-30 03:41:52 +00:00
parent dfdbb72181
commit 89df021b43
4 changed files with 22 additions and 30 deletions
+2 -5
View File
@@ -220,9 +220,7 @@ def step_run_context_clear_path(context: Any, pattern: str) -> None:
from cleveragents.cli.commands.acms_context import acms_context_clear from cleveragents.cli.commands.acms_context import acms_context_clear
all_entries: list[TieredFragment] = context.entries_to_remove all_entries: list[TieredFragment] = context.entries_to_remove
filtered = [ filtered = [f for f in all_entries if fnmatch.fnmatch(f.resource_id, pattern)]
f for f in all_entries if fnmatch.fnmatch(f.resource_id, pattern)
]
mock_service = make_mock_tier_service(fragments=all_entries) mock_service = make_mock_tier_service(fragments=all_entries)
mock_container = make_mock_container(mock_service) mock_container = make_mock_container(mock_service)
@@ -344,8 +342,7 @@ def step_run_context_clear_help(context: Any) -> None:
from cleveragents.cli.commands.acms_context import acms_context_clear from cleveragents.cli.commands.acms_context import acms_context_clear
context.command_output = ( context.command_output = (
acms_context_clear.__doc__ acms_context_clear.__doc__ or "Remove stale context entries from the ACMS index"
or "Remove stale context entries from the ACMS index"
) )
context.command_exit_code = 0 context.command_exit_code = 0
+2 -6
View File
@@ -152,9 +152,7 @@ def _cmd_context_show_empty() -> int:
print(f"acms-fail: context show empty exited with code {exit_code}") print(f"acms-fail: context show empty exited with code {exit_code}")
return 1 return 1
if "No context found for view: empty_view" not in output: if "No context found for view: empty_view" not in output:
print( print(f"acms-fail: expected 'No context found for view' in output\n{output}")
f"acms-fail: expected 'No context found for view' in output\n{output}"
)
return 1 return 1
print("acms-context-show-empty-ok") print("acms-context-show-empty-ok")
return 0 return 0
@@ -238,9 +236,7 @@ def _cmd_context_clear_no_match() -> int:
print(f"acms-fail: context clear no-match exited with code {exit_code}") print(f"acms-fail: context clear no-match exited with code {exit_code}")
return 1 return 1
if "No context entries match the specified filters" not in output: if "No context entries match the specified filters" not in output:
print( print(f"acms-fail: expected 'No context entries match' in output\n{output}")
f"acms-fail: expected 'No context entries match' in output\n{output}"
)
return 1 return 1
print("acms-context-clear-no-match-ok") print("acms-context-clear-no-match-ok")
return 0 return 0
+8 -19
View File
@@ -23,9 +23,7 @@ if TYPE_CHECKING:
pass pass
# Create sub-app for ACMS context commands # Create sub-app for ACMS context commands
app = typer.Typer( app = typer.Typer(help="ACMS context management commands (agents acms context)")
help="ACMS context management commands (agents acms context)"
)
def _format_budget_utilization( def _format_budget_utilization(
@@ -82,9 +80,7 @@ def acms_context_show(
fragments = tier_service.get_scoped_view([view.strip()]) fragments = tier_service.get_scoped_view([view.strip()])
if not fragments: if not fragments:
console.print( console.print(f"[yellow]No context found for view: {view}[/yellow]")
f"[yellow]No context found for view: {view}[/yellow]"
)
return return
# Display assembled context # Display assembled context
@@ -98,9 +94,7 @@ def acms_context_show(
total_tokens = 0 total_tokens = 0
for fragment in fragments: for fragment in fragments:
resource_id, tier_label, token_str, project = ( resource_id, tier_label, token_str, project = _format_fragment_row(fragment)
_format_fragment_row(fragment)
)
total_tokens += fragment.token_count total_tokens += fragment.token_count
table.add_row(resource_id, tier_label, token_str, project) table.add_row(resource_id, tier_label, token_str, project)
@@ -200,9 +194,7 @@ def acms_context_clear(
console.print(table) console.print(table)
if len(entries_to_remove) > 10: if len(entries_to_remove) > 10:
console.print( console.print(f" ... and {len(entries_to_remove) - 10} more entries")
f" ... and {len(entries_to_remove) - 10} more entries"
)
# Confirm if needed # Confirm if needed
if not yes: if not yes:
@@ -215,9 +207,7 @@ def acms_context_clear(
# Remove entries by evicting from their respective tiers # Remove entries by evicting from their respective tiers
removed_count = _remove_fragments(tier_service, entries_to_remove) removed_count = _remove_fragments(tier_service, entries_to_remove)
console.print( console.print(f"\n[green]✓[/green] Removed {removed_count} context entries.")
f"\n[green]✓[/green] Removed {removed_count} context entries."
)
except CleverAgentsError as e: except CleverAgentsError as e:
console = _get_console() console = _get_console()
@@ -249,13 +239,12 @@ def _filter_fragments(
result = fragments result = fragments
if path: if path:
result = [ result = [f for f in result if fnmatch.fnmatch(f.resource_id, path)]
f for f in result if fnmatch.fnmatch(f.resource_id, path)
]
if tag: if tag:
result = [ result = [
f for f in result f
for f in result
if f.metadata.get("tag") == tag or f.metadata.get("tags") == tag if f.metadata.get("tag") == tag or f.metadata.get("tags") == tag
] ]
+10
View File
@@ -79,6 +79,7 @@ def _register_subcommands() -> None:
try: try:
from cleveragents.cli.commands import ( from cleveragents.cli.commands import (
acms_context,
action, action,
actor, actor,
audit, audit,
@@ -112,6 +113,13 @@ def _register_subcommands() -> None:
app.add_typer(project.app, name="project", help="Project management") app.add_typer(project.app, name="project", help="Project management")
# Register acms context as a sub-app (canonical: agents acms context)
app.add_typer(
acms_context.app,
name="acms",
help="ACMS (Advanced Context Management System) operations.",
)
# Register context as a sub-app of actor (canonical: agents actor context) # Register context as a sub-app of actor (canonical: agents actor context)
actor.app.add_typer( actor.app.add_typer(
context.app, context.app,
@@ -252,6 +260,7 @@ def _print_basic_help() -> None:
typer.echo("\nCommon commands:") typer.echo("\nCommon commands:")
typer.echo(" project Project management") typer.echo(" project Project management")
typer.echo(" actor context Actor context management") typer.echo(" actor context Actor context management")
typer.echo(" acms context ACMS context management (show, clear)")
typer.echo(" plan Plan operations (actor required)") typer.echo(" plan Plan operations (actor required)")
typer.echo(" actor Actor management and defaults") typer.echo(" actor Actor management and defaults")
typer.echo(" init Initialize a project") typer.echo(" init Initialize a project")
@@ -725,6 +734,7 @@ def main(args: list[str] | None = None) -> int:
"diagnostics", "diagnostics",
"init", "init",
"project", "project",
"acms",
"context", "context",
"plan", "plan",
"actor", "actor",