feat(cli): improve interactive shell automation#1167
Conversation
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
|
🎊 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 SummaryThis PR upgrades the interactive shell with four new deterministic action kinds (shell execution, LLM provider switching, sample alert, synthetic RDS test), a
Confidence Score: 4/5Safe 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
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]
|
| ok = completed.returncode == 0 | ||
| if not ok: | ||
| console.print(f"[red]exit code:[/red] {completed.returncode}") | ||
| elif not completed.stdout and not completed.stderr: |
There was a problem hiding this comment.
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.
| 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) |
| ), | ||
| ) | ||
|
|
||
| _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( |
There was a problem hiding this comment.
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.
| ), | |
| ) | |
| _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).
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

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?
If you used AI assistance:
Explain your implementation approach:
Checklist before requesting a review
Note: Please check Allow edits from maintainers if you would like us to assist in the PR.