Skip to content

feat(cli): improve interactive shell automation#1167

Merged
davincios merged 1 commit intomainfrom
feature/automated-terminal-fixes
May 1, 2026
Merged

feat(cli): improve interactive shell automation#1167
davincios merged 1 commit intomainfrom
feature/automated-terminal-fixes

Conversation

@davincios
Copy link
Copy Markdown
Contributor

Update the interactive shell to execute model/provider changes directly, keep model metadata current, and cover the related terminal workflows with regression tests.

Made-with: Cursor

Fixes #

Describe the changes you have made in this PR -

Demo/Screenshot for feature changes and bug fixes -


Code Understanding and AI Usage

Did you use AI assistance (ChatGPT, Claude, Copilot, etc.) to write any part of this code?

  • No, I wrote all the code myself
  • Yes, I used AI assistance (continue below)

If you used AI assistance:

  • I have reviewed every single line of the AI-generated code
  • I can explain the purpose and logic of each function/component I added
  • I have tested edge cases and understand how the code handles them
  • I have modified the AI output to follow this project's coding standards and conventions

Explain your implementation approach:


Checklist before requesting a review

  • I have added proper PR title and linked to the issue
  • I have performed a self-review of my code
  • I can explain the purpose of every function, class, and logic block I added
  • I understand why my changes work and have tested them thoroughly
  • I have considered potential edge cases and how my code handles them
  • If it is a core feature, I have added thorough tests
  • My code follows the project's style guidelines and conventions

Note: Please check Allow edits from maintainers if you would like us to assist in the PR.

Update the interactive shell to execute model/provider changes directly, keep model metadata current, and cover the related terminal workflows with regression tests.

Made-with: Cursor
@davincios davincios merged commit 449f0c0 into main May 1, 2026
7 of 9 checks passed
@davincios davincios deleted the feature/automated-terminal-fixes branch May 1, 2026 01:16
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 1, 2026

🎊 Achievement unlocked: PR Merged. @davincios passed code review, survived CI, and shipped. Respect. 🤝


👋 Join us on Discord - OpenSRE : hang out, contribute, or hunt for features and issues. Everyone's welcome.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 1, 2026

Greptile Summary

This PR upgrades the interactive shell with four new deterministic action kinds (shell execution, LLM provider switching, sample alert, synthetic RDS test), a SlashCommandCompleter with live bottom toolbar, persistent prompt history, a centralised theme module, and an LLM-driven JSON action-plan path in the CLI agent. The /model set command now applies provider/model changes live without requiring a restart.

  • P1 – In execute_cli_actions, the return value of switch_llm_provider is not checked, so a failed provider switch (e.g. unrecognised provider) is unconditionally recorded as ok=True in session history.

Confidence Score: 4/5

Safe to merge after fixing the session-history ok flag for failed provider switches; all other findings are non-blocking P2 suggestions.

One P1 defect: failed LLM provider switches are silently recorded as successful in session history. The remaining findings are a duplicate regex (P2) and a missing error guard in history loading (P2). The feature is well-tested and the new deterministic pre-pass architecture is sound.

app/cli/interactive_shell/agent_actions.py (P1 return-value bug on llm_provider action), app/cli/interactive_shell/history.py (missing OSError guard)

Important Files Changed

Filename Overview
app/cli/interactive_shell/agent_actions.py Major expansion: adds shell execution, LLM provider switching, sample alert, and synthetic test action kinds; switch_llm_provider return value ignored (P1); _SAMPLE_ALERT_RE duplicates terminal_intent.py (P2)
app/cli/interactive_shell/commands.py Adds switch_llm_provider public function; replaces the "not yet supported" stub for /model set with live env-var synchronisation; theme tokens extracted
app/cli/interactive_shell/history.py New file: persistent command history via prompt_toolkit FileHistory; load_command_history_entries lacks the try/except OSError guard present in its sibling load_prompt_history (P2)
app/cli/interactive_shell/loop.py Adds slash-command autocomplete, bottom toolbar with live model info, persistent history, themed prompt colour, and key-bindings for completion navigation
app/cli/interactive_shell/cli_agent.py Adds JSON action-plan parsing so LLM can return structured actions (switch_llm_provider, slash); _execute_action_plan validates against allowlist before dispatching
app/cli/interactive_shell/theme.py New file: centralises OpenClaw brand colour tokens for Rich markup and ANSI escape sequences; replaces scattered hard-coded bold cyan strings across the shell
app/cli/interactive_shell/terminal_intent.py Adds is_sample_alert_launch_intent with the same regex used in agent_actions.py; the duplicate definition is the source of the P2 divergence risk
app/cli/investigation/investigate.py Extracts shared _run_session_alert_payload helper; adds run_sample_alert_for_session that loads a built-in template and delegates to the shared helper
app/integrations/github_mcp.py Wraps asyncio.run in _run_async with a BaseException handler that closes the coroutine before re-raising, preventing resource leaks on unexpected exceptions
tests/cli/interactive_shell/test_agent_actions.py Adds tests for provider switch, shell execution, sample alert, synthetic RDS test, and various planning edge cases; good coverage of new action kinds

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[User types in REPL] --> B{Starts with /}
    B -- Yes --> C[dispatch_slash]
    B -- No --> D[execute_cli_actions\ndeterministic pre-pass]
    D --> E{Any planned\nactions?}
    E -- No --> F[classify_input router]
    E -- Yes --> G[_print_planned_actions]
    G --> H{action.kind}
    H -- slash --> I[dispatch_slash]
    H -- llm_provider --> J[switch_llm_provider\nwrites .env + os.environ]
    H -- shell --> K[subprocess.run\nshell=True]
    H -- sample_alert --> L[run_sample_alert_for_session\nLangGraph pipeline]
    H -- synthetic_test --> M[subprocess: opensre tests synthetic]
    F --> N{InputKind}
    N -- cli_help --> O[answer_cli_help]
    N -- cli_agent --> P[answer_cli_agent\nLLM call]
    N -- new_alert / follow_up --> Q[LangGraph pipeline]
    P --> R{LLM returns\nJSON action plan?}
    R -- Yes --> S[_execute_action_plan\nswitch_llm_provider or slash]
    R -- No --> T[Render Markdown reply]
Loading

Comments Outside Diff (1)

  1. app/cli/interactive_shell/history.py, line 36-39 (link)

    P2 load_command_history_entries silently raises on filesystem errors

    load_prompt_history wraps its FileHistory construction in try/except OSError and falls back to InMemoryHistory. load_command_history_entries creates a FileHistory object directly without any guard, so a non-writable home directory, a full filesystem, or a missing parent directory will raise an unhandled OSError all the way to the caller (the /history command handler). A simple try/except returning an empty list keeps the same defensive posture as its sibling.

Reviews (1): Last reviewed commit: "feat(cli): improve interactive shell aut..." | Re-trigger Greptile

Comment on lines +421 to +424
ok = completed.returncode == 0
if not ok:
console.print(f"[red]exit code:[/red] {completed.returncode}")
elif not completed.stdout and not completed.stderr:
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.

P1 switch_llm_provider return value is ignored

The return value of switch_llm_provider is not checked, so a failed provider switch (e.g. an unrecognised provider name or a missing PROVIDER_BY_VALUE entry) is unconditionally recorded as ok=True in the session history. _LLM_PROVIDER_NAMES includes "codex" and "nvidia" which may not be present in PROVIDER_BY_VALUE, making this failure path reachable.

Suggested change
ok = completed.returncode == 0
if not ok:
console.print(f"[red]exit code:[/red] {completed.returncode}")
elif not completed.stdout and not completed.stderr:
elif action.kind == "llm_provider":
console.print(f"[bold]$ /model set {escape(action.content)}[/bold]")
ok = switch_llm_provider(action.content, console)
session.record("slash", f"/model set {action.content}", ok=ok)

Comment on lines 69 to +77
),
)

_SAMPLE_ALERT_RE = re.compile(
r"\b(?:try|run|start|launch|fire|send|trigger)\b.{0,60}?"
r"\b(?:sample|simple|test|demo)\s+(?:alert|event)\b",
re.IGNORECASE,
)
_SYNTHETIC_RDS_TEST_RE = re.compile(
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.

P2 Duplicated regex from terminal_intent.py

_SAMPLE_ALERT_RE is byte-for-byte identical to _SAMPLE_ALERT_LAUNCH_RE defined in terminal_intent.py. The module already imports mentioned_integration_services from terminal_intent, so it can import is_sample_alert_launch_intent (or expose the compiled pattern) instead. Duplicating the pattern means a future edit to one copy won't automatically propagate to the other.

Suggested change
),
)
_SAMPLE_ALERT_RE = re.compile(
r"\b(?:try|run|start|launch|fire|send|trigger)\b.{0,60}?"
r"\b(?:sample|simple|test|demo)\s+(?:alert|event)\b",
re.IGNORECASE,
)
_SYNTHETIC_RDS_TEST_RE = re.compile(
from app.cli.interactive_shell.terminal_intent import is_sample_alert_launch_intent, mentioned_integration_services

Then replace the _SAMPLE_ALERT_RE.search(clause.text) is not None call with is_sample_alert_launch_intent(clause.text).

Sarah-Salah added a commit to Sarah-Salah/opensre that referenced this pull request May 5, 2026
Resolves conflicts in auto-generated bot files: docs/daily-updates/overview.mdx, docs/daily-updates/2026-04-30.mdx, docs/daily-updates/2026-05-01.mdx, and README.md (contributors section). All four are produced by scheduled bot workflows in main and have no relationship to this PR; resolved by accepting the upstream main version verbatim.

Pulls in 35+ commits from main since this PR was opened, including: refactor of integrations module (Tracer-Cloud#1165), Splunk integration (Tracer-Cloud#791), interactive shell improvements (Tracer-Cloud#1159, Tracer-Cloud#1167), Claude Code CLI provider (Tracer-Cloud#1168), and CI quality gate restoration. None of these touch the OpenSearch wizard, detect_sources, or the validation modules this PR modifies.

Refs: Tracer-Cloud#1143
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant