Skip to content

Conversation

@ShreeJejurikar
Copy link
Collaborator

@ShreeJejurikar ShreeJejurikar commented Dec 29, 2025

Related Issue

Closes #393

Summary

Enhances the existing cortex ask command to include tutor-like capabilities without adding a separate command or flag. The LLM automatically detects whether a question is educational or diagnostic and responds appropriately.

Changes:

  • Enhanced system prompt to detect educational vs diagnostic queries automatically
  • Added LearningTracker class to track educational topics explored by the user
  • Learning history stored in ~/.cortex/learning_history.json
  • Increased max_tokens from 500 to 2000 for longer educational responses
  • Added terminal-friendly formatting rules (no markdown headings that render poorly)
  • Rich Markdown rendering for proper terminal display
  • Added 25 new unit tests (50 total) for ask module
  • Updated COMMANDS.md with cortex ask documentation

Example usage:

# Educational queries - get structured tutorials
cortex ask "explain how Docker containers work"
cortex ask "best practices for nginx configuration"
cortex ask "teach me about systemd"

# Diagnostic queries - get system-specific answers
cortex ask "what version of Python do I have"
cortex ask "Am I in a virtual Environment?

AI Disclosure

  • No AI used
  • AI/IDE/Agents used (please describe below)

Used Claude Code for development assistance.

Checklist

  • PR title follows format: type(scope): description or [scope] description
  • Tests pass (pytest tests/)
  • MVP label added if closing MVP issue
  • Update "Cortex -h" (if needed)

Video Demonstration:

Screencast.from.12-01-26.10.42.51.AM.IST.webm

Summary by CodeRabbit

  • New Features

    • Learning history: detects educational queries, extracts topics, records persistent learning history, and exposes recent-topic/history retrieval.
  • Improvements

    • Dual-mode system prompts (Educational vs Diagnostic) with clearer output rules.
    • Longer AI responses supported (higher token allowance).
    • Terminal output now renders Markdown for improved readability.
    • Topics recorded for both cached and non-cached responses.
  • Documentation

    • Expanded command docs with examples and a Learning with Ask section.
  • Tests

    • Added tests for detection, topic recording, history persistence, and prompt behavior.

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

…ortexlinux#393)

- Enhanced system prompt to detect educational vs diagnostic queries
- Added LearningTracker class for tracking educational topics
- Learning history stored in ~/.cortex/learning_history.json
- Increased max_tokens from 500 to 2000 for longer responses
- Added terminal-friendly formatting rules
- Rich Markdown rendering for proper terminal display
- Added 25 new unit tests (50 total) for ask module
- Updated COMMANDS.md with cortex ask documentation
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 29, 2025

Important

Review skipped

Draft detected.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

📝 Walkthrough

Walkthrough

Adds a LearningTracker to detect, extract, and persist educational topics to ~/.cortex/learning_history.json, integrates it into AskHandler (public API + recording), expands the system prompt for Educational vs Diagnostic modes, raises OpenAI/Claude max_tokens to 2000, updates CLI to render Markdown, and adds docs and tests.

Changes

Cohort / File(s) Summary
Core Learning Feature
cortex/ask.py
Adds LearningTracker (regex-based educational detection, topic extraction, JSON-backed history at ~/.cortex/learning_history.json, load/save). Integrates into AskHandler via learning_tracker attribute, records topics for cached and fresh responses, adds get_learning_history() and get_recent_topics(), revises _get_system_prompt (Educational vs Diagnostic) and increases OpenAI/Claude max_tokens 500→2000.
CLI Rendering
cortex/cli.py
Uses rich.markdown.Markdown(...) to render cortex ask output instead of plain text.
Documentation
docs/COMMANDS.md
Adds cortex ask quick reference and expanded guidance on Diagnostic vs Educational queries, examples, and learning-history behavior.
Unit Tests
tests/test_ask.py
Adds tests for LearningTracker and AskHandler integration: detection, topic extraction, history persistence, recent topics, and system-prompt expectations; uses isolated temporary history path.
Metadata / Config
manifest_file, requirements.txt, pyproject.toml
Minor metadata/requirements adjustments referenced by the diff.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant AskHandler
    participant LearningTracker
    participant FileSystem as File System
    participant LLM as OpenAI/Claude

    User->>AskHandler: ask(question)
    AskHandler->>LearningTracker: is_educational_query(question)
    LearningTracker-->>AskHandler: true/false

    alt Educational
        AskHandler->>LearningTracker: extract_topic(question)
        LearningTracker-->>AskHandler: topic
        AskHandler->>LearningTracker: record_topic(question)
        LearningTracker->>FileSystem: _load_history()
        FileSystem-->>LearningTracker: history
        LearningTracker->>FileSystem: _save_history(updated_history)
    end

    AskHandler->>LLM: call with expanded system prompt + max_tokens=2000
    LLM-->>AskHandler: response
    AskHandler-->>User: return formatted Markdown response
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Suggested reviewers

  • mikejmorgan-ai
  • Suyashd999

Poem

🐰 I hop through questions, whiskers all aglow,
I find a lesson where curious minds go.
I tuck a topic in a tiny file,
So learners return and study awhile.
A rabbit's record — soft, patient, and slow.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The PR title clearly summarizes the main enhancement: adding interactive tutor capabilities to cortex ask, which aligns with the primary changes in adding LearningTracker, educational query detection, and related features.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering all required template sections: related issue (#393), detailed summary of changes, AI disclosure, and completed checklist items. All critical sections are properly filled.
Linked Issues check ✅ Passed The PR successfully implements all core requirements from issue #393: automatic intent detection via enhanced system prompt and LearningTracker [393], structured learning with increased max_tokens [393], learning history tracking and persistence [393], and examples demonstrating both educational and diagnostic queries [393].
Out of Scope Changes check ✅ Passed All changes are scoped to issue #393 objectives: LearningTracker class and AskHandler integration for learning tracking, enhanced system prompt for query-type detection, terminal formatting improvements via Markdown rendering, documentation updates, and comprehensive test coverage. No extraneous changes detected.
Docstring Coverage ✅ Passed Docstring coverage is 91.84% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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: 0

🧹 Nitpick comments (2)
cortex/ask.py (2)

172-200: Consider edge case in topic truncation logic.

Line 199 truncates topics to 50 characters at word boundaries using topic[:50].rsplit(" ", 1)[0]. If the first 50 characters contain no spaces, rsplit returns a single-element list, and [0] will return the full 50-character string, which is correct.

However, this could still result in awkwardly truncated topics for long compound words or URLs. Consider whether 50 characters is sufficient for your use cases.

Example edge case:

# Topic with no spaces in first 50 chars
topic = "verylongcompoundwordwithoutanyspacesthatexceeds50characters"
# Result: "verylongcompoundwordwithoutanyspacesthatexceeds50"

The current behavior is safe but might not be ideal for all inputs.


255-262: Silent failure on save may complicate debugging.

Line 262 silently suppresses OSError when writing the learning history file. While this prevents the CLI from crashing when the history file can't be written (e.g., permission issues, disk full), it makes debugging difficult if users expect their learning history to be tracked but it's failing silently.

Consider whether this trade-off aligns with your UX goals. For a "Chill" review mode, this is acceptable, but you might want to log these failures in verbose mode in the future.

Based on learnings from similar patterns in the codebase.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e95c874 and 8d13ebe.

📒 Files selected for processing (4)
  • cortex/ask.py
  • cortex/cli.py
  • docs/COMMANDS.md
  • tests/test_ask.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.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/cli.py
  • tests/test_ask.py
  • cortex/ask.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Maintain >80% test coverage for pull requests

Files:

  • tests/test_ask.py
🧬 Code graph analysis (1)
tests/test_ask.py (1)
cortex/ask.py (11)
  • ask (458-526)
  • LearningTracker (139-262)
  • SystemInfoGatherer (20-136)
  • is_educational_query (165-170)
  • extract_topic (172-200)
  • record_topic (202-225)
  • get_history (227-229)
  • get_recent_topics (231-242)
  • get_recent_topics (536-545)
  • gather_context (129-136)
  • _get_system_prompt (334-391)
⏰ 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). (4)
  • GitHub Check: Test (Python 3.10)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.10)
🔇 Additional comments (13)
cortex/cli.py (2)

9-10: LGTM! Appropriate import for Markdown rendering.

The import extends the existing Rich library usage to support formatted terminal output for the enhanced educational responses.


302-303: LGTM! Clean integration of Markdown rendering.

The change properly leverages Rich's Markdown class to render formatted educational responses in the terminal, aligning with the enhanced output formatting rules in the system prompt.

tests/test_ask.py (3)

273-396: Excellent test coverage for LearningTracker.

The test class comprehensively covers:

  • Educational query pattern detection across multiple patterns
  • Topic extraction with various prefixes
  • Truncation handling for long topics
  • History persistence and incremental updates
  • Non-educational query filtering

The use of temporary files and proper patching ensures test isolation.


398-460: LGTM! Strong integration tests for learning features.

The tests validate:

  • Educational queries are properly recorded through AskHandler
  • Diagnostic queries are correctly excluded from learning history
  • Recent topics retrieval works through the handler API
  • System prompt contains the necessary educational guidance

Good use of the fake provider to avoid external API dependencies.


462-493: Good validation of system prompt enhancements.

The tests ensure the enhanced system prompt includes:

  • Query type detection guidance
  • Educational response instructions with examples and best practices
  • Diagnostic response instructions with system context

This validates the PR's core objective of distinguishing between query types.

docs/COMMANDS.md (2)

75-132: Excellent documentation for the enhanced ask command.

The documentation clearly explains:

  • The dual nature of the command (diagnostic vs educational)
  • Automatic intent detection
  • System-aware responses and learning progress tracking
  • Practical examples for both query types

The feature list and notes provide users with a complete understanding of the command's capabilities.


429-445: Well-structured learning workflow section.

The workflow provides a clear progression:

  1. Diagnostic queries for system information
  2. Educational queries for learning
  3. Step-by-step tutorials
  4. Automatic tracking of learning history

This practical guide helps users understand and leverage the new capabilities.

cortex/ask.py (6)

1-17: LGTM! Clean import additions and updated docstring.

The new imports (re, datetime, Path) are from the standard library and support the learning tracking functionality. The docstring accurately reflects the expanded scope to include educational content and progress tracking.


139-170: Well-designed LearningTracker class with comprehensive patterns.

The class structure is solid:

  • Pre-compiled regex patterns for efficiency
  • Comprehensive educational query detection patterns
  • Case-insensitive matching appropriately handles user input variations

The pattern list covers the main educational query types mentioned in the PR objectives.


288-288: LGTM! Proper integration of LearningTracker.

The learning tracker is correctly instantiated in __init__, ensuring it's available for all ask operations.


334-391: Excellent system prompt design for dual-mode operation.

The enhanced system prompt effectively:

  • Distinguishes between educational and diagnostic query types with clear trigger patterns
  • Provides specific guidelines for each response type
  • Includes explicit output formatting rules to prevent terminal rendering issues
  • Provides a concrete example to guide the LLM

The level of detail is appropriate for ensuring consistent, high-quality responses across both query modes. The terminal-specific formatting rules (avoiding markdown headings, limiting line length) are particularly valuable.


401-401: Appropriate token increase for educational responses.

Increasing max_tokens from 500 to 2000 for both OpenAI and Claude is necessary to support the longer, structured educational responses with code examples and best practices. The 4x increase aligns with the PR's objective to provide comprehensive tutorials.

Note: This will increase API costs, but is appropriate for the enhanced functionality.

Also applies to: 413-413


523-545: Clean integration and well-designed public API.

The learning tracking integration:

  • Records topics at the appropriate point (after successful answer generation)
  • Exposes a clean public API through get_learning_history() and get_recent_topics()
  • Follows Python conventions with proper type hints and docstrings
  • Delegates appropriately to the LearningTracker instance

The API design allows external code to access learning history without tight coupling to the tracker implementation.

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.

@ShreeJejurikar Kindly Update your branch and merge with main. and follow contribution guidelines.

Copilot AI review requested due to automatic review settings January 5, 2026 20:36
@github-actions
Copy link

github-actions bot commented Jan 5, 2026

CLA Verification Passed

All contributors have signed the CLA.

Contributor Signed As
@ShreeJejurikar @ShreeJejurikar
@Suyashd999 @Suyashd999
@Anshgrover23 @Anshgrover23

Copy link
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 enhances the cortex ask command to automatically detect and respond appropriately to both educational and diagnostic queries, eliminating the need for a separate cortex tutor command. The system intelligently distinguishes between learning-focused questions (e.g., "explain how Docker works") and system-specific diagnostics (e.g., "why is my disk full"), providing structured tutorials with code examples for the former and actionable system information for the latter.

Key changes:

  • Added LearningTracker class to detect educational queries using regex patterns and persist learning history to ~/.cortex/learning_history.json
  • Enhanced system prompt with query type detection instructions and terminal-friendly formatting guidelines
  • Increased max_tokens from 500 to 2000 to accommodate longer educational responses
  • Added 25 new unit tests for learning tracker functionality

Reviewed changes

Copilot reviewed 4 out of 4 changed files in this pull request and generated 5 comments.

File Description
cortex/ask.py Implemented LearningTracker class for educational query detection and history tracking; enhanced system prompt with dual-mode instructions; increased token limits
cortex/cli.py Added Rich Markdown rendering for properly formatted terminal output
tests/test_ask.py Added comprehensive test coverage for LearningTracker class and enhanced system prompt validation
docs/COMMANDS.md Added cortex ask command documentation with examples of diagnostic and educational queries; included learning history feature description

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

docs/COMMANDS.md Outdated

**Notes:**
- Educational responses are longer and include code examples with syntax highlighting
- The `--offline` flag can be used to only return cached responses
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

The documentation mentions an --offline flag, but this flag is not actually implemented in the CLI argument parser for the ask command. The ask command only accepts a question argument and has no optional flags defined. Either implement the --offline flag functionality or remove this reference from the documentation.

Suggested change
- The `--offline` flag can be used to only return cached responses

Copilot uses AI. Check for mistakes.
cortex/ask.py Outdated
Comment on lines 198 to 201
if len(topic) > 50:
topic = topic[:50].rsplit(" ", 1)[0]
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

There's an edge case bug in the topic truncation logic. When a topic is exactly 50 characters long, calling rsplit(" ", 1) will split it and return only the first part, potentially removing the last word unnecessarily. The condition should check if the topic is greater than 50 characters before attempting truncation, or the rsplit should only be applied after confirming there's content beyond 50 characters.

Copilot uses AI. Check for mistakes.
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

@copilot open a new pull request to apply changes based on this feedback

def test_is_educational_query_best_practices(self):
"""Test detection of 'best practices' queries."""
self.assertTrue(self.tracker.is_educational_query("best practices for security"))
self.assertTrue(self.tracker.is_educational_query("what are best practice for nginx"))
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

Spelling error: "practice" should be "practices" to match the plural form used elsewhere in the documentation and code.

Suggested change
self.assertTrue(self.tracker.is_educational_query("what are best practice for nginx"))
self.assertTrue(self.tracker.is_educational_query("what are best practices for nginx"))

Copilot uses AI. Check for mistakes.
cortex/ask.py Outdated
Comment on lines 337 to 371
## Query Type Detection
Automatically detect the type of question and respond appropriately:
### Educational Questions (tutorials, explanations, learning)
Triggered by questions like: "explain...", "teach me...", "how does X work", "what is...", "best practices for...", "tutorial on...", "learn about...", "guide to..."
For educational questions:
1. Provide structured, tutorial-style explanations
2. Include practical code examples with proper formatting
3. Highlight best practices and common pitfalls to avoid
4. Break complex topics into digestible sections
5. Use clear section labels and bullet points for readability
6. Mention related topics the user might want to explore next
7. Tailor examples to the user's system when relevant (e.g., use apt for Debian-based systems)
### Diagnostic Questions (system-specific, troubleshooting)
Triggered by questions about: current system state, "why is my...", "what packages...", "check my...", specific errors, system status
For diagnostic questions:
1. Analyze the provided system context
2. Give specific, actionable answers
3. Be concise but informative
4. If you don't have enough information, say so clearly
5. For package compatibility questions, consider the system's Python version and OS
6. Return ONLY the answer text, no JSON or markdown formatting"""
## Output Formatting Rules (CRITICAL - Follow exactly)
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

The system prompt contains markdown headings (## Query Type Detection, ### Educational Questions, ### Diagnostic Questions, ## Output Formatting Rules) despite instructing the LLM in the "Output Formatting Rules" section to "NEVER use markdown headings (# or ##) - they render poorly in terminals". While these headings are for organizing the system prompt itself (not the LLM's output), this inconsistency could confuse the model or make it less likely to follow the formatting rules. Consider using bold text for these section titles in the system prompt as well, to demonstrate the desired formatting style.

Copilot uses AI. Check for mistakes.
@@ -1,14 +1,16 @@
"""Unit tests for the ask module."""

import json
Copy link

Copilot AI Jan 5, 2026

Choose a reason for hiding this comment

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

Import of 'json' is not used.

Suggested change
import json

Copilot uses AI. Check for mistakes.
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: 0

🧹 Nitpick comments (3)
cortex/ask.py (3)

139-163: Consider making compiled patterns a class variable.

The _compiled_patterns list is recompiled for every LearningTracker instance, but since EDUCATIONAL_PATTERNS is static, the compiled patterns could be shared across all instances.

🔎 Proposed refactor
 class LearningTracker:
     """Tracks educational topics the user has explored."""
 
     PROGRESS_FILE = Path.home() / ".cortex" / "learning_history.json"
 
     # Patterns that indicate educational questions
     EDUCATIONAL_PATTERNS = [
         r"^explain\b",
         r"^teach\s+me\b",
         r"^what\s+is\b",
         r"^what\s+are\b",
         r"^how\s+does\b",
         r"^how\s+do\b",
         r"^how\s+to\b",
         r"\bbest\s+practices?\b",
         r"^tutorial\b",
         r"^guide\s+to\b",
         r"^learn\s+about\b",
         r"^introduction\s+to\b",
         r"^basics\s+of\b",
     ]
+    _COMPILED_PATTERNS = [re.compile(p, re.IGNORECASE) for p in EDUCATIONAL_PATTERNS]
 
     def __init__(self):
         """Initialize the learning tracker."""
-        self._compiled_patterns = [re.compile(p, re.IGNORECASE) for p in self.EDUCATIONAL_PATTERNS]
+        pass  # No instance-specific initialization needed
 
     def is_educational_query(self, question: str) -> bool:
         """Determine if a question is educational in nature."""
-        for pattern in self._compiled_patterns:
+        for pattern in self._COMPILED_PATTERNS:
             if pattern.search(question):
                 return True
         return False

172-200: Consider clarifying topic truncation logic.

The truncation logic at lines 198-199 works correctly but could be more explicit about its intent to truncate at word boundaries.

🔎 Proposed clarification
     # Clean up and truncate
     topic = topic.strip("? ").strip()
-    # Take first 50 chars as topic identifier
     if len(topic) > 50:
+        # Truncate at word boundary to avoid splitting words
         topic = topic[:50].rsplit(" ", 1)[0]
     return topic

202-225: Consider using timezone-aware timestamps.

Lines 216 and 221 use datetime.now().isoformat() which creates naive (timezone-unaware) timestamps. For better consistency and sorting accuracy, consider using UTC timestamps.

🔎 Proposed improvement
+from datetime import datetime, timezone

 def record_topic(self, question: str) -> None:
     """Record that the user explored an educational topic."""
     if not self.is_educational_query(question):
         return
 
     topic = self.extract_topic(question)
     if not topic:
         return
 
     history = self._load_history()
 
     # Update or add topic
     if topic in history["topics"]:
         history["topics"][topic]["count"] += 1
-        history["topics"][topic]["last_accessed"] = datetime.now().isoformat()
+        history["topics"][topic]["last_accessed"] = datetime.now(timezone.utc).isoformat()
     else:
         history["topics"][topic] = {
             "count": 1,
-            "first_accessed": datetime.now().isoformat(),
-            "last_accessed": datetime.now().isoformat(),
+            "first_accessed": datetime.now(timezone.utc).isoformat(),
+            "last_accessed": datetime.now(timezone.utc).isoformat(),
         }
 
     history["total_queries"] = history.get("total_queries", 0) + 1
     self._save_history(history)
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 8d13ebe and 1dce8ea.

📒 Files selected for processing (4)
  • cortex/ask.py
  • cortex/cli.py
  • docs/COMMANDS.md
  • tests/test_ask.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • cortex/cli.py
  • docs/COMMANDS.md
🧰 Additional context used
📓 Path-based instructions (2)
**/*.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:

  • tests/test_ask.py
  • cortex/ask.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Maintain >80% test coverage for pull requests

Files:

  • tests/test_ask.py
🧬 Code graph analysis (1)
tests/test_ask.py (2)
cortex/ask.py (9)
  • ask (455-520)
  • SystemInfoGatherer (20-136)
  • record_topic (202-225)
  • get_history (227-229)
  • get_recent_topics (231-242)
  • get_recent_topics (530-539)
  • get_learning_history (522-528)
  • gather_context (129-136)
  • _get_system_prompt (331-388)
cortex/llm/interpreter.py (1)
  • _get_system_prompt (123-157)
⏰ 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). (1)
  • GitHub Check: Agent
🔇 Additional comments (9)
cortex/ask.py (6)

11-11: LGTM! Imports are appropriate.

The new imports (re, datetime, Path) are all used by the LearningTracker class and follow proper import conventions.

Also applies to: 15-16


285-285: LGTM! Clean integration of learning tracker.

The LearningTracker is properly instantiated in __init__, maintaining good separation of concerns.


331-388: LGTM! Comprehensive system prompt enhancements.

The enhanced system prompt effectively distinguishes between educational and diagnostic queries with clear formatting rules. The terminal-friendly formatting guidelines (avoiding markdown headings, using bold for sections) are well thought out.


398-398: LGTM! Appropriate token limit increase.

Increasing max_tokens from 500 to 2000 is justified for educational responses that require structured tutorials and code examples.

Also applies to: 410-410


517-519: LGTM! Proper placement of topic recording.

Recording the topic after the response is generated and cached is the correct approach, as it only tracks successful queries.


522-539: LGTM! Well-documented public API.

Both methods follow coding guidelines with proper type hints and docstrings. The delegation pattern to learning_tracker maintains good encapsulation.

tests/test_ask.py (3)

265-388: LGTM! Comprehensive test coverage for LearningTracker.

The test class thoroughly covers:

  • Educational query pattern detection (multiple trigger phrases)
  • Topic extraction with various prefixes
  • Edge cases like truncation and empty states
  • Persistence and data integrity
  • Proper isolation using temp files and patching

The tests are well-structured with clear naming and proper setup/teardown.


390-451: LGTM! Solid integration tests for learning features.

The tests properly verify the integration between AskHandler and LearningTracker:

  • Educational topics are recorded through the ask() method
  • Diagnostic queries are correctly ignored
  • Public API methods work as expected
  • System prompt content is validated

Using the fake provider and disabling cache ensures fast, deterministic tests.


454-485: LGTM! System prompt validation tests.

These tests verify that the enhanced system prompt contains the necessary instructions for both educational and diagnostic queries. The tests appropriately check for key phrases that indicate the prompt's intent.

Note: These tests validate prompt content directly, which means they may need updates if prompt wording changes, but this is acceptable for ensuring the educational feature works as designed.

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

🤖 Fix all issues with AI agents
In @cortex/ask.py:
- Around line 526-529: The issue is that
self.learning_tracker.record_topic(question) is only called after generating
non-cached answers, so cached hits (returned around the earlier cache return)
never update last_accessed/count; move the call to
self.learning_tracker.record_topic(question) so it runs for every access—either
invoke it immediately before the cache lookup/early-return (so both cache hits
and misses are recorded) or call it right before any early return that returns a
cached response (ensure it executes in the same function/method where the cache
is checked, preserving the original variable names like cached_answer/cache_hit
and the existing return behavior).
🧹 Nitpick comments (3)
cortex/ask.py (2)

163-165: Missing docstring content.

Per coding guidelines, docstrings are required for all public APIs. The __init__ method has a docstring but it's minimal. Consider adding a brief note about pattern compilation.


257-264: Consider logging on save failure for debuggability.

Silent failure when unable to write learning history (pass on line 264) is reasonable for CLI UX, but makes diagnosing permission or disk issues difficult. Consider adding debug-level logging if a logger is available.

tests/test_ask.py (1)

417-468: Consider cleaning up CORTEX_FAKE_RESPONSE in tearDown.

Tests set os.environ["CORTEX_FAKE_RESPONSE"] but don't clean it up. This could cause test pollution if test order changes or new tests are added. Consider adding cleanup in tearDown or using unittest.mock.patch.dict.

Proposed fix
     def setUp(self):
         """Set up test fixtures."""
         self.temp_dir = tempfile.mkdtemp()
         self.temp_file = Path(self.temp_dir) / "learning_history.json"
         self.patcher = patch.object(LearningTracker, "PROGRESS_FILE", self.temp_file)
         self.patcher.start()
+        self._original_fake_response = os.environ.get("CORTEX_FAKE_RESPONSE")

     def tearDown(self):
         """Clean up temporary files."""
         import shutil

         self.patcher.stop()
+        if self._original_fake_response is not None:
+            os.environ["CORTEX_FAKE_RESPONSE"] = self._original_fake_response
+        else:
+            os.environ.pop("CORTEX_FAKE_RESPONSE", None)
         if os.path.exists(self.temp_dir):
             shutil.rmtree(self.temp_dir)
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 1dce8ea and adb1d14.

📒 Files selected for processing (4)
  • cortex/ask.py
  • cortex/cli.py
  • docs/COMMANDS.md
  • tests/test_ask.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • cortex/cli.py
  • docs/COMMANDS.md
🧰 Additional context used
📓 Path-based instructions (2)
**/*.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:

  • tests/test_ask.py
  • cortex/ask.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Maintain >80% test coverage for pull requests

Files:

  • tests/test_ask.py
⏰ 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). (4)
  • GitHub Check: Test (Python 3.11)
  • GitHub Check: test (3.10)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.12)
🔇 Additional comments (7)
cortex/ask.py (4)

1-17: LGTM!

Module docstring and imports are appropriately updated to reflect the new educational capabilities.


287-287: LGTM!

Clean integration of LearningTracker into AskHandler.


406-408: Verify cost implications of 4x token increase.

Increasing max_tokens from 500 to 2000 is appropriate for educational content but increases potential API costs. Ensure this aligns with expected usage patterns and cost budgets.

Also applies to: 418-420


531-548: LGTM!

Well-documented public APIs with proper type hints and docstrings. Clean delegation to LearningTracker.

tests/test_ask.py (3)

292-311: Good test isolation with temporary directory and patched PROGRESS_FILE.

The setup properly isolates tests from the real learning history file, and teardown ensures cleanup.


481-512: LGTM!

Good test coverage for the enhanced system prompt content, verifying presence of key sections and instructions.


292-512: Comprehensive test coverage for new learning features.

The 25 new tests thoroughly cover:

  • Educational query detection patterns
  • Topic extraction logic
  • History persistence and retrieval
  • Integration with AskHandler
  • System prompt content validation

Good adherence to the >80% coverage guideline for new functionality.

@mikejmorgan-ai mikejmorgan-ai self-assigned this Jan 10, 2026
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: 0

🧹 Nitpick comments (4)
cortex/ask.py (4)

163-165: Missing return type hint on __init__.

Per coding guidelines, type hints are required. Add -> None return type.

-    def __init__(self):
+    def __init__(self) -> None:
         """Initialize the learning tracker."""
         self._compiled_patterns = [re.compile(p, re.IGNORECASE) for p in self.EDUCATIONAL_PATTERNS]

251-253: Specify explicit encoding for file operations.

Reading JSON without explicit encoding may cause issues on systems where the default encoding is not UTF-8. The same applies to the write operation on line 261.

Suggested fix
-            with open(self.PROGRESS_FILE) as f:
+            with open(self.PROGRESS_FILE, encoding="utf-8") as f:
                 return json.load(f)

And for _save_history:

-            with open(self.PROGRESS_FILE, "w") as f:
+            with open(self.PROGRESS_FILE, "w", encoding="utf-8") as f:
                 json.dump(history, f, indent=2)

144-144: Consider lazy initialization of PROGRESS_FILE for robustness in containerized environments.

Path.home() is evaluated at class definition time, which could raise RuntimeError in environments where HOME is not set (e.g., some containers). While this pattern is used consistently throughout the codebase, consider making this a property or initializing in __init__ for improved compatibility.


431-451: Add num_predict: 2000 to Ollama options for token limit consistency.

OpenAI and Claude both use max_tokens=2000, but _call_ollama doesn't specify a token limit (Ollama defaults to unlimited generation). For consistency across all three providers, add num_predict: 2000 to the Ollama options.

Suggested change
         data = json.dumps(
             {
                 "model": self.model,
                 "prompt": prompt,
                 "stream": False,
-                "options": {"temperature": 0.3},
+                "options": {"temperature": 0.3, "num_predict": 2000},
             }
         ).encode("utf-8")
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between adb1d14 and c553df7.

📒 Files selected for processing (1)
  • cortex/ask.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/ask.py
⏰ 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). (4)
  • GitHub Check: Build Package
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.10)
🔇 Additional comments (2)
cortex/ask.py (2)

496-498: LGTM!

Good to track topic access even for cached responses - this correctly reflects user engagement with educational topics over time, not just unique queries.


533-550: LGTM!

Clean delegation methods with proper type hints and docstrings as required by the coding guidelines.

Record topic access even when returning cached responses to ensure
last_accessed timestamps and counts are updated correctly.
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

🤖 Fix all issues with AI agents
In @cortex/ask.py:
- Around line 141-165: PROGRESS_FILE is computed at import time which can raise
RuntimeError in restricted envs; change it to lazy initialization by removing
the module-level Path.home() usage and implement a property or cached_property
on LearningTracker (e.g., progress_file) that computes Path.home() / ".cortex" /
"learning_history.json" inside a try/except, falling back to a safe location
(like tempfile.gettempdir() or Path.cwd()) and ensuring parent dirs are created;
update methods that reference PROGRESS_FILE to use the new progress_file
property and add minimal error handling/logging when home is inaccessible.
🧹 Nitpick comments (2)
cortex/ask.py (2)

167-172: Consider using any() for more idiomatic Python.

The loop can be simplified using any() for improved readability.

Suggested refactor
     def is_educational_query(self, question: str) -> bool:
         """Determine if a question is educational in nature."""
-        for pattern in self._compiled_patterns:
-            if pattern.search(question):
-                return True
-        return False
+        return any(pattern.search(question) for pattern in self._compiled_patterns)

257-264: Silent failure on save may hide persistent issues.

While silent failure keeps CLI output clean, users won't know if their learning history is never being saved (e.g., due to permissions). Consider logging at debug level or surfacing persistent failures after repeated attempts.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between c553df7 and aea5339.

📒 Files selected for processing (1)
  • cortex/ask.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/ask.py
⏰ 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). (4)
  • GitHub Check: Test (Python 3.10)
  • GitHub Check: test (3.10)
  • GitHub Check: test (3.12)
  • GitHub Check: test (3.11)
🔇 Additional comments (7)
cortex/ask.py (7)

1-17: LGTM!

The module docstring accurately reflects the expanded scope, and the new imports (re, datetime, Path) are appropriately added for the LearningTracker functionality.


204-227: LGTM!

The method has proper guard clauses for non-educational queries and empty topics. The history update logic correctly handles both new and existing topics.


287-287: LGTM!

The LearningTracker integration into AskHandler.__init__ is clean and follows the existing initialization pattern.


340-397: Well-structured dual-mode system prompt.

The enhanced prompt effectively guides the LLM to distinguish between educational and diagnostic queries, with clear formatting rules for terminal-friendly output. The example formatting section is a good practice for LLM instruction.


407-407: max_tokens increase supports longer educational responses.

The 4x increase from 500 to 2000 tokens aligns with the PR objective to enable tutorial-style content. Be aware this may increase API costs and response latency for commercial providers.

Also applies to: 419-419


496-498: LGTM!

Topic tracking is correctly integrated in both the cache-hit and fresh-response paths. The record_topic method internally filters non-educational queries, so calling it unconditionally is appropriate.

Also applies to: 528-529


533-550: LGTM!

The new public API methods are well-documented with proper docstrings and type hints. They provide clean access to learning history functionality at the AskHandler level.

cortex/ask.py Outdated
Comment on lines 141 to 165
class LearningTracker:
"""Tracks educational topics the user has explored."""

PROGRESS_FILE = Path.home() / ".cortex" / "learning_history.json"

# Patterns that indicate educational questions
EDUCATIONAL_PATTERNS = [
r"^explain\b",
r"^teach\s+me\b",
r"^what\s+is\b",
r"^what\s+are\b",
r"^how\s+does\b",
r"^how\s+do\b",
r"^how\s+to\b",
r"\bbest\s+practices?\b",
r"^tutorial\b",
r"^guide\s+to\b",
r"^learn\s+about\b",
r"^introduction\s+to\b",
r"^basics\s+of\b",
]

def __init__(self):
"""Initialize the learning tracker."""
self._compiled_patterns = [re.compile(p, re.IGNORECASE) for p in self.EDUCATIONAL_PATTERNS]
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 12, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Path.home() evaluated at class definition may fail in restricted environments.

PROGRESS_FILE is evaluated at import time. If HOME is unset or inaccessible (e.g., containerized/sandboxed environments), Path.home() raises RuntimeError, crashing the import. Consider lazy initialization or wrapping in a property/method with error handling.

Suggested fix using a cached property
 class LearningTracker:
     """Tracks educational topics the user has explored."""

-    PROGRESS_FILE = Path.home() / ".cortex" / "learning_history.json"
+    _progress_file: Path | None = None

+    @classmethod
+    def _get_progress_file(cls) -> Path | None:
+        """Get the progress file path, handling missing HOME gracefully."""
+        if cls._progress_file is None:
+            try:
+                cls._progress_file = Path.home() / ".cortex" / "learning_history.json"
+            except RuntimeError:
+                return None
+        return cls._progress_file
🤖 Prompt for AI Agents
In @cortex/ask.py around lines 141 - 165, PROGRESS_FILE is computed at import
time which can raise RuntimeError in restricted envs; change it to lazy
initialization by removing the module-level Path.home() usage and implement a
property or cached_property on LearningTracker (e.g., progress_file) that
computes Path.home() / ".cortex" / "learning_history.json" inside a try/except,
falling back to a safe location (like tempfile.gettempdir() or Path.cwd()) and
ensuring parent dirs are created; update methods that reference PROGRESS_FILE to
use the new progress_file property and add minimal error handling/logging when
home is inaccessible.

✅ Addressed in commit 11e7b35

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

🤖 Fix all issues with AI agents
In @docs/COMMANDS.md:
- Around line 76-133: Docs mention a --offline flag for the cortex ask command
but the CLI parser (cortex/cli.py) and AskHandler.ask() don't support it; either
remove the doc line or implement the flag. To implement: add an optional boolean
--offline/--no-offline flag to the ask command definition in cortex/cli.py that
sets a parameter (e.g., offline: bool) and pass that value when invoking
AskHandler.ask; update AskHandler.ask(signature) to accept an offline: bool
parameter and branch its behavior to only use cached responses when offline is
true (or raise an informative error if caching isn't available). Ensure help
text and COMMANDS.md are consistent with the new flag.
🧹 Nitpick comments (1)
cortex/ask.py (1)

204-227: Consider thread safety for concurrent file access.

The record_topic method performs a read-modify-write cycle on the history file without locking. If multiple cortex ask processes run concurrently, this could lead to lost updates. Given this is a CLI tool where concurrent invocations are rare and learning history is non-critical, this is acceptable for now.

📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between aea5339 and f4abbed.

📒 Files selected for processing (4)
  • cortex/ask.py
  • cortex/cli.py
  • docs/COMMANDS.md
  • tests/test_ask.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.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/cli.py
  • cortex/ask.py
  • tests/test_ask.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Maintain >80% test coverage for pull requests

Files:

  • tests/test_ask.py
🧬 Code graph analysis (1)
tests/test_ask.py (1)
cortex/ask.py (13)
  • ask (464-531)
  • AskHandler (267-550)
  • LearningTracker (141-264)
  • SystemInfoGatherer (22-138)
  • is_educational_query (167-172)
  • extract_topic (174-202)
  • record_topic (204-227)
  • get_history (229-231)
  • get_recent_topics (233-244)
  • get_recent_topics (541-550)
  • get_learning_history (533-539)
  • gather_context (131-138)
  • _get_system_prompt (340-397)
⏰ 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). (4)
  • GitHub Check: Build Package
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.10)
  • GitHub Check: test (3.12)
🔇 Additional comments (24)
cortex/cli.py (2)

9-10: LGTM!

Import correctly added to enable Markdown rendering for ask command responses.


617-618: LGTM!

The Markdown rendering correctly formats the LLM response for terminal display, aligning with the enhanced system prompt that instructs the LLM to use terminal-friendly formatting (bold text, code blocks, etc.).

cortex/ask.py (12)

4-6: LGTM!

Module docstring properly updated to reflect the new educational content and learning progress tracking capabilities.


11-16: LGTM!

Necessary imports added for the new LearningTracker functionality: re for pattern matching, datetime for timestamps, and Path for file operations.


141-165: LGTM!

The LearningTracker class is well-structured with:

  • Clear docstring explaining its purpose
  • Sensible file location (~/.cortex/learning_history.json)
  • Comprehensive regex patterns for educational query detection
  • Pre-compiled patterns for better performance

167-172: LGTM!

Educational query detection correctly iterates through compiled patterns and returns on first match for efficiency.


174-202: LGTM!

Topic extraction logic is sound:

  • Removes common educational prefixes to isolate the actual topic
  • Properly handles truncation for long topics (50 char limit)
  • Uses word-boundary-aware truncation (rsplit(" ", 1)[0]) to avoid cutting mid-word

246-264: LGTM!

File I/O methods have appropriate error handling:

  • _load_history returns sensible defaults on missing file or parse errors
  • _save_history creates parent directories and silently fails on write errors to avoid disrupting the user experience

287-287: LGTM!

LearningTracker is properly initialized as a public attribute in AskHandler.__init__, enabling the learning history features.


340-397: Well-designed system prompt enhancement.

The prompt effectively:

  • Distinguishes between educational and diagnostic queries with clear trigger examples
  • Provides structured guidance for each response type
  • Includes critical terminal formatting rules (avoiding # headings, using bold instead)
  • Shows a concrete formatting example

This aligns well with the PR objective of automatic intent detection.


407-407: Verify token increase impact on API costs.

The max_tokens increase from 500 to 2000 (4x) for OpenAI will proportionally increase costs for educational responses. This is intentional per the PR objectives, but ensure users are aware of potential cost implications.


419-419: LGTM!

Matching max_tokens increase for Claude provider to maintain consistent behavior across providers.


496-498: LGTM!

Correctly tracks topic access even for cached responses, ensuring learning history remains accurate regardless of cache hits.


528-550: LGTM!

  • Topic tracking for non-cached responses is correctly placed after the LLM call
  • New public API methods get_learning_history() and get_recent_topics() are properly documented with docstrings and type hints, as per coding guidelines
docs/COMMANDS.md (2)

11-11: LGTM!

Quick reference updated with clear, concise description of the enhanced cortex ask functionality.


525-541: LGTM!

The "Learning with Cortex Ask" workflow section provides a clear, practical guide for users, demonstrating the progression from diagnostic queries to educational content, with a helpful note about automatic learning history tracking.

tests/test_ask.py (8)

3-3: LGTM!

Import added for JSON operations used in learning history tests.


13-13: LGTM!

LearningTracker correctly imported alongside existing AskHandler and SystemInfoGatherer imports.


292-311: LGTM!

Test fixture setup properly:

  • Uses tempfile.mkdtemp() for isolated test directory
  • Patches LearningTracker.PROGRESS_FILE to use temp location
  • Cleans up in tearDown with proper error handling for Windows

312-346: LGTM!

Comprehensive test coverage for is_educational_query:

  • Tests all major educational patterns (explain, teach me, what is, how does, best practices, tutorial)
  • Includes negative test cases for diagnostic queries
  • Good variety of case sensitivity tests

347-367: LGTM!

Good topic extraction tests covering prefix removal and truncation behavior.


368-415: LGTM!

Solid tests for record_topic and related functionality:

  • File creation verification
  • Data storage correctness
  • Count increment on repeated topics
  • Non-educational query filtering
  • Recent topics retrieval with ordering
  • Total queries tracking

417-478: LGTM!

Integration tests properly verify AskHandler's learning features:

  • Educational topics are recorded after ask
  • Diagnostic questions don't pollute learning history
  • get_recent_topics API works through handler
  • System prompt contains expected educational/diagnostic instructions

481-512: LGTM!

System prompt enhancement tests verify the prompt contains:

  • Query type detection section
  • Educational trigger phrases
  • Code examples and best practices guidance
  • System context and actionable response instructions

Comment on lines 76 to 133
### `cortex ask`

Ask natural language questions about your system or learn about Linux, packages, and best practices. The AI automatically detects whether you're asking a diagnostic question about your system or an educational question to learn something new.

**Usage:**
```bash
cortex ask "<question>"
```

**Question Types:**

**Diagnostic Questions** - Questions about your specific system:
```bash
# System status queries
cortex ask "why is my disk full"
cortex ask "what packages need updating"
cortex ask "is my Python version compatible with TensorFlow"
cortex ask "check my GPU drivers"
```

**Educational Questions** - Learn about Linux, packages, and best practices:
```bash
# Explanations and tutorials
cortex ask "explain how Docker containers work"
cortex ask "what is systemd and how do I use it"
cortex ask "teach me about nginx configuration"
cortex ask "best practices for securing a Linux server"
cortex ask "how to set up a Python virtual environment"
```

**Features:**
- **Automatic Intent Detection**: The AI distinguishes between diagnostic and educational queries
- **System-Aware Responses**: Uses your actual system context (OS, Python version, GPU, etc.)
- **Structured Learning**: Educational responses include examples, best practices, and related topics
- **Learning Progress Tracking**: Educational topics you explore are tracked in `~/.cortex/learning_history.json`
- **Response Caching**: Repeated questions return cached responses for faster performance

**Examples:**
```bash
# Diagnostic: Get specific info about your system
cortex ask "what version of Python do I have"
cortex ask "can I run PyTorch on this system"

# Educational: Learn with structured tutorials
cortex ask "explain how apt package management works"
cortex ask "what are best practices for Docker security"
cortex ask "guide to setting up nginx as a reverse proxy"

# Mix of both
cortex ask "how do I install and configure Redis"
```

**Notes:**
- Educational responses are longer and include code examples with syntax highlighting
- The `--offline` flag can be used to only return cached responses
- Learning history helps track what topics you've explored over time

---
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Search for --offline flag references in Python files
echo "=== Searching for --offline in cortex/cli.py ===" 
rg -n '\-\-offline' cortex/cli.py

echo -e "\n=== Searching for offline in cortex/ask.py ===" 
rg -n 'offline' cortex/ask.py

echo -e "\n=== Checking cortex/cli.py around lines 1748-1749 ===" 
if [ -f cortex/cli.py ]; then
  sed -n '1740,1760p' cortex/cli.py
fi

echo -e "\n=== Checking if cortex/ask.py exists ===" 
if [ -f cortex/ask.py ]; then
  wc -l cortex/ask.py
else
  echo "cortex/ask.py not found"
  # Try to find similar files
  find . -name "*ask*" -type f | head -20
fi

Repository: cortexlinux/cortex

Length of output: 1270


🏁 Script executed:

#!/bin/bash
# Find the ask command parser definition
echo "=== Searching for ask command subparser definition ===" 
rg -n "ask" cortex/cli.py | grep -i "subparser\|add_parser\|argument" | head -20

echo -e "\n=== Searching for ask in cortex/cli.py ===" 
rg -n "add_parser.*ask|subparsers.*ask" cortex/cli.py

echo -e "\n=== Checking cortex/ask.py around line 475 ===" 
sed -n '470,490p' cortex/ask.py

echo -e "\n=== Checking entire ask command definition in cli.py ===" 
rg -B5 -A10 "ask.*command|def.*ask" cortex/cli.py | head -50

echo -e "\n=== Checking COMMANDS.md line 130 ===" 
if [ -f docs/COMMANDS.md ]; then
  sed -n '125,135p' docs/COMMANDS.md
fi

Repository: cortexlinux/cortex

Length of output: 2036


🏁 Script executed:

#!/bin/bash
# Get full ask_parser definition
echo "=== Full ask_parser definition in cli.py ===" 
sed -n '2137,2160p' cortex/cli.py

echo -e "\n=== Check ask function signature ===" 
rg -A5 "def ask\(self" cortex/cli.py | head -20

echo -e "\n=== Search for offline usage in cortex/ask.py ===" 
rg -B3 -A3 "offline" cortex/ask.py

echo -e "\n=== Check how ask command calls handler ===" 
rg -A15 "def ask\(self, question" cortex/cli.py | head -40

Repository: cortexlinux/cortex

Length of output: 2269


🏁 Script executed:

#!/bin/bash
# Check AskHandler.ask() method signature
echo "=== AskHandler.ask() method definition ===" 
rg -B2 -A20 "class AskHandler" cortex/ask.py | head -30

echo -e "\n=== ask() method in AskHandler ===" 
rg -B2 -A15 "def ask\(self, question" cortex/ask.py

Repository: cortexlinux/cortex

Length of output: 1345


Correct documentation or implement the --offline flag for the ask command.

Line ~131 of the documentation states: "The --offline flag can be used to only return cached responses"

However, the ask command parser in cortex/cli.py (lines 2137-2138) only defines question as a positional argument with no --offline option. The AskHandler.ask() method also does not accept an offline parameter. Either implement the flag or remove this documentation.

🤖 Prompt for AI Agents
In @docs/COMMANDS.md around lines 76 - 133, Docs mention a --offline flag for
the cortex ask command but the CLI parser (cortex/cli.py) and AskHandler.ask()
don't support it; either remove the doc line or implement the flag. To
implement: add an optional boolean --offline/--no-offline flag to the ask
command definition in cortex/cli.py that sets a parameter (e.g., offline: bool)
and pass that value when invoking AskHandler.ask; update
AskHandler.ask(signature) to accept an offline: bool parameter and branch its
behavior to only use cached responses when offline is true (or raise an
informative error if caching isn't available). Ensure help text and COMMANDS.md
are consistent with the new flag.

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

🤖 Fix all issues with AI agents
In @cortex/ask.py:
- Around line 1-6: The file cortex/ask.py fails Black formatting in CI; run the
formatter (black .) locally or apply Black's rules to reformat cortex/ask.py
(and any other changed files), ensure the module docstring and surrounding code
conform to Black's line-length and string conventions, then stage and commit the
reformatted file(s) so CI picks up the updated, Black-compliant version.
🧹 Nitpick comments (2)
cortex/ask.py (1)

163-166: Add type hint for _compiled_patterns.

Per coding guidelines, type hints are required. Consider adding the type annotation:

 def __init__(self):
     """Initialize the learning tracker."""
-    self._compiled_patterns = [re.compile(p, re.IGNORECASE) for p in self.EDUCATIONAL_PATTERNS]
+    self._compiled_patterns: list[re.Pattern[str]] = [
+        re.compile(p, re.IGNORECASE) for p in self.EDUCATIONAL_PATTERNS
+    ]
tests/test_ask.py (1)

292-413: Consider adding edge case tests for error handling.

The LearningTracker handles corrupted JSON files and inaccessible home directories, but these paths aren't tested. Consider adding tests for:

  • _load_history with malformed JSON (should return empty dict)
  • progress_file fallback when Path.home() raises RuntimeError
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between b2a74f4 and dd254a3.

📒 Files selected for processing (2)
  • cortex/ask.py
  • tests/test_ask.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.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:

  • tests/test_ask.py
  • cortex/ask.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Maintain >80% test coverage for pull requests

Files:

  • tests/test_ask.py
🪛 GitHub Actions: CI
cortex/ask.py

[error] 1-1: Black formatting check failed. 1 file would be reformatted. Run 'black .' to fix formatting.


[error] 1-1: Command failed with exit code 1.

⏰ 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.12)
  • GitHub Check: test (3.11)
  • GitHub Check: test (3.10)
🔇 Additional comments (14)
cortex/ask.py (7)

186-214: LGTM!

The topic extraction logic handles prefixes cleanly, and the truncation at 50 characters using rsplit preserves word boundaries appropriately.


216-239: LGTM!

The topic recording logic correctly handles both new and existing topics with proper timestamp tracking.


269-276: LGTM!

Silent failure on save is acceptable for non-critical learning history. Creating parent directories defensively is good practice.


352-409: Well-designed dual-mode system prompt.

The prompt structure clearly delineates educational vs. diagnostic handling with concrete examples and terminal-friendly formatting rules. The example formatting section helps guide consistent LLM output.


419-431: Verify cost implications of increased max_tokens.

The 4x increase (500 → 2000) enables longer educational responses as intended. Ensure this aligns with expected API usage costs, especially for high-volume deployments.


508-541: LGTM!

Topic recording is correctly placed to execute exactly once per ask() call, regardless of whether the response is cached or freshly generated.


545-562: LGTM!

Clean delegation to learning_tracker with proper type hints and complete docstrings.

tests/test_ask.py (7)

1-14: LGTM!

Imports are appropriate for the new test cases.


292-308: LGTM!

Test setup properly isolates the learning history file to a temp directory, and teardown ensures cleanup.


310-344: LGTM!

Good coverage of educational pattern detection with both positive and negative test cases.


345-365: LGTM!

Topic extraction tests cover key prefixes and verify truncation behavior.


366-413: LGTM!

Comprehensive tests for topic recording, including file creation, count increments, and recent topics ordering.


415-478: LGTM!

Integration tests properly verify the learning tracker behavior through AskHandler, covering both educational and diagnostic query paths.


480-511: LGTM!

System prompt tests appropriately verify the presence of key sections without being overly brittle to prompt wording changes.

Comment on lines 1 to 6
"""Natural language query interface for Cortex.
Handles user questions about installed packages, configurations,
and system state using LLM with semantic caching.
and system state using LLM with semantic caching. Also provides
educational content and tracks learning progress.
"""
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Fix Black formatting to pass CI.

The pipeline indicates Black formatting failed. Run black . locally and commit the reformatted code to fix the CI failure.

🧰 Tools
🪛 GitHub Actions: CI

[error] 1-1: Black formatting check failed. 1 file would be reformatted. Run 'black .' to fix formatting.


[error] 1-1: Command failed with exit code 1.

🤖 Prompt for AI Agents
In @cortex/ask.py around lines 1 - 6, The file cortex/ask.py fails Black
formatting in CI; run the formatter (black .) locally or apply Black's rules to
reformat cortex/ask.py (and any other changed files), ensure the module
docstring and surrounding code conform to Black's line-length and string
conventions, then stage and commit the reformatted file(s) so CI picks up the
updated, Black-compliant version.

Convert PROGRESS_FILE from class-level constant to lazily-computed
property to avoid RuntimeError in restricted environments where
Path.home() may fail at import time. Falls back to temp directory.
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: 0

🧹 Nitpick comments (2)
cortex/ask.py (1)

219-279: Consider adding a brief note about concurrent access.

The read-modify-write pattern in record_topic isn't atomic, so concurrent processes could lose updates. This is acceptable for a single-user CLI tool, but consider adding a brief code comment noting this limitation if the feature might be used in multi-process scenarios in the future.

tests/test_ask.py (1)

3-3: Unused import.

The json module is imported but not used in this test file. The LearningTracker class handles JSON operations internally.

♻️ Proposed fix
 """Unit tests for the ask module."""
 
-import json
 import os
 import sys
📜 Review details

Configuration used: defaults

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between dd254a3 and 187b9f9.

📒 Files selected for processing (2)
  • cortex/ask.py
  • tests/test_ask.py
🧰 Additional context used
📓 Path-based instructions (2)
**/*.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:

  • tests/test_ask.py
  • cortex/ask.py
tests/**/*.py

📄 CodeRabbit inference engine (AGENTS.md)

Maintain >80% test coverage for pull requests

Files:

  • tests/test_ask.py
🧬 Code graph analysis (1)
tests/test_ask.py (1)
cortex/ask.py (11)
  • ask (479-546)
  • LearningTracker (141-279)
  • SystemInfoGatherer (22-138)
  • is_educational_query (182-187)
  • extract_topic (189-217)
  • record_topic (219-242)
  • get_history (244-246)
  • get_recent_topics (248-259)
  • get_recent_topics (556-565)
  • gather_context (131-138)
  • _get_system_prompt (355-412)
⏰ 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.12)
  • GitHub Check: test (3.10)
  • GitHub Check: test (3.11)
🔇 Additional comments (10)
cortex/ask.py (7)

1-17: LGTM!

Imports are properly organized and the module docstring has been updated to reflect the new educational content and learning progress tracking capabilities.


141-180: LGTM!

The LearningTracker class is well-designed with:

  • Lazy initialization of the progress file path with a sensible fallback for restricted environments
  • Compiled regex patterns for efficient repeated matching
  • Proper type hints and docstrings on all public methods

182-217: LGTM!

The educational query detection and topic extraction logic is clean and handles edge cases well, including the word-boundary-aware truncation at 50 characters.


282-312: LGTM!

The LearningTracker integration into AskHandler is clean. The tracker is properly initialized in __init__ and exposes appropriate public methods.


355-412: LGTM!

The enhanced system prompt is well-structured with clear sections for query type detection, educational vs. diagnostic response guidelines, and terminal-friendly formatting rules. The formatting guidance (avoiding markdown headings, using bold text instead) aligns with the PR objective of improving terminal rendering.


414-444: LGTM!

The max_tokens increase from 500 to 2000 is applied consistently to both OpenAI and Claude providers, enabling longer educational responses as specified in the PR objectives.


479-565: LGTM!

The ask method properly records topics for both cached and fresh responses, ensuring learning history is tracked regardless of cache state. The new get_learning_history and get_recent_topics methods provide clean public APIs with proper docstrings and type hints.

tests/test_ask.py (3)

292-413: LGTM!

The TestLearningTracker class provides comprehensive test coverage including:

  • Educational query detection for all pattern types
  • Topic extraction with prefix removal and truncation
  • History persistence (file creation, data storage, count incrementing)
  • Edge cases (non-educational queries, empty history, recent topics ordering)

Using a temporary directory with direct _progress_file assignment is an appropriate strategy for test isolation.


415-477: LGTM!

The TestAskHandlerLearning class effectively tests the integration between AskHandler and LearningTracker, verifying that:

  • Educational questions are recorded after ask() calls
  • Diagnostic questions are not recorded
  • The public API methods (get_learning_history, get_recent_topics) work through the handler
  • The system prompt contains expected educational guidance

480-511: LGTM!

The TestSystemPromptEnhancement class provides good regression protection for the enhanced system prompt, verifying the presence of key sections (query type detection, educational instructions, diagnostic instructions) and content (code examples, best practices, related topics).

@Anshgrover23 Anshgrover23 marked this pull request as draft January 12, 2026 19:58
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.

@ShreeJejurikar Kindly address all bot comments and ping me again will review then.

ShreeJejurikar and others added 5 commits January 13, 2026 13:17
This commit resolves 18 outstanding issues identified in code review:

CODE QUALITY IMPROVEMENTS:
- Removed unused 'import json' from test_ask.py
- Added return type hints (-> None) to LearningTracker.__init__
- Added type annotation for _compiled_patterns: list[re.Pattern[str]]
- Enhanced __init__ docstring with pattern compilation details

DESIGN & LOGIC ENHANCEMENTS:
- Refactored _compiled_patterns as class variable to avoid regex recompilation
- Improved topic truncation logic with explicit boundary checking (len > 50)
- Switched to UTC timestamps (datetime.now(timezone.utc).isoformat())
- Simplified is_educational_query() using any() for idiomatic Python

ERROR HANDLING & ROBUSTNESS:
- Added explicit UTF-8 encoding to json.load() and json.dump()
- Added debug-level logging for save failures without breaking CLI
- Fixed test environment pollution by cleaning up CORTEX_FAKE_RESPONSE
- Verified lazy Path.home() initialization with RuntimeError fallback

CONSISTENCY & DOCUMENTATION:
- Removed obsolete --offline flag documentation reference
- Replaced markdown headings with bold text in system prompt for consistency
- Added num_predict: 2000 to Ollama options matching OpenAI/Claude tokens
- Added edge case tests for malformed JSON and Path.home() failures
- Added concurrency documentation notes in record_topic() method
- Formatted all changes with Black and Ruff

TESTING:
- All 51 tests passing (+ 2 new edge case tests)
- Black formatter: ✓ All 129 files properly formatted
- Ruff linter: ✓ All checks passed

Closes: Related to enhanced cortex ask with tutor capabilities
- Renamed 'gpu' variable to 'gpu_info' for better clarity
- Now consistently uses 'gpu_info' throughout instead of 'gpu'
- Improves code readability and consistency
@sonarqubecloud
Copy link

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.

[FEATURE] Enhance cortex ask with interactive tutor capabilities

4 participants