Metadata-Version: 2.4
Name: rosforge
Version: 0.2.0
Summary: AI-driven ROS1 to ROS2 migration CLI tool
Author: ROSForge Contributors
License-Expression: Apache-2.0
License-File: LICENSE
Keywords: ai,migration,robotics,ros,ros2
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Topic :: Software Development :: Code Generators
Requires-Python: >=3.10
Requires-Dist: jinja2<4.0,>=3.1
Requires-Dist: lxml<6.0,>=5.0
Requires-Dist: pydantic<3.0,>=2.0
Requires-Dist: pyyaml>=6.0
Requires-Dist: rich<14.0,>=13.0
Requires-Dist: tomli-w<2.0,>=1.0
Requires-Dist: typer<1.0,>=0.12
Provides-Extra: all
Requires-Dist: anthropic<1.0,>=0.40; extra == 'all'
Requires-Dist: google-generativeai>=0.8; extra == 'all'
Requires-Dist: openai<2.0,>=1.50; extra == 'all'
Provides-Extra: claude
Requires-Dist: anthropic<1.0,>=0.40; extra == 'claude'
Provides-Extra: dev
Requires-Dist: mypy>=1.13; extra == 'dev'
Requires-Dist: pytest-cov; extra == 'dev'
Requires-Dist: pytest-mock; extra == 'dev'
Requires-Dist: pytest>=8.0; extra == 'dev'
Requires-Dist: ruff>=0.8; extra == 'dev'
Provides-Extra: gemini
Requires-Dist: google-generativeai>=0.8; extra == 'gemini'
Provides-Extra: openai
Requires-Dist: openai<2.0,>=1.50; extra == 'openai'
Description-Content-Type: text/markdown

# ROSForge

**AI-driven ROS1 to ROS2 migration CLI tool.**

[![CI](https://img.shields.io/github/actions/workflow/status/Rlin1027/ROSForge/ci.yml?branch=main&label=CI)](https://github.com/Rlin1027/ROSForge/actions) [![PyPI](https://img.shields.io/pypi/v/rosforge)](https://pypi.org/project/rosforge/) [![License](https://img.shields.io/badge/license-Apache%202.0-blue)](LICENSE)

## Why ROSForge?

ROS1 reached end-of-life in May 2025. Migrating a production codebase to ROS2 by hand is tedious and error-prone: API namespaces changed, CMakeLists.txt rules are different, launch files moved to Python, and hundreds of `ros::` calls need one-by-one replacement. ROSForge automates this work by combining a static knowledge base of known API mappings with an AI backend that handles the cases rules alone cannot cover. The result is a complete, confidence-scored migration in minutes rather than days.

## Features

- **Full pipeline** — analyze, transform, validate, and report in a single command
- **BYOM (Bring Your Own Model)** — Claude, Gemini, and OpenAI backends; CLI or API mode
- **Auto-fix loop** — runs `colcon build`, feeds errors back to the AI, retries up to N times
- **Interactive mode** — per-file diff review; accept or skip each transformed file
- **Batch workspace migration** — migrate an entire catkin workspace in one pass
- **Custom transformation rules** — override or extend mappings with a YAML file
- **Static knowledge base** — built-in C++/Python API mappings, CMake rules, and launch conversion patterns
- **Cost estimation** — token and USD estimates shown before any API calls are made
- **Confidence scoring** — every output file is rated HIGH / MEDIUM / LOW; low-confidence files are flagged for manual review

## Quick Start

```bash
# Install
pip install rosforge

# Set your preferred AI backend (stored in ~/.config/rosforge/config.toml)
rosforge config set engine.name gemini
rosforge config set engine.mode cli

# Migrate a single ROS1 package
rosforge migrate ./my_ros1_package -o ./my_ros1_package_ros2
```

The migrated package and a `migration_report.md` are written to the output directory.

## Commands

| Command | Description |
|---|---|
| `rosforge migrate <path>` | Migrate a single ROS1 package to ROS2 |
| `rosforge migrate-workspace <path>` | Migrate all packages in a catkin workspace |
| `rosforge analyze <path>` | Analyze a package and report migration complexity without transforming |
| `rosforge config set <key> <value>` | Set a configuration value and persist it |
| `rosforge config get <key>` | Get a single configuration value |
| `rosforge config list` | Print all current configuration values as JSON |
| `rosforge config reset` | Reset configuration to defaults |
| `rosforge config path` | Show the path to the configuration file |
| `rosforge status` | Show the status of an in-progress or completed migration |

## AI Engine Configuration

ROSForge supports three AI backends. Each can run in **cli** mode (calls a locally installed CLI tool, no API key required) or **api** mode (calls the provider's REST API directly, requires an API key).

### Claude

```bash
# CLI mode — requires the Anthropic Claude CLI installed and authenticated
rosforge config set engine.name claude
rosforge config set engine.mode cli

# API mode — requires ANTHROPIC_API_KEY
pip install "rosforge[claude]"
rosforge config set engine.name claude
rosforge config set engine.mode api
export ANTHROPIC_API_KEY=sk-ant-...
```

### Gemini

```bash
# CLI mode — requires the Google Gemini CLI installed and authenticated
rosforge config set engine.name gemini
rosforge config set engine.mode cli

# API mode — requires GOOGLE_API_KEY
pip install "rosforge[gemini]"
rosforge config set engine.name gemini
rosforge config set engine.mode api
export GOOGLE_API_KEY=AIza...
```

### OpenAI

```bash
# API mode — requires OPENAI_API_KEY
pip install "rosforge[openai]"
rosforge config set engine.name openai
rosforge config set engine.mode api
export OPENAI_API_KEY=sk-...
```

Install all backends at once:

```bash
pip install "rosforge[all]"
```

## Advanced Usage

### Interactive review

Review each transformed file before it is written:

```bash
rosforge migrate ./my_package --interactive
```

Press `a` to accept, `s` to skip, `q` to quit and accept all remaining files.

### Auto-fix loop

Build the output with `colcon build` after migration, feed any errors back to the AI, and retry:

```bash
rosforge migrate ./my_package --max-fix-attempts 3
```

### Custom rules

Supply additional or overriding transformation mappings:

```bash
rosforge migrate ./my_package --rules custom_rules.yaml
```

### Skip confirmation

Skip the cost-estimate confirmation prompt (useful in CI):

```bash
rosforge migrate ./my_package --yes
```

### Target ROS2 distribution

The default target is `humble`. To target a different distribution:

```bash
rosforge migrate ./my_package --distro jazzy
```

### Workspace migration

```bash
rosforge migrate-workspace ./catkin_ws -o ./ros2_ws --engine gemini --yes
```

### Analyze without migrating

```bash
# Rich table output in the terminal
rosforge analyze ./my_package

# Machine-readable JSON
rosforge analyze ./my_package --json

# Save JSON report to file
rosforge analyze ./my_package -o analysis.json
```

## CI/CD Integration

ROSForge provides ready-made templates for GitHub Actions and GitLab CI so you can automatically verify ROS1→ROS2 migration in your pipeline.

### GitHub Actions

Use the reusable composite action:

```yaml
# .github/workflows/rosforge.yml
name: ROSForge Migration Check
on: [push, pull_request]

jobs:
  analyze:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: Rlin1027/ROSForge/ci-templates/github@main
        with:
          source: ./src/my_ros1_package
          mode: analyze            # "analyze" or "migrate"
```

For a full migration dry-run with auto-fix:

```yaml
      - uses: Rlin1027/ROSForge/ci-templates/github@main
        with:
          source: ./src/my_ros1_package
          mode: migrate
          engine: claude
          engine-mode: api
          max-fix-attempts: "2"
          fail-on-warnings: "true"
        env:
          ANTHROPIC_API_KEY: ${{ secrets.ANTHROPIC_API_KEY }}
```

See [`ci-templates/github/example-workflow.yml`](ci-templates/github/example-workflow.yml) for a complete example.

### GitLab CI

Include the remote template and extend the hidden jobs:

```yaml
# .gitlab-ci.yml
include:
  - remote: "https://raw.githubusercontent.com/Rlin1027/ROSForge/main/ci-templates/gitlab/.gitlab-ci-rosforge.yml"

variables:
  ROSFORGE_SOURCE: ./src/my_ros1_package
  ROSFORGE_ENGINE: claude
  ROSFORGE_TARGET_DISTRO: humble

rosforge-analyze:
  extends: .rosforge-analyze

rosforge-migrate:
  extends: .rosforge-migrate
  variables:
    ROSFORGE_ENGINE_MODE: api
    ROSFORGE_MAX_FIX_ATTEMPTS: "2"
```

### Exit Codes

| Code | Meaning |
|------|---------|
| 0 | Success |
| 1 | Failure |
| 2 | Completed with warnings (set `fail-on-warnings` to treat as failure) |

## Custom Rules

Create a YAML file to add or override transformation mappings:

```yaml
# custom_rules.yaml
version: 1

api_mappings:
  cpp:
    "ros::NodeHandle": "rclcpp::Node"
    "ros::Publisher": "rclcpp::Publisher"
  python:
    "rospy.init_node": "rclpy.init"
    "rospy.Publisher": "rclpy.create_publisher"

package_mappings:
  "roscpp": "rclcpp"
  "rospy": "rclpy"

cmake_mappings:
  "find_package(catkin REQUIRED": "find_package(ament_cmake REQUIRED"
```

Pass the file with `--rules custom_rules.yaml`. Custom mappings take precedence over the built-in knowledge base.

## Development

```bash
git clone https://github.com/Rlin1027/ROSForge.git
cd ROSForge
pip install -e ".[dev,all]"
pytest tests/
```

Lint and type-check:

```bash
ruff check src/
mypy src/
```

## Contributing

Contributions are welcome. Please open an issue before submitting a pull request for significant changes. See [CONTRIBUTING.md](CONTRIBUTING.md) for guidelines.

## License

Apache 2.0 — see [LICENSE](LICENSE) for details.
