Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
50d92cf
Voice feature: speeech-to-text added
Sahilbhatane Dec 31, 2025
9acb0d7
Merge branch 'cortexlinux:main' into issue-325
Sahilbhatane Dec 31, 2025
bb1de82
test fixs
Sahilbhatane Dec 31, 2025
891dff5
chore: add myenv and venv312 to gitignore
Sahilbhatane Dec 31, 2025
1734cff
fix: remove myenv from repo and fix voice test mocking
Sahilbhatane Dec 31, 2025
dab189b
docs: remove tiny.en model, use base.en as default everywhere
Sahilbhatane Dec 31, 2025
b66f6c0
fix: address Copilot and CodeRabbit review comments
Sahilbhatane Dec 31, 2025
45d3769
fix: skip voice tests when numpy not installed (optional dep)
Sahilbhatane Dec 31, 2025
8f2384f
Merge branch 'cortexlinux:main' into issue-325
Sahilbhatane Dec 31, 2025
12e7208
Merge branch 'main' into issue-325
Sahilbhatane Jan 11, 2026
3ae13dd
Suggestion fix and import fix
Sahilbhatane Jan 11, 2026
4837e51
Add import for error
Sahilbhatane Jan 11, 2026
73a734f
System requirements for voice and key detection
Sahilbhatane Jan 11, 2026
0cd18a1
test fix for py 3.11
Sahilbhatane Jan 11, 2026
1abb28e
Test fix and consolidate package installations
Sahilbhatane Jan 12, 2026
9645134
Merge branch 'main' into issue-325
Sahilbhatane Jan 12, 2026
0de57d2
fix: Code review fixes for PR #405
Sahilbhatane Jan 12, 2026
f55bd8c
fix: SonarCloud reliability improvements
Sahilbhatane Jan 12, 2026
7e49182
refactor: Reduce cognitive complexity in install method
Sahilbhatane Jan 12, 2026
2563901
fix: Remove unused variable and clean imports in voice.py
Sahilbhatane Jan 12, 2026
e322815
test: Clean up unused variables in test_voice.py
Sahilbhatane Jan 12, 2026
c4dffe5
fix: Extract 'Installation failed' constant to eliminate duplication
Sahilbhatane Jan 12, 2026
6bb4173
fix: Remove unused fixture parameters from voice tests
Sahilbhatane Jan 12, 2026
758299d
black formating for lint
Sahilbhatane Jan 12, 2026
d771562
fix: VoiceInputHandler resources are always cleaned up
Sahilbhatane Jan 12, 2026
580eb76
remove duplicate package
Sahilbhatane Jan 12, 2026
83f3360
user choice for model selection
Sahilbhatane Jan 12, 2026
1934d19
suggstion fix
Sahilbhatane Jan 12, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ __pycache__/
# ==============================
env/
venv/
myenv/
venv312/
Comment on lines +16 to +17
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 | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check for committed virtual environment files in the current HEAD and recent commits

echo "=== Checking git log for myenv and venv312 directories ==="
git log --all --oneline --full-history -- myenv/ venv312/ 2>&1 | head -20

echo -e "\n=== Checking git status ==="
git status --short | grep -E '(myenv|venv312)' || echo "No myenv/venv312 in current status"

echo -e "\n=== Checking HEAD commit for these files ==="
git ls-tree -r HEAD | grep -E '(myenv|venv312)' || echo "No myenv/venv312 files in HEAD"

echo -e "\n=== Checking recent commits (last 5) ==="
git log --oneline -5

echo -e "\n=== Checking if myenv and venv312 are untracked/ignored ==="
git check-ignore -v myenv/ venv312/ 2>&1 || echo "Checking ignore patterns..."

echo -e "\n=== Listing actual directories in repository root ==="
ls -la | grep -E '(myenv|venv|env)' || echo "No venv directories found in root"

Repository: cortexlinux/cortex

Length of output: 5200


Critical: Virtual environment files committed to git; .gitignore change is incomplete.

The myenv/ directory with virtual environment artifacts (activation scripts, pyvenv.cfg, executables, man pages) is already committed in this PR. Adding myenv/ and venv312/ to .gitignore prevents future commits but does not remove these files from git history.

These directories must be removed from the commit before merging. Use git rm -r --cached myenv/ venv312/ and amend the commit, or rebase to exclude them entirely. Without this cleanup, the repository will include unnecessary virtual environment files that violate the project's policy of never committing local development environments.

🤖 Prompt for AI Agents
In .gitignore around lines 16-17, the review notes that myenv/ and venv312/ were
committed despite being ignored; remove those directories from the repository
index and rewrite the offending commit(s): run git rm -r --cached myenv/
venv312/ to untrack them, commit the removal (or git commit --amend if you want
to fix the latest commit), and if the directories exist in earlier commits use
an interactive rebase or filter-branch/BFG to purge them from history; ensure
.gitignore retains myenv/ and venv312/ so they are not re-added, then push with
force-if-rewriting-history and notify reviewers.

ENV/
env.bak/
venv.bak/
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ cortex install "tools for video compression"
| Feature | Description |
|---------|-------------|
| **Natural Language** | Describe what you need in plain English |
| **Voice Input** | Hands-free mode with Whisper speech recognition ([F9 to speak](docs/VOICE_INPUT.md)) |
| **Dry-Run Default** | Preview all commands before execution |
| **Sandboxed Execution** | Commands run in Firejail isolation |
| **Full Rollback** | Undo any installation with `cortex rollback` |
Expand Down
38 changes: 36 additions & 2 deletions cortex/api_key_detector.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,23 @@ def detect(self) -> tuple[bool, str | None, str | None, str | None]:
return result or (False, None, None, None)

def _check_environment_api_keys(self) -> tuple[bool, str, str, str] | None:
"""Check for API keys in environment variables."""
"""Check for API keys in environment variables.

If CORTEX_PROVIDER is explicitly set, prefer that provider's key first.
"""
explicit_provider = os.environ.get("CORTEX_PROVIDER", "").lower()

# If user explicitly set CORTEX_PROVIDER to a specific provider, check that key first
if explicit_provider in ["openai", "claude"]:
target_env_var = (
"OPENAI_API_KEY" if explicit_provider == "openai" else "ANTHROPIC_API_KEY"
)
target_provider = "openai" if explicit_provider == "openai" else "anthropic"
value = os.environ.get(target_env_var)
if value:
return (True, value, target_provider, "environment")

# Otherwise check all providers in default order
for env_var, provider in ENV_VAR_PROVIDERS.items():
value = os.environ.get(env_var)
if value:
Expand All @@ -141,7 +157,25 @@ def _check_encrypted_storage(self) -> tuple[bool, str, str, str] | None:

env_mgr = get_env_manager()

# Check for API keys in encrypted storage
# If CORTEX_PROVIDER is explicitly set, check that provider's key first
explicit_provider = os.environ.get("CORTEX_PROVIDER", "").lower()
if explicit_provider in ["openai", "claude"]:
target_env_var = (
"OPENAI_API_KEY" if explicit_provider == "openai" else "ANTHROPIC_API_KEY"
)
target_provider = "openai" if explicit_provider == "openai" else "anthropic"
value = env_mgr.get_variable(app="cortex", key=target_env_var, decrypt=True)
if value:
os.environ[target_env_var] = value
logger.debug(f"Loaded {target_env_var} from encrypted storage")
return (
True,
value,
target_provider,
"encrypted storage (~/.cortex/environments/)",
)

# Check for API keys in encrypted storage (default order)
for env_var, provider in ENV_VAR_PROVIDERS.items():
value = env_mgr.get_variable(app="cortex", key=env_var, decrypt=True)
if value:
Expand Down
37 changes: 26 additions & 11 deletions cortex/branding.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,13 @@
Uses Rich library for cross-platform terminal styling.
"""

import sys

from rich.console import Console
from rich.panel import Panel

console = Console()
# Use force_terminal and legacy_windows for better Windows compatibility
console = Console(force_terminal=True, legacy_windows=sys.platform == "win32")

# Brand colors
CORTEX_CYAN = "cyan"
Expand Down Expand Up @@ -57,13 +60,23 @@ def cx_print(message: str, status: str = "info"):
"""
badge = "[bold white on dark_cyan] CX [/bold white on dark_cyan]"

status_icons = {
"info": "[dim]│[/dim]",
"success": "[green]✓[/green]",
"warning": "[yellow]⚠[/yellow]",
"error": "[red]✗[/red]",
"thinking": "[cyan]⠋[/cyan]", # Spinner frame
}
# Use ASCII-only icons on Windows for better compatibility
if sys.platform == "win32":
status_icons = {
"info": "[dim]|[/dim]",
"success": "[green]+[/green]",
"warning": "[yellow]![/yellow]",
"error": "[red]x[/red]",
"thinking": "[cyan]*[/cyan]",
}
else:
status_icons = {
"info": "[dim]│[/dim]",
"success": "[green]✓[/green]",
"warning": "[yellow]⚠[/yellow]",
"error": "[red]✗[/red]",
"thinking": "[cyan]⠋[/cyan]", # Spinner frame
}

icon = status_icons.get(status, status_icons["info"])
console.print(f"{badge} {icon} {message}")
Expand All @@ -73,18 +86,20 @@ def cx_step(step_num: int, total: int, message: str):
"""
Print a numbered step with the CX badge.

Example: CX [1/4] Updating package lists...
Example: CX | [1/4] Updating package lists...
"""
badge = "[bold white on dark_cyan] CX [/bold white on dark_cyan]"
console.print(f"{badge} [dim]│[/dim] [{step_num}/{total}] {message}")
separator = "|" if sys.platform == "win32" else "│"
console.print(f"{badge} [dim]{separator}[/dim] [{step_num}/{total}] {message}")


def cx_header(title: str):
"""
Print a section header.
"""
console.print()
console.print(f"[bold cyan]━━━ {title} ━━━[/bold cyan]")
separator = "---" if sys.platform == "win32" else "━━━"
console.print(f"[bold cyan]{separator} {title} {separator}[/bold cyan]")
console.print()


Expand Down
Loading
Loading