Skip to content

Conversation

@pavanimanchala53
Copy link
Contributor

@pavanimanchala53 pavanimanchala53 commented Jan 1, 2026

Related Issue

Closes #248

Summary

This PR improves the stability and reliability of the natural-language
install flow by refining prompt construction and handling edge cases
that affected demos and tests.

No hardcoded request mappings or fixed install logic were introduced.


What changed

  • Improved system prompt consistency for command generation
  • Normalized how user input (including stdin and dry-run) is passed to the LLM
  • Removed unreachable and duplicated code paths flagged by static analysis
  • Fixed edge cases that caused ambiguous behavior or test failures
  • Aligned CLI behavior to be deterministic and test-safe

Summary by CodeRabbit

  • New Features

    • Interactive command confirmation with edit-before-execute flow.
    • Intent extraction to better interpret user requests.
    • Stdin-aware prompt handling to include piped input when building commands.
  • Improvements

    • More robust command parsing for varied LLM outputs.
    • Non-interactive paths auto-approve; added a simulated provider path that prints generated commands without executing.
  • Style

    • Removed environment entry from help display.
  • Chores

    • Added a new CLA signer entry.

✏️ Tip: You can customize this high-level summary in your review settings.

@github-actions
Copy link

github-actions bot commented Jan 1, 2026

CLA Verification Passed

All contributors have signed the CLA.

Contributor Signed As
@pavanimanchala53 @pavanimanchala53

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 1, 2026

Warning

Rate limit exceeded

@pavanimanchala53 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 9 minutes and 45 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between a6b8b49 and 47ab94e.

📒 Files selected for processing (2)
  • cortex/cli.py
  • cortex/llm/interpreter.py
📝 Walkthrough

Walkthrough

This PR adds intent extraction to the install flow, integrates stdin-aware prompt building, and introduces an interactive confirmation/editing step (with non-interactive auto-approve). It also expands LLM intent/command-parsing logic and adds a CLA signer entry.

Changes

Cohort / File(s) Summary
CLI interactive flow
cortex/cli.py
Added _is_interactive() and CortexCLI._build_prompt_with_stdin(). Reworked install() to extract intent, build prompts with stdin, support a fake provider path (print-only), present interactive proceed/edit/cancel confirmation (non-interactive auto-approve), and removed env from help output.
Intent extraction & parsing
cortex/llm/interpreter.py
Added extract_intent() and provider-specific intent extractors (_extract_intent_openai, _extract_intent_ollama), _get_intent_prompt(), _parse_intent_from_text(), _estimate_confidence(). Enhanced _parse_commands() for robust JSON/code-fence extraction and added richer system prompt/formatting.
Repository metadata
.github/cla-signers.json
Added a new CLA signer entry for Swaroop Manchala ("github_username": "renoschubert").

Sequence Diagram(s)

sequenceDiagram
    actor User
    participant CLI as cortex/cli
    participant Interp as CommandInterpreter
    participant LLM as LLM Provider\n(OpenAI / Ollama)
    participant Shell as System Shell

    User->>CLI: run install <natural-language>
    CLI->>CLI: _is_interactive() check
    CLI->>CLI: _build_prompt_with_stdin(user_prompt)
    CLI->>Interp: extract_intent(user_prompt)
    activate Interp
    Interp->>LLM: provider-specific intent request
    activate LLM
    LLM-->>Interp: intent JSON (action, install_mode, confidence)
    deactivate LLM
    Interp-->>CLI: structured intent
    deactivate Interp

    CLI->>Interp: generate commands (prompt w/ mode context)
    activate Interp
    Interp->>LLM: command-generation request
    activate LLM
    LLM-->>Interp: suggested commands
    deactivate LLM
    Interp-->>CLI: parsed command list
    deactivate Interp

    alt interactive
        CLI->>User: show commands + [proceed / edit / cancel]
        alt edit
            User->>CLI: line-by-line edits
            CLI->>User: show updated commands -> re-confirm
            User->>CLI: confirm
        else proceed
            User->>CLI: confirm
        end
    else non-interactive
        CLI->>CLI: auto-approve
    end

    CLI->>Shell: execute approved commands
    Shell-->>CLI: execution result
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

Suggested reviewers

  • dhvll
  • mikejmorgan-ai

Poem

🐰 I nibble prompts from stdin’s stream,
I parse intent in a LLM dream,
I print the plan and ask to play,
Edit or go — CI says “OK!” 🥕

Pre-merge checks and finishing touches

❌ Failed checks (2 warnings)
Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The addition of a CLA signer entry in .github/cla-signers.json is administrative and unrelated to the NL install feature work described in issue #248. The CLA signer entry should be committed separately or the PR scope should be clarified; administrative changes are typically decoupled from feature development.
Docstring Coverage ⚠️ Warning Docstring coverage is 44.44% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
✅ Passed checks (3 passed)
Check name Status Explanation
Title check ✅ Passed The title 'NL install: Improve prompt handling and reliability for demos' directly reflects the main changes: enhanced prompt construction and improved reliability for the natural-language install flow.
Description check ✅ Passed The description adequately covers the PR's objectives and changes. It explains the motivation (reliability and edge case handling), lists key improvements, and explicitly states no hardcoded logic was introduced.
Linked Issues check ✅ Passed The PR addresses issue #248 by implementing core requirements: improved system prompt consistency, normalized LLM input handling, intent extraction with confidence scoring, and prompt confirmation flows for reliability.

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
cortex/llm/interpreter.py (1)

413-431: Unreachable code: lines 416–431 can never execute.

The early return at lines 413–414 exits whenever commands is a list. Since data.get("commands", []) always returns a list (defaulting to []), the code after line 414 handling object arrays is dead code.

🔎 Proposed fix: integrate both parsing paths
             data = json.loads(json_blob)
             commands = data.get("commands", [])

-            if isinstance(commands, list):
-                return [c for c in commands if isinstance(c, str) and c.strip()]
-
             # Handle both formats:
             # 1. ["cmd1", "cmd2"] - direct string array
             # 2. [{"command": "cmd1"}, {"command": "cmd2"}] - object array
+            if not isinstance(commands, list):
+                raise ValueError("commands must be a list")
+
             result = []
             for cmd in commands:
                 if isinstance(cmd, str):
-                    # Direct string
-                    if cmd:
+                    if cmd.strip():
                         result.append(cmd)
                 elif isinstance(cmd, dict):
                     # Object with "command" key
                     cmd_str = cmd.get("command", "")
-                    if cmd_str:
+                    if cmd_str and cmd_str.strip():
                         result.append(cmd_str)

             return result
🧹 Nitpick comments (4)
cortex/llm/interpreter.py (2)

144-158: Multiline string indentation introduces leading whitespace in prompt.

The indentation inside the return string adds literal leading spaces to each line of the prompt sent to the LLM. This wastes tokens and may confuse some models. Consider using textwrap.dedent() or removing the leading indentation.

🔎 Proposed fix using dedent
+import textwrap
+
 ...
 
-        return """You are a Linux system command expert. Convert natural language requests into safe, validated bash commands.
-
-    Rules:
-    1. Return ONLY a JSON array of commands
+        return textwrap.dedent("""\
+            You are a Linux system command expert. Convert natural language requests into safe, validated bash commands.
+
+            Rules:
+            1. Return ONLY a JSON array of commands
 ...
+        """).strip()

528-560: _estimate_confidence method is never called — appears to be dead code.

This method is defined but not invoked anywhere in the file. If it's intended for future use, consider adding a TODO comment or removing it to reduce maintenance burden.

cortex/cli.py (2)

655-656: Duplicate comment line.

Lines 655 and 656 contain the same comment. Remove the duplicate.

             # ---------- User confirmation ----------
-            # ---------- User confirmation ----------

677-686: Edit mode UX could be clearer.

The edit flow prompts with just > without explaining how to finish input (empty line to end). Consider adding brief instructions.

🔎 Proposed improvement
                 elif choice == "e":
                     if not _is_interactive():
                         self._print_error("Cannot edit commands in non-interactive mode")
                         return 1

+                    print("Enter commands (one per line, empty line to finish):")
                     edited_commands = []
                     while True:
                         line = input("> ").strip()
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 13195aa and dccb375.

📒 Files selected for processing (2)
  • cortex/cli.py
  • cortex/llm/interpreter.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Follow PEP 8 style guide
Type hints required in Python code
Docstrings required for all public APIs

Files:

  • cortex/llm/interpreter.py
  • cortex/cli.py
🧠 Learnings (2)
📚 Learning: 2025-12-11T12:03:24.071Z
Learnt from: CR
Repo: cortexlinux/cortex PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-11T12:03:24.071Z
Learning: Applies to **/*install*.py : Dry-run by default for all installations in command execution

Applied to files:

  • cortex/cli.py
📚 Learning: 2025-12-11T12:03:24.071Z
Learnt from: CR
Repo: cortexlinux/cortex PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-11T12:03:24.071Z
Learning: Applies to **/*install*.py : No silent sudo execution - require explicit user confirmation

Applied to files:

  • cortex/cli.py
🧬 Code graph analysis (1)
cortex/cli.py (2)
cortex/first_run_wizard.py (1)
  • _print_error (746-748)
cortex/llm/interpreter.py (2)
  • parse (458-516)
  • extract_intent (562-573)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (3)
  • GitHub Check: test (3.10)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.11)
🔇 Additional comments (3)
cortex/cli.py (3)

34-36: LGTM!

Simple and correct implementation for detecting interactive mode.


611-633: Intent extraction integration looks correct.

The integration of extract_intent to determine install_mode and tailor the prompt is well-structured. Consider adding exception handling around extract_intent to provide a graceful fallback if intent extraction fails, similar to how command parsing failures are handled.


657-666: Non-interactive auto-approval may bypass user confirmation for sudo commands.

Based on learnings, "No silent sudo execution - require explicit user confirmation" is expected. However, non-interactive mode (CI/pytest) auto-approves all commands including those with sudo. Consider logging a warning or ensuring the --execute flag itself serves as the explicit confirmation in CI contexts.

@pavanimanchala53
Copy link
Contributor Author

here is the working video which shows installing commands using edit option and then proceeding with installation

Screen.Recording.2026-01-01.160454.mp4

Copy link
Collaborator

@Anshgrover23 Anshgrover23 left a comment

Choose a reason for hiding this comment

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

@pavanimanchala53 Create a new PR following the pattern of this PR #401 , As currently CLA Verification CI check is failing.

@Anshgrover23 Anshgrover23 mentioned this pull request Jan 1, 2026
@pavanimanchala53 pavanimanchala53 force-pushed the feature/nl-parser-clean branch from 64a2515 to a6b8b49 Compare January 2, 2026 07:09
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

♻️ Duplicate comments (6)
cortex/cli.py (2)

44-53: self.stdin_data is still never initialized — stdin context feature remains non-functional.

The method checks for self.stdin_data via getattr, but this attribute is never assigned anywhere in the class or __init__. The stdin context prepending will always be skipped, making the feature dead code.

Based on learnings, this should be initialized to capture stdin when available (e.g., in __init__ or before calling this method) by reading sys.stdin.read() when not sys.stdin.isatty().


594-596: Hardcoded "docker installed successfully!" message is incorrect for non-docker software.

This message is printed regardless of what software is being installed in fake mode. It should reflect the actual software parameter.

🔎 Proposed fix
             if execute:
-                print("\ndocker installed successfully!")
+                print(f"\n{software} installed successfully!")
cortex/llm/interpreter.py (4)

179-183: self.ollama_url is undefined — this will raise AttributeError at runtime.

The _extract_intent_ollama method references self.ollama_url on line 180, but this attribute is never set. In _initialize_client (lines 93-122), ollama_base_url is a local variable and is not stored on the instance.

🔎 Proposed fix

Store the URL as an instance attribute in _initialize_client:

         elif self.provider == APIProvider.OLLAMA:
             # Ollama uses OpenAI-compatible API
             try:
                 from openai import OpenAI

                 ollama_base_url = os.environ.get("OLLAMA_BASE_URL", "http://localhost:11434")
+                self.ollama_url = ollama_base_url
                 self.client = OpenAI(
                     api_key="ollama", base_url=f"{ollama_base_url}/v1"  # Dummy key, not used
                 )

231-238: Missing colon in JSON format example will confuse LLMs.

Line 234 shows "install_mode" "..." but should be "install_mode": "...". The LLM may produce malformed JSON responses that fail parsing.

🔎 Proposed fix
         Format:
         {
         "action": "...",
         "domain": "...",
-        "install_mode" "..."
+        "install_mode": "...",
         "description": "...",
         "ambiguous": true/false,
         "confidence": 0.0
         }

258-270: Missing error handling in _extract_intent_openai — inconsistent with Ollama path.

_extract_intent_ollama returns a fallback dict on failure (lines 191-199), but _extract_intent_openai will raise unhandled exceptions if the API call fails or returns malformed JSON. This creates inconsistent behavior between providers.

🔎 Proposed fix: wrap in try/except with fallback
     def _extract_intent_openai(self, user_input: str) -> dict:
+        try:
             response = self.client.chat.completions.create(
                 model=self.model,
                 messages=[
                     {"role": "system", "content": self._get_intent_prompt()},
                     {"role": "user", "content": user_input},
                 ],
                 temperature=0.2,
                 max_tokens=300,
             )

             content = response.choices[0].message.content.strip()
-            return json.loads(content)
+            return self._parse_intent_from_text(content)
+        except Exception:
+            return {
+                "action": "unknown",
+                "domain": "unknown",
+                "install_mode": "system",
+                "description": "Failed to extract intent",
+                "ambiguous": True,
+                "confidence": 0.0,
+            }

562-573: Missing docstring for public API extract_intent and FAKE provider not handled.

Per coding guidelines, docstrings are required for all public APIs. Additionally, the FAKE provider is not handled and will raise ValueError, which may break tests or CLI paths that use the fake provider.

🔎 Proposed fix
     def extract_intent(self, user_input: str) -> dict:
+        """Extract user intent from natural language input.
+
+        Args:
+            user_input: Natural language description of desired action
+
+        Returns:
+            Dictionary containing action, domain, install_mode, description,
+            ambiguous flag, and confidence score.
+
+        Raises:
+            ValueError: If input is empty or provider is unsupported
+            NotImplementedError: If provider does not support intent extraction
+        """
         if not user_input or not user_input.strip():
             raise ValueError("User input cannot be empty")

         if self.provider == APIProvider.OPENAI:
             return self._extract_intent_openai(user_input)
         elif self.provider == APIProvider.CLAUDE:
             raise NotImplementedError("Intent extraction not yet implemented for Claude")
         elif self.provider == APIProvider.OLLAMA:
             return self._extract_intent_ollama(user_input)
+        elif self.provider == APIProvider.FAKE:
+            # Return a default intent for testing
+            return {
+                "action": "install",
+                "domain": "unknown",
+                "install_mode": "system",
+                "description": "Fake intent for testing",
+                "ambiguous": False,
+                "confidence": 1.0,
+            }
         else:
             raise ValueError(f"Unsupported provider: {self.provider}")
🧹 Nitpick comments (2)
cortex/cli.py (2)

34-36: Consider adding type hints and a docstring for completeness.

Per coding guidelines, type hints and docstrings are required for public APIs. While this is an internal helper, adding them improves maintainability.

🔎 Proposed enhancement
-def _is_interactive():
+def _is_interactive() -> bool:
+    """Check if stdin is connected to a TTY (interactive terminal).
+    
+    Returns:
+        bool: True if stdin is a TTY, False otherwise (e.g., in CI/piped input)
+    """
     return sys.stdin.isatty()

656-656: Remove duplicate comment.

The comment # ---------- User confirmation ---------- appears twice on consecutive lines.

🔎 Proposed fix
-            # ---------- User confirmation ----------
             # ---------- User confirmation ----------
             if execute:
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dccb375 and a6b8b49.

📒 Files selected for processing (3)
  • .github/cla-signers.json
  • cortex/cli.py
  • cortex/llm/interpreter.py
🧰 Additional context used
📓 Path-based instructions (1)
**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

**/*.py: Follow PEP 8 style guide
Type hints required in Python code
Docstrings required for all public APIs

Files:

  • cortex/llm/interpreter.py
  • cortex/cli.py
🧠 Learnings (2)
📚 Learning: 2025-12-11T12:03:24.071Z
Learnt from: CR
Repo: cortexlinux/cortex PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-11T12:03:24.071Z
Learning: Applies to **/*install*.py : Dry-run by default for all installations in command execution

Applied to files:

  • cortex/cli.py
📚 Learning: 2025-12-11T12:03:24.071Z
Learnt from: CR
Repo: cortexlinux/cortex PR: 0
File: AGENTS.md:0-0
Timestamp: 2025-12-11T12:03:24.071Z
Learning: Applies to **/*install*.py : No silent sudo execution - require explicit user confirmation

Applied to files:

  • cortex/cli.py
🧬 Code graph analysis (1)
cortex/cli.py (1)
cortex/llm/interpreter.py (3)
  • CommandInterpreter (18-573)
  • parse (458-516)
  • extract_intent (562-573)
🔇 Additional comments (6)
.github/cla-signers.json (2)

26-34: LGTM! CLA entry structure is correct.

The new CLA signer entry for Swaroop Manchala is well-formed, follows the established structure, and includes all required fields with valid data.


1-98: Verify: CLA update appears inconsistent with PR objectives.

The PR objectives and AI summary describe substantial changes to the natural language install flow (intent extraction, stdin-aware prompt building, interactive confirmation/editing), but only the CLA signers file is provided for review.

Please confirm:

  1. Are the actual code changes for NL install improvements in a different file set?
  2. Is this CLA update for a co-contributor on this PR?
cortex/cli.py (1)

611-633: LGTM — Intent-driven prompt construction is well-structured.

The extraction of install_mode from intent and the conditional prompt building (python vs system) provides good separation between Python virtualenv workflows and system package installation. The integration with _build_prompt_with_stdin allows for future stdin context enrichment once that feature is properly initialized.

cortex/llm/interpreter.py (3)

144-157: LGTM — System prompt improvements enhance command generation clarity.

The updated rules and structured format with examples should improve consistency across providers.


272-300: LGTM — Robust intent parsing with sensible fallback.

The JSON extraction logic handles loose LLM output gracefully, validates required fields, and returns a safe default on failure. This approach prevents crashes from malformed responses.


528-560: LGTM — Confidence estimation uses reasonable heuristics.

The linguistic signal approach (length, install keywords, vague words, domain) provides a practical confidence score without hardcoding domain-specific semantics. The clamping to [0.2, 1.0] ensures meaningful scores.

@pavanimanchala53 pavanimanchala53 force-pushed the feature/nl-parser-clean branch 2 times, most recently from 06b3928 to 07a4d5f Compare January 2, 2026 07:28
@pavanimanchala53 pavanimanchala53 force-pushed the feature/nl-parser-clean branch from 07a4d5f to 47ab94e Compare January 2, 2026 07:29
@sonarqubecloud
Copy link

sonarqubecloud bot commented Jan 2, 2026

@pavanimanchala53
Copy link
Contributor Author

Hi @Anshgrover23

can you review this

CodeQL is failing due to a repository configuration conflict
no CodeQL -related changes were made in this PR

Copy link
Collaborator

@Anshgrover23 Anshgrover23 left a comment

Choose a reason for hiding this comment

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

@pavanimanchala53 Follow Contributing.md guideliness i.e add a demonstration video.

Copy link
Collaborator

@Anshgrover23 Anshgrover23 left a comment

Choose a reason for hiding this comment

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

@pavanimanchala53 Missing test, docs, video. Do not attempt low quality PR reminding you again.
@mikejmorgan-ai I'm closing this one.
Feel free to open a new with all the changes,

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.

Natural Language Install: Polish and Edge Cases

2 participants