Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 10 additions & 1 deletion .github/cla-signers.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"version": "1.0",
"last_updated": "2025-12-31",
"last_updated": "2026-01-03",
"individuals": [
{
"name": "Mike Morgan",
Expand Down Expand Up @@ -122,6 +122,15 @@
],
"signed_date": "2026-01-02",
"cla_version": "1.0"
},
{
"name": "Ajay Bandaru",
"github_username": "aybanda",
"emails": [
"jsaj2024@gmail.com"
],
"signed_date": "2026-01-03",
"cla_version": "1.0"
}
],
"corporations": {
Expand Down
107 changes: 107 additions & 0 deletions cortex/cli.py
Copy link
Collaborator

Choose a reason for hiding this comment

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

This files are irrelevant, why changed ?

Original file line number Diff line number Diff line change
Expand Up @@ -543,6 +543,9 @@ def install(
execute: bool = False,
dry_run: bool = False,
parallel: bool = False,
from_source: bool = False,
source_url: str | None = None,
version: str | None = None,
):
# Validate input first
is_valid, error = validate_install_request(software)
Expand Down Expand Up @@ -577,6 +580,12 @@ def install(
start_time = datetime.now()

try:
# Handle --from-source flag
if from_source:
return self._install_from_source(
software, execute, dry_run, source_url, version
)

self._print_status("🧠", "Understanding request...")

interpreter = CommandInterpreter(api_key=api_key, provider=provider)
Expand Down Expand Up @@ -1521,6 +1530,86 @@ def progress_callback(current: int, total: int, step: InstallationStep) -> None:
console.print(f"Error: {result.error_message}", style="red")
return 1

def _install_from_source(
self,
package_name: str,
execute: bool,
dry_run: bool,
source_url: str | None,
version: str | None,
) -> int:
"""Handle installation from source."""
from cortex.source_builder import SourceBuilder

builder = SourceBuilder()

# Parse version from package name if specified (e.g., python@3.12)
if "@" in package_name and not version:
parts = package_name.split("@")
package_name = parts[0]
version = parts[1] if len(parts) > 1 else None

cx_print(f"Building {package_name} from source...", "info")
if version:
cx_print(f"Version: {version}", "info")

result = builder.build_from_source(
package_name=package_name,
version=version,
source_url=source_url,
use_cache=True,
)

if not result.success:
self._print_error(f"Build failed: {result.error_message}")
return 1

if result.cached:
cx_print(f"Using cached build for {package_name}", "info")

if dry_run:
cx_print("\nBuild commands (dry run):", "info")
for cmd in result.install_commands:
console.print(f" • {cmd}")
return 0

if not execute:
cx_print("\nBuild completed. Install commands:", "info")
for cmd in result.install_commands:
console.print(f" • {cmd}")
cx_print("Run with --execute to install", "info")
return 0

# Execute install commands
from cortex.coordinator import InstallationCoordinator, InstallationStep, StepStatus

def progress_callback(current: int, total: int, step: InstallationStep) -> None:
status_emoji = "⏳"
if step.status == StepStatus.SUCCESS:
status_emoji = "✅"
elif step.status == StepStatus.FAILED:
status_emoji = "❌"
console.print(f"[{current}/{total}] {status_emoji} {step.description}")

coordinator = InstallationCoordinator(
commands=result.install_commands,
descriptions=[f"Install {package_name}" for _ in result.install_commands],
timeout=600,
stop_on_error=True,
progress_callback=progress_callback,
)

install_result = coordinator.execute()

if install_result.success:
self._print_success(f"{package_name} built and installed successfully!")
return 0
else:
self._print_error("Installation failed")
if install_result.error_message:
console.print(f"Error: {install_result.error_message}", style="red")
return 1

# --------------------------


Expand Down Expand Up @@ -1641,6 +1730,21 @@ def main():
action="store_true",
help="Enable parallel execution for multi-step installs",
)
install_parser.add_argument(
"--from-source",
action="store_true",
help="Build and install from source code when binaries unavailable",
)
install_parser.add_argument(
"--source-url",
type=str,
help="URL to source code (for --from-source)",
)
install_parser.add_argument(
"--version",
type=str,
help="Version to build (for --from-source)",
)

# Import command - import dependencies from package manager files
import_parser = subparsers.add_parser(
Expand Down Expand Up @@ -1882,6 +1986,9 @@ def main():
execute=args.execute,
dry_run=args.dry_run,
parallel=args.parallel,
from_source=getattr(args, "from_source", False),
source_url=getattr(args, "source_url", None),
version=getattr(args, "version", None),
)
elif args.command == "import":
return cli.import_deps(args)
Expand Down
Loading
Loading