64 changed files with 107 additions and 8673 deletions
@ -1,49 +0,0 @@ |
|||||||
# Version control |
|
||||||
.git |
|
||||||
.gitignore |
|
||||||
|
|
||||||
# Python |
|
||||||
__pycache__/ |
|
||||||
*.py[cod] |
|
||||||
*$py.class |
|
||||||
*.so |
|
||||||
.Python |
|
||||||
.env |
|
||||||
.venv |
|
||||||
env/ |
|
||||||
venv/ |
|
||||||
ENV/ |
|
||||||
*.egg-info/ |
|
||||||
dist/ |
|
||||||
build/ |
|
||||||
|
|
||||||
# Logs and databases |
|
||||||
*.log |
|
||||||
logs/ |
|
||||||
*.sqlite |
|
||||||
|
|
||||||
# Downloads and temporary files |
|
||||||
downloads/ |
|
||||||
tmp/ |
|
||||||
temp/ |
|
||||||
|
|
||||||
# IDE specific files |
|
||||||
.idea/ |
|
||||||
.vscode/ |
|
||||||
*.swp |
|
||||||
*.swo |
|
||||||
|
|
||||||
# Docker |
|
||||||
Dockerfile |
|
||||||
.dockerignore |
|
||||||
|
|
||||||
# Documentation |
|
||||||
docs/ |
|
||||||
*.md |
|
||||||
LICENSE |
|
||||||
|
|
||||||
# Test files |
|
||||||
tests/ |
|
||||||
.pytest_cache/ |
|
||||||
.coverage |
|
||||||
htmlcov/ |
|
@ -1,9 +0,0 @@ |
|||||||
# API Keys Configuration |
|
||||||
OPENAI_API_KEY=your-openai-key |
|
||||||
ANTHROPIC_API_KEY=your-anthropic-key |
|
||||||
GOOGLE_API_KEY=your-google-key |
|
||||||
DEEPSEEK_API_KEY=your-deepseek-key |
|
||||||
GROQ_API_KEY=your-groq-key |
|
||||||
|
|
||||||
# Server Configuration |
|
||||||
PORT=7860 # Change this if port 7860 is already in use |
|
@ -1,51 +0,0 @@ |
|||||||
# CodeXchange AI CI/CD Workflows |
|
||||||
|
|
||||||
This directory contains GitHub Actions workflows for continuous integration and deployment of the CodeXchange AI application. |
|
||||||
|
|
||||||
## Workflow Overview |
|
||||||
|
|
||||||
1. **python-test.yml**: Runs Python tests, linting, and code coverage |
|
||||||
2. **docker-build.yml**: Builds and validates Docker images with security scanning |
|
||||||
3. **deploy-staging.yml**: Deploys to staging environment when changes are pushed to develop branch |
|
||||||
4. **deploy-production.yml**: Deploys to production environment when a new release is published |
|
||||||
|
|
||||||
## Required GitHub Secrets |
|
||||||
|
|
||||||
To use these workflows, you need to set up the following secrets in your GitHub repository: |
|
||||||
|
|
||||||
1. Go to your GitHub repository |
|
||||||
2. Navigate to Settings → Secrets and Variables → Actions |
|
||||||
3. Add the following secrets: |
|
||||||
|
|
||||||
| Secret Name | Description | |
|
||||||
|-------------|-------------| |
|
||||||
| `DOCKERHUB_USERNAME` | Your Docker Hub username | |
|
||||||
| `DOCKERHUB_TOKEN` | A personal access token from Docker Hub (not your password) | |
|
||||||
|
|
||||||
## Getting a Docker Hub Access Token |
|
||||||
|
|
||||||
1. Log in to [Docker Hub](https://hub.docker.com) |
|
||||||
2. Go to Account Settings → Security |
|
||||||
3. Create a new access token with appropriate permissions |
|
||||||
4. Copy the token immediately (it's only shown once) |
|
||||||
5. Add it as a GitHub secret |
|
||||||
|
|
||||||
## Customizing Deployment |
|
||||||
|
|
||||||
The deployment workflows currently include placeholder comments where you would add your specific deployment commands. Update these sections based on your hosting environment: |
|
||||||
|
|
||||||
- For VPS hosting: Add SSH-based deployment steps |
|
||||||
- For cloud providers: Add their specific deployment APIs |
|
||||||
- For Kubernetes: Add kubectl commands or Helm chart updates |
|
||||||
|
|
||||||
## Testing GitHub Actions Locally |
|
||||||
|
|
||||||
You can test GitHub Actions locally using [act](https://github.com/nektos/act): |
|
||||||
|
|
||||||
```bash |
|
||||||
# Install act |
|
||||||
brew install act |
|
||||||
|
|
||||||
# Run a specific workflow |
|
||||||
act -j test -W .github/workflows/python-test.yml |
|
||||||
``` |
|
@ -1,48 +0,0 @@ |
|||||||
name: Deploy to Production |
|
||||||
|
|
||||||
on: |
|
||||||
release: |
|
||||||
types: [published] |
|
||||||
|
|
||||||
jobs: |
|
||||||
build-and-deploy: |
|
||||||
runs-on: ubuntu-latest |
|
||||||
environment: production |
|
||||||
steps: |
|
||||||
- name: Checkout code |
|
||||||
uses: actions/checkout@v3 |
|
||||||
|
|
||||||
- name: Set up Docker Buildx |
|
||||||
uses: docker/setup-buildx-action@v2 |
|
||||||
|
|
||||||
- name: Login to DockerHub |
|
||||||
uses: docker/login-action@v2 |
|
||||||
with: |
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }} |
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }} |
|
||||||
|
|
||||||
- name: Extract metadata |
|
||||||
id: meta |
|
||||||
uses: docker/metadata-action@v4 |
|
||||||
with: |
|
||||||
images: ${{ secrets.DOCKERHUB_USERNAME }}/codexchangeai |
|
||||||
tags: | |
|
||||||
type=semver,pattern={{version}} |
|
||||||
type=semver,pattern={{major}}.{{minor}} |
|
||||||
latest |
|
||||||
|
|
||||||
- name: Build and push Docker image |
|
||||||
uses: docker/build-push-action@v4 |
|
||||||
with: |
|
||||||
context: . |
|
||||||
push: true |
|
||||||
tags: ${{ steps.meta.outputs.tags }} |
|
||||||
labels: ${{ steps.meta.outputs.labels }} |
|
||||||
cache-from: type=gha |
|
||||||
cache-to: type=gha,mode=max |
|
||||||
|
|
||||||
# Production deployment steps would be added here |
|
||||||
# This could involve: |
|
||||||
# 1. Updating a Kubernetes deployment |
|
||||||
# 2. SSH into production server and updating containers |
|
||||||
# 3. Using cloud provider deployment APIs |
|
@ -1,44 +0,0 @@ |
|||||||
name: Deploy to Staging |
|
||||||
|
|
||||||
on: |
|
||||||
push: |
|
||||||
branches: [ develop ] |
|
||||||
|
|
||||||
jobs: |
|
||||||
build-and-deploy: |
|
||||||
runs-on: ubuntu-latest |
|
||||||
steps: |
|
||||||
- name: Checkout code |
|
||||||
uses: actions/checkout@v3 |
|
||||||
|
|
||||||
- name: Set up Docker Buildx |
|
||||||
uses: docker/setup-buildx-action@v2 |
|
||||||
|
|
||||||
- name: Login to DockerHub |
|
||||||
uses: docker/login-action@v2 |
|
||||||
with: |
|
||||||
username: ${{ secrets.DOCKERHUB_USERNAME }} |
|
||||||
password: ${{ secrets.DOCKERHUB_TOKEN }} |
|
||||||
|
|
||||||
- name: Extract metadata |
|
||||||
id: meta |
|
||||||
uses: docker/metadata-action@v4 |
|
||||||
with: |
|
||||||
images: ${{ secrets.DOCKERHUB_USERNAME }}/codexchangeai |
|
||||||
tags: | |
|
||||||
type=ref,event=branch |
|
||||||
type=sha,format=short |
|
||||||
|
|
||||||
- name: Build and push Docker image |
|
||||||
uses: docker/build-push-action@v4 |
|
||||||
with: |
|
||||||
context: . |
|
||||||
push: true |
|
||||||
tags: ${{ steps.meta.outputs.tags }} |
|
||||||
labels: ${{ steps.meta.outputs.labels }} |
|
||||||
cache-from: type=gha |
|
||||||
cache-to: type=gha,mode=max |
|
||||||
|
|
||||||
# Here you would typically include steps to deploy to your staging environment |
|
||||||
# For example, using SSH to connect to your server and pull the new image |
|
||||||
# Or using a cloud provider's deployment API |
|
@ -1,40 +0,0 @@ |
|||||||
name: Python Tests |
|
||||||
|
|
||||||
on: |
|
||||||
push: |
|
||||||
branches: [ main, develop ] |
|
||||||
pull_request: |
|
||||||
branches: [ main, develop ] |
|
||||||
|
|
||||||
jobs: |
|
||||||
test: |
|
||||||
runs-on: ubuntu-latest |
|
||||||
strategy: |
|
||||||
matrix: |
|
||||||
python-version: ['3.10', '3.11'] |
|
||||||
|
|
||||||
steps: |
|
||||||
- uses: actions/checkout@v4 |
|
||||||
|
|
||||||
- name: Set up Python ${{ matrix.python-version }} |
|
||||||
uses: actions/setup-python@v5 |
|
||||||
with: |
|
||||||
python-version: ${{ matrix.python-version }} |
|
||||||
cache: 'pip' |
|
||||||
|
|
||||||
- name: Install dependencies |
|
||||||
run: | |
|
||||||
python -m pip install --upgrade pip |
|
||||||
pip install flake8 pytest pytest-cov |
|
||||||
if [ -f requirements.txt ]; then pip install -r requirements.txt; fi |
|
||||||
|
|
||||||
- name: Lint with flake8 |
|
||||||
run: | |
|
||||||
# stop the build if there are Python syntax errors or undefined names |
|
||||||
flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics |
|
||||||
# exit-zero treats all errors as warnings |
|
||||||
flake8 . --count --exit-zero --max-complexity=10 --max-line-length=120 --statistics |
|
||||||
|
|
||||||
- name: Test with pytest |
|
||||||
run: | |
|
||||||
pytest --cov=src/ai_code_converter tests/ |
|
@ -1,66 +0,0 @@ |
|||||||
# Environment variables |
|
||||||
.env |
|
||||||
|
|
||||||
# Windsurf |
|
||||||
.windsurfrules |
|
||||||
|
|
||||||
action_plan_save.md |
|
||||||
action_plan.md |
|
||||||
|
|
||||||
ai_converter_v2.code-workspace |
|
||||||
|
|
||||||
# Python |
|
||||||
__pycache__/ |
|
||||||
*.py[cod] |
|
||||||
*$py.class |
|
||||||
*.so |
|
||||||
.Python |
|
||||||
env/ |
|
||||||
build/ |
|
||||||
develop-eggs/ |
|
||||||
dist/ |
|
||||||
downloads/ |
|
||||||
eggs/ |
|
||||||
.eggs/ |
|
||||||
lib/ |
|
||||||
lib64/ |
|
||||||
parts/ |
|
||||||
sdist/ |
|
||||||
var/ |
|
||||||
wheels/ |
|
||||||
*.egg-info/ |
|
||||||
.installed.cfg |
|
||||||
*.egg |
|
||||||
|
|
||||||
# Logs |
|
||||||
logs/ |
|
||||||
*.log |
|
||||||
|
|
||||||
# IDE specific files |
|
||||||
.idea/ |
|
||||||
.vscode/ |
|
||||||
*.swp |
|
||||||
*.swo |
|
||||||
|
|
||||||
# OS specific files |
|
||||||
.DS_Store |
|
||||||
Thumbs.db |
|
||||||
|
|
||||||
# Virtual Environment |
|
||||||
venv/ |
|
||||||
.venv/ |
|
||||||
ENV/ |
|
||||||
|
|
||||||
# Prometheus |
|
||||||
/tmp/prometheus-multiproc/ |
|
||||||
|
|
||||||
# Local development |
|
||||||
.env.local |
|
||||||
.env.development.local |
|
||||||
.env.test.local |
|
||||||
.env.production.local |
|
||||||
|
|
||||||
# Temporary files |
|
||||||
tmp/ |
|
||||||
temp/ |
|
||||||
*.tmp |
|
@ -1,287 +0,0 @@ |
|||||||
# Stage 1: Base development image |
|
||||||
FROM ubuntu:22.04 AS builder |
|
||||||
|
|
||||||
# Add metadata about build environment |
|
||||||
LABEL org.opencontainers.image.title="CodeXchange AI Builder" |
|
||||||
LABEL org.opencontainers.image.description="Multi-platform build environment for CodeXchange AI" |
|
||||||
|
|
||||||
# Prevent interactive prompts during package installation |
|
||||||
ENV DEBIAN_FRONTEND=noninteractive |
|
||||||
|
|
||||||
# Install essential build tools and compilers |
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \ |
|
||||||
python3.10 \ |
|
||||||
python3-pip \ |
|
||||||
python3.10-venv \ |
|
||||||
build-essential \ |
|
||||||
gcc \ |
|
||||||
g++ \ |
|
||||||
openjdk-17-jdk \ |
|
||||||
curl \ |
|
||||||
ca-certificates \ |
|
||||||
git \ |
|
||||||
nodejs \ |
|
||||||
npm \ |
|
||||||
perl \ |
|
||||||
lua5.3 \ |
|
||||||
php \ |
|
||||||
r-base \ |
|
||||||
ruby \ |
|
||||||
rustc \ |
|
||||||
cargo \ |
|
||||||
mono-complete \ |
|
||||||
mono-devel \ |
|
||||||
mono-mcs \ |
|
||||||
sqlite3 \ |
|
||||||
unzip \ |
|
||||||
&& rm -rf /var/lib/apt/lists/* |
|
||||||
|
|
||||||
# Install TypeScript |
|
||||||
RUN npm install -g typescript |
|
||||||
|
|
||||||
# Install Swift |
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \ |
|
||||||
binutils \ |
|
||||||
libc6-dev \ |
|
||||||
libcurl4 \ |
|
||||||
libedit2 \ |
|
||||||
libgcc-9-dev \ |
|
||||||
libpython3.10 \ |
|
||||||
libsqlite3-0 \ |
|
||||||
libstdc++-9-dev \ |
|
||||||
libxml2 \ |
|
||||||
libz3-dev \ |
|
||||||
pkg-config \ |
|
||||||
tzdata \ |
|
||||||
zlib1g-dev \ |
|
||||||
&& rm -rf /var/lib/apt/lists/* |
|
||||||
|
|
||||||
RUN arch=$(uname -m) && \ |
|
||||||
if [ "$arch" = "x86_64" ]; then \ |
|
||||||
SWIFT_URL="https://download.swift.org/swift-5.9.2-release/ubuntu2204/swift-5.9.2-RELEASE/swift-5.9.2-RELEASE-ubuntu22.04.tar.gz"; \ |
|
||||||
elif [ "$arch" = "aarch64" ] || [ "$arch" = "arm64" ]; then \ |
|
||||||
SWIFT_URL="https://download.swift.org/swift-5.9.2-release/ubuntu2204-aarch64/swift-5.9.2-RELEASE/swift-5.9.2-RELEASE-ubuntu22.04-aarch64.tar.gz"; \ |
|
||||||
else \ |
|
||||||
echo "Unsupported architecture for Swift: $arch"; \ |
|
||||||
exit 1; \ |
|
||||||
fi && \ |
|
||||||
curl -fL $SWIFT_URL | tar xz -C /opt && \ |
|
||||||
ln -s /opt/swift-5.9.2-RELEASE-ubuntu22.04*/usr/bin/swift /usr/local/bin/swift |
|
||||||
|
|
||||||
# Install Kotlin |
|
||||||
RUN KOTLIN_VERSION=1.9.22 && \ |
|
||||||
cd /tmp && \ |
|
||||||
curl -LO "https://github.com/JetBrains/kotlin/releases/download/v${KOTLIN_VERSION}/kotlin-compiler-${KOTLIN_VERSION}.zip" && \ |
|
||||||
unzip "kotlin-compiler-${KOTLIN_VERSION}.zip" -d /opt && \ |
|
||||||
rm "kotlin-compiler-${KOTLIN_VERSION}.zip" && \ |
|
||||||
ln -s "/opt/kotlinc/bin/kotlin" /usr/local/bin/kotlin && \ |
|
||||||
ln -s "/opt/kotlinc/bin/kotlinc" /usr/local/bin/kotlinc |
|
||||||
|
|
||||||
# Install Julia based on architecture (with Windows WSL2 compatibility) |
|
||||||
RUN arch=$(uname -m) && \ |
|
||||||
echo "Detected architecture: $arch" && \ |
|
||||||
if [ "$arch" = "aarch64" ] || [ "$arch" = "arm64" ]; then \ |
|
||||||
echo "Installing ARM64 version of Julia" && \ |
|
||||||
curl -fL https://julialang-s3.julialang.org/bin/linux/aarch64/1.9/julia-1.9.3-linux-aarch64.tar.gz | tar xz -C /opt && \ |
|
||||||
ln -s /opt/julia-1.9.3/bin/julia /usr/local/bin/julia; \ |
|
||||||
elif [ "$arch" = "x86_64" ] || [ "$arch" = "amd64" ]; then \ |
|
||||||
echo "Installing x86_64 version of Julia" && \ |
|
||||||
curl -fL https://julialang-s3.julialang.org/bin/linux/x64/1.9/julia-1.9.3-linux-x86_64.tar.gz | tar xz -C /opt && \ |
|
||||||
ln -s /opt/julia-1.9.3/bin/julia /usr/local/bin/julia; \ |
|
||||||
else \ |
|
||||||
echo "WARNING: Unknown architecture $arch, defaulting to x86_64" && \ |
|
||||||
curl -fL https://julialang-s3.julialang.org/bin/linux/x64/1.9/julia-1.9.3-linux-x86_64.tar.gz | tar xz -C /opt && \ |
|
||||||
ln -s /opt/julia-1.9.3/bin/julia /usr/local/bin/julia; \ |
|
||||||
fi |
|
||||||
|
|
||||||
# Install Go based on architecture (with Windows WSL2 compatibility) |
|
||||||
RUN arch=$(uname -m) && \ |
|
||||||
echo "Detected architecture for Go: $arch" && \ |
|
||||||
if [ "$arch" = "aarch64" ] || [ "$arch" = "arm64" ]; then \ |
|
||||||
echo "Installing ARM64 version of Go" && \ |
|
||||||
curl -L https://go.dev/dl/go1.21.6.linux-arm64.tar.gz | tar -C /usr/local -xzf -; \ |
|
||||||
elif [ "$arch" = "x86_64" ] || [ "$arch" = "amd64" ]; then \ |
|
||||||
echo "Installing x86_64 version of Go" && \ |
|
||||||
curl -L https://go.dev/dl/go1.21.6.linux-amd64.tar.gz | tar -C /usr/local -xzf -; \ |
|
||||||
else \ |
|
||||||
echo "WARNING: Unknown architecture $arch for Go, defaulting to x86_64" && \ |
|
||||||
curl -L https://go.dev/dl/go1.21.6.linux-amd64.tar.gz | tar -C /usr/local -xzf -; \ |
|
||||||
fi |
|
||||||
ENV PATH="/usr/local/go/bin:${PATH}" |
|
||||||
ENV GOPATH="/go" |
|
||||||
ENV PATH="${GOPATH}/bin:${PATH}" |
|
||||||
|
|
||||||
# Create app user |
|
||||||
RUN useradd -m -s /bin/bash app |
|
||||||
WORKDIR /app |
|
||||||
|
|
||||||
# Copy project files |
|
||||||
COPY --chown=app:app . . |
|
||||||
|
|
||||||
# Create and activate virtual environment |
|
||||||
RUN python3 -m venv /app/.venv |
|
||||||
ENV PATH="/app/.venv/bin:$PATH" |
|
||||||
|
|
||||||
# Install Python dependencies |
|
||||||
RUN pip install --no-cache-dir -r requirements.txt |
|
||||||
|
|
||||||
# Stage 2: Runtime image |
|
||||||
FROM ubuntu:22.04 |
|
||||||
|
|
||||||
# Add metadata about runtime environment |
|
||||||
LABEL org.opencontainers.image.title="AI CodeXchange" |
|
||||||
LABEL org.opencontainers.image.description="Multi-platform AI CodeXchange application" |
|
||||||
LABEL org.opencontainers.image.version="1.0" |
|
||||||
|
|
||||||
# Create platform-specific label at build time |
|
||||||
RUN echo "Building on $(uname -s) $(uname -m) architecture" > /platform-info.txt |
|
||||||
LABEL org.opencontainers.image.platform="$(cat /platform-info.txt)" |
|
||||||
|
|
||||||
# Install runtime dependencies |
|
||||||
ENV DEBIAN_FRONTEND=noninteractive |
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \ |
|
||||||
python3.10 \ |
|
||||||
python3-pip \ |
|
||||||
gcc \ |
|
||||||
g++ \ |
|
||||||
openjdk-17-jdk \ |
|
||||||
curl \ |
|
||||||
nodejs \ |
|
||||||
npm \ |
|
||||||
perl \ |
|
||||||
lua5.3 \ |
|
||||||
php \ |
|
||||||
r-base \ |
|
||||||
ruby \ |
|
||||||
rustc \ |
|
||||||
cargo \ |
|
||||||
mono-complete \ |
|
||||||
mono-devel \ |
|
||||||
mono-mcs \ |
|
||||||
sqlite3 \ |
|
||||||
unzip \ |
|
||||||
&& rm -rf /var/lib/apt/lists/* |
|
||||||
|
|
||||||
# Install TypeScript |
|
||||||
RUN npm install -g typescript |
|
||||||
|
|
||||||
# Install Swift |
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \ |
|
||||||
binutils \ |
|
||||||
libc6-dev \ |
|
||||||
libcurl4 \ |
|
||||||
libedit2 \ |
|
||||||
libgcc-9-dev \ |
|
||||||
libpython3.10 \ |
|
||||||
libsqlite3-0 \ |
|
||||||
libstdc++-9-dev \ |
|
||||||
libxml2 \ |
|
||||||
libz3-dev \ |
|
||||||
pkg-config \ |
|
||||||
tzdata \ |
|
||||||
zlib1g-dev \ |
|
||||||
&& rm -rf /var/lib/apt/lists/* |
|
||||||
|
|
||||||
RUN arch=$(uname -m) && \ |
|
||||||
if [ "$arch" = "x86_64" ]; then \ |
|
||||||
SWIFT_URL="https://download.swift.org/swift-5.9.2-release/ubuntu2204/swift-5.9.2-RELEASE/swift-5.9.2-RELEASE-ubuntu22.04.tar.gz"; \ |
|
||||||
elif [ "$arch" = "aarch64" ] || [ "$arch" = "arm64" ]; then \ |
|
||||||
SWIFT_URL="https://download.swift.org/swift-5.9.2-release/ubuntu2204-aarch64/swift-5.9.2-RELEASE/swift-5.9.2-RELEASE-ubuntu22.04-aarch64.tar.gz"; \ |
|
||||||
else \ |
|
||||||
echo "Unsupported architecture for Swift: $arch"; \ |
|
||||||
exit 1; \ |
|
||||||
fi && \ |
|
||||||
curl -fL $SWIFT_URL | tar xz -C /opt && \ |
|
||||||
ln -s /opt/swift-5.9.2-RELEASE-ubuntu22.04*/usr/bin/swift /usr/local/bin/swift |
|
||||||
|
|
||||||
# Install Kotlin |
|
||||||
RUN KOTLIN_VERSION=1.9.22 && \ |
|
||||||
cd /tmp && \ |
|
||||||
curl -LO "https://github.com/JetBrains/kotlin/releases/download/v${KOTLIN_VERSION}/kotlin-compiler-${KOTLIN_VERSION}.zip" && \ |
|
||||||
unzip "kotlin-compiler-${KOTLIN_VERSION}.zip" -d /opt && \ |
|
||||||
rm "kotlin-compiler-${KOTLIN_VERSION}.zip" && \ |
|
||||||
ln -s "/opt/kotlinc/bin/kotlin" /usr/local/bin/kotlin && \ |
|
||||||
ln -s "/opt/kotlinc/bin/kotlinc" /usr/local/bin/kotlinc |
|
||||||
|
|
||||||
# Install Julia based on architecture (with Windows WSL2 compatibility) |
|
||||||
RUN arch=$(uname -m) && \ |
|
||||||
echo "Detected architecture: $arch" && \ |
|
||||||
if [ "$arch" = "aarch64" ] || [ "$arch" = "arm64" ]; then \ |
|
||||||
echo "Installing ARM64 version of Julia" && \ |
|
||||||
curl -fL https://julialang-s3.julialang.org/bin/linux/aarch64/1.9/julia-1.9.3-linux-aarch64.tar.gz | tar xz -C /opt && \ |
|
||||||
ln -s /opt/julia-1.9.3/bin/julia /usr/local/bin/julia; \ |
|
||||||
elif [ "$arch" = "x86_64" ] || [ "$arch" = "amd64" ]; then \ |
|
||||||
echo "Installing x86_64 version of Julia" && \ |
|
||||||
curl -fL https://julialang-s3.julialang.org/bin/linux/x64/1.9/julia-1.9.3-linux-x86_64.tar.gz | tar xz -C /opt && \ |
|
||||||
ln -s /opt/julia-1.9.3/bin/julia /usr/local/bin/julia; \ |
|
||||||
else \ |
|
||||||
echo "WARNING: Unknown architecture $arch, defaulting to x86_64" && \ |
|
||||||
curl -fL https://julialang-s3.julialang.org/bin/linux/x64/1.9/julia-1.9.3-linux-x86_64.tar.gz | tar xz -C /opt && \ |
|
||||||
ln -s /opt/julia-1.9.3/bin/julia /usr/local/bin/julia; \ |
|
||||||
fi |
|
||||||
|
|
||||||
# Install Go runtime |
|
||||||
COPY --from=builder /usr/local/go /usr/local/go |
|
||||||
ENV PATH="/usr/local/go/bin:${PATH}" |
|
||||||
ENV GOPATH="/go" |
|
||||||
ENV PATH="${GOPATH}/bin:${PATH}" |
|
||||||
|
|
||||||
# Create app user |
|
||||||
RUN useradd -m -s /bin/bash app |
|
||||||
WORKDIR /app |
|
||||||
|
|
||||||
# Copy virtual environment and application files from builder |
|
||||||
COPY --from=builder --chown=app:app /app/.venv /app/.venv |
|
||||||
COPY --from=builder --chown=app:app /app /app |
|
||||||
|
|
||||||
# Set environment variables |
|
||||||
ENV PATH="/app/.venv/bin:$PATH" \ |
|
||||||
PYTHONPATH="/app/src" \ |
|
||||||
PYTHONUNBUFFERED=1 \ |
|
||||||
GRADIO_SERVER_NAME=0.0.0.0 \ |
|
||||||
GRADIO_SERVER_PORT=7860 |
|
||||||
|
|
||||||
# Create necessary directories with correct permissions |
|
||||||
RUN mkdir -p /app/logs /app/downloads \ |
|
||||||
&& chown -R app:app /app/logs /app/downloads |
|
||||||
|
|
||||||
# Verify installations with comprehensive platform information |
|
||||||
RUN echo "======= PLATFORM & LANGUAGE VERIFICATION =======" && \ |
|
||||||
echo "OS: $(uname -s)" && \ |
|
||||||
echo "Architecture: $(uname -m)" && \ |
|
||||||
echo "Kernel: $(uname -r)" && \ |
|
||||||
echo "Host: $(uname -n)" && \ |
|
||||||
echo "\n=== Language Installations ===" && \ |
|
||||||
echo "Node.js: $(node --version 2>/dev/null || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "TypeScript: $(tsc --version 2>/dev/null || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "Java: $(java -version 2>&1 | head -n 1 || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "Julia: $(julia --version 2>/dev/null || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "Go: $(go version 2>/dev/null || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "Python: $(python3 --version 2>/dev/null || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "Perl: $(perl -v 2>/dev/null | head -n 2 || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "Lua: $(lua5.3 -v 2>/dev/null || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "PHP: $(php --version 2>/dev/null | head -n 1 || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "R: $(R --version 2>/dev/null | head -n 1 || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "Ruby: $(ruby --version 2>/dev/null || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "Rust: $(rustc --version 2>/dev/null || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "C#/Mono: $(mono-csc --version 2>/dev/null || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "SQLite: $(sqlite3 --version 2>/dev/null || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "Kotlin: $(kotlinc -version 2>&1 || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "C++: $(g++ --version 2>/dev/null | head -n 1 || echo 'NOT VERIFIED')" && \ |
|
||||||
echo "\n=== Environment Variables ===" && \ |
|
||||||
echo "PATH: $PATH" && \ |
|
||||||
echo "======= VERIFICATION COMPLETE =======" |
|
||||||
|
|
||||||
# Switch to non-root user |
|
||||||
USER app |
|
||||||
|
|
||||||
# Expose port |
|
||||||
EXPOSE 7860 |
|
||||||
|
|
||||||
# Health check |
|
||||||
HEALTHCHECK --interval=30s --timeout=30s --start-period=5s --retries=3 \ |
|
||||||
CMD curl -f http://localhost:7860/healthz || exit 1 |
|
||||||
|
|
||||||
# Set entrypoint and default command |
|
||||||
ENTRYPOINT ["python3"] |
|
||||||
CMD ["run.py"] |
|
@ -1,21 +0,0 @@ |
|||||||
MIT License |
|
||||||
|
|
||||||
Copyright (c) 2025 Blaise Alako |
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy |
|
||||||
of this software and associated documentation files (the "Software"), to deal |
|
||||||
in the Software without restriction, including without limitation the rights |
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell |
|
||||||
copies of the Software, and to permit persons to whom the Software is |
|
||||||
furnished to do so, subject to the following conditions: |
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all |
|
||||||
copies or substantial portions of the Software. |
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR |
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, |
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE |
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER |
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE |
|
||||||
SOFTWARE. |
|
@ -1,39 +0,0 @@ |
|||||||
.PHONY: install run dev docker-build docker-run test clean |
|
||||||
|
|
||||||
# Install project dependencies
|
|
||||||
install: |
|
||||||
pip install -r requirements.txt
|
|
||||||
|
|
||||||
# Run the application
|
|
||||||
run: |
|
||||||
python run.py
|
|
||||||
|
|
||||||
# Run with development settings (enables hot-reloading)
|
|
||||||
dev: |
|
||||||
PYTHON_ENV=development python run.py
|
|
||||||
|
|
||||||
# Build Docker container
|
|
||||||
docker-build: |
|
||||||
docker build -t ai-code-converter .
|
|
||||||
|
|
||||||
# Run Docker container
|
|
||||||
docker-run: |
|
||||||
docker run -p 7860:7860 --env-file .env ai-code-converter
|
|
||||||
|
|
||||||
# Run tests
|
|
||||||
test: |
|
||||||
python -m pytest tests/
|
|
||||||
|
|
||||||
# Clean Python cache and build artifacts
|
|
||||||
clean: |
|
||||||
find . -type d -name "__pycache__" -exec rm -rf {} +
|
|
||||||
find . -type f -name "*.pyc" -delete
|
|
||||||
find . -type f -name "*.pyo" -delete
|
|
||||||
find . -type f -name "*.pyd" -delete
|
|
||||||
find . -type d -name ".pytest_cache" -exec rm -rf {} +
|
|
||||||
find . -type d -name "build" -exec rm -rf {} +
|
|
||||||
find . -type d -name "dist" -exec rm -rf {} +
|
|
||||||
|
|
||||||
# Generate documentation diagrams
|
|
||||||
docs-diagrams: |
|
||||||
cd docs && python -c "import mermaid_generator; mermaid_generator.generate_diagrams()"
|
|
@ -1,191 +0,0 @@ |
|||||||
# CodeXchange AI |
|
||||||
|
|
||||||
[](https://python.org) |
|
||||||
[](LICENSE) |
|
||||||
[](https://github.com/alakob/ai_code_converter/actions/workflows/python-test.yml) |
|
||||||
|
|
||||||
A powerful tool for converting and executing code between different programming languages using AI models. |
|
||||||
|
|
||||||
## Overview |
|
||||||
|
|
||||||
CodeXchangeAI is a Python application that leverages various AI models to translate code between programming languages while maintaining functionality and idiomatic patterns. |
|
||||||
|
|
||||||
### Key Features |
|
||||||
|
|
||||||
- Multi-language code conversion |
|
||||||
- Real-time code execution |
|
||||||
- Multiple AI model support (GPT, Claude, DeepSeek, GROQ, Gemini) |
|
||||||
- File upload/download functionality |
|
||||||
- Syntax highlighting |
|
||||||
- Detailed logging system |
|
||||||
- Docker support |
|
||||||
|
|
||||||
## Quick Start |
|
||||||
|
|
||||||
```bash |
|
||||||
# Clone the repository |
|
||||||
git clone git@github.com:alakob/ai_code_converter.git |
|
||||||
cd ai_code_converter |
|
||||||
|
|
||||||
# Configure environment |
|
||||||
cp .env.example .env |
|
||||||
# Edit .env with your API keys |
|
||||||
|
|
||||||
``` |
|
||||||
|
|
||||||
### Using the Docker Wrapper Script (Recommended) |
|
||||||
|
|
||||||
For a more convenient way to run the application with Docker, you can use the provided wrapper script: |
|
||||||
|
|
||||||
```bash |
|
||||||
# Make the script executable |
|
||||||
chmod +x run-docker.sh |
|
||||||
|
|
||||||
# Run the application |
|
||||||
./run-docker.sh # Build and run normally |
|
||||||
./run-docker.sh -d # Run in detached mode |
|
||||||
./run-docker.sh -p 8080 # Run on port 8080 |
|
||||||
./run-docker.sh -s # Stop the container |
|
||||||
./run-docker.sh -h # Show help message |
|
||||||
``` |
|
||||||
|
|
||||||
## CI/CD Pipeline |
|
||||||
|
|
||||||
CodeXchange AI uses GitHub Actions for continuous integration and deployment. The pipeline includes: |
|
||||||
|
|
||||||
### Automated Testing |
|
||||||
- Runs Python tests on multiple Python versions (3.9, 3.10, 3.11) |
|
||||||
- Performs code linting and style checks |
|
||||||
- Generates test coverage reports |
|
||||||
|
|
||||||
### Docker Image Validation |
|
||||||
- Builds the Docker image to verify Dockerfile integrity |
|
||||||
- Performs vulnerability scanning with Trivy |
|
||||||
- Validates container startup and dependencies |
|
||||||
|
|
||||||
### Deployment Automation |
|
||||||
- Automatically deploys to staging environment when changes are pushed to develop branch |
|
||||||
- Creates production releases with semantic versioning |
|
||||||
- Publishes Docker images to Docker Hub |
|
||||||
|
|
||||||
### Setting Up for Development |
|
||||||
|
|
||||||
To use the CI/CD pipeline in your fork, you'll need to add these secrets to your GitHub repository: |
|
||||||
|
|
||||||
1. `DOCKERHUB_USERNAME`: Your Docker Hub username |
|
||||||
2. `DOCKERHUB_TOKEN`: A Docker Hub access token (not your password) |
|
||||||
|
|
||||||
See the [CI/CD documentation](docs/ci_cd_pipeline.md) for detailed setup instructions. |
|
||||||
|
|
||||||
The wrapper script provides several options for customizing the Docker deployment: |
|
||||||
|
|
||||||
```bash |
|
||||||
Usage: ./run-docker.sh [OPTIONS] |
|
||||||
|
|
||||||
Options: |
|
||||||
-b, --build Build the Docker image without running the container |
|
||||||
-d, --detach Run container in detached mode (background) |
|
||||||
-e, --env FILE Specify an environment file (default: .env) |
|
||||||
-p, --port PORT Specify the port to expose (default: 7860) |
|
||||||
-l, --logs Follow the container logs after starting |
|
||||||
-s, --stop Stop the running container |
|
||||||
-r, --restart Restart the container |
|
||||||
-D, --down Stop and remove the container |
|
||||||
-k, --keys Check for API keys and show setup instructions if missing |
|
||||||
-h, --help Display this help message |
|
||||||
-v, --version Display script version |
|
||||||
``` |
|
||||||
|
|
||||||
Examples: |
|
||||||
- Run on a different port: `./run-docker.sh -p 8080` |
|
||||||
- Run in background: `./run-docker.sh -d` |
|
||||||
- Stop the application: `./run-docker.sh -s` |
|
||||||
- View logs: `./run-docker.sh -l` |
|
||||||
|
|
||||||
The application will be available at `http://localhost:7860` |
|
||||||
|
|
||||||
### Manual Installation |
|
||||||
|
|
||||||
```bash |
|
||||||
# Create and activate virtual environment |
|
||||||
python -m venv .venv |
|
||||||
source .venv/bin/activate # On Windows: .venv\Scripts\activate |
|
||||||
|
|
||||||
# Install dependencies |
|
||||||
pip install -r requirements.txt |
|
||||||
|
|
||||||
# Configure environment |
|
||||||
cp .env.example .env |
|
||||||
# Edit .env with your API keys |
|
||||||
|
|
||||||
# Run the application |
|
||||||
python run.py |
|
||||||
``` |
|
||||||
|
|
||||||
### Using Make Commands |
|
||||||
|
|
||||||
The project includes a Makefile with useful commands to streamline development: |
|
||||||
|
|
||||||
```bash |
|
||||||
# Install dependencies |
|
||||||
make install |
|
||||||
|
|
||||||
# Run the application |
|
||||||
make run |
|
||||||
|
|
||||||
# Run with development settings (hot-reloading) |
|
||||||
make dev |
|
||||||
|
|
||||||
# Build Docker container |
|
||||||
make docker-build |
|
||||||
|
|
||||||
# Run Docker container |
|
||||||
make docker-run |
|
||||||
|
|
||||||
# Or use the Docker wrapper script for more options |
|
||||||
./run-docker.sh |
|
||||||
|
|
||||||
# Run tests |
|
||||||
make test |
|
||||||
|
|
||||||
# Clean Python cache and build artifacts |
|
||||||
make clean |
|
||||||
``` |
|
||||||
|
|
||||||
## Basic Usage |
|
||||||
|
|
||||||
1. Select source and target programming languages |
|
||||||
2. Enter or upload source code |
|
||||||
3. Choose AI model and temperature |
|
||||||
4. Click "Convert" to translate the code |
|
||||||
5. Use "Run" buttons to execute original or converted code |
|
||||||
6. Download the results including compiled binaries (for compiled languages) |
|
||||||
|
|
||||||
## Supported Languages |
|
||||||
|
|
||||||
Currently supports 17 programming languages including Python, JavaScript, Java, C++, Julia, Go, Ruby, Swift, Rust, C#, TypeScript, R, Perl, Lua, PHP, Kotlin, and SQL. |
|
||||||
|
|
||||||
See [Supported Languages](./docs/languages.md) for detailed information on each language. |
|
||||||
|
|
||||||
## Documentation |
|
||||||
|
|
||||||
For detailed documentation, please refer to the [docs](./docs) directory: |
|
||||||
|
|
||||||
- [Supported Languages](./docs/languages.md) - Details on all supported programming languages |
|
||||||
- [Configuration Guide](./docs/configuration.md) - How to configure the application |
|
||||||
- [Development Guide](./docs/development.md) - Guide for developers extending the application |
|
||||||
- [Contributing Guidelines](./docs/contributing.md) - How to contribute to the project |
|
||||||
- [Project Structure](./docs/project_structure.md) - Overview of the codebase architecture |
|
||||||
- [Architecture Diagram](./docs/architecture_diagram.md) - Visual representation of the application architecture |
|
||||||
|
|
||||||
## License |
|
||||||
|
|
||||||
This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details. |
|
||||||
|
|
||||||
## Acknowledgments |
|
||||||
|
|
||||||
- OpenAI for GPT models |
|
||||||
- Anthropic for Claude |
|
||||||
- Google for Gemini |
|
||||||
- DeepSeek and GROQ for their AI models |
|
||||||
- The Gradio team for the web interface framework |
|
@ -0,0 +1,107 @@ |
|||||||
|
{ |
||||||
|
"cells": [ |
||||||
|
{ |
||||||
|
"cell_type": "markdown", |
||||||
|
"metadata": {}, |
||||||
|
"source": [ |
||||||
|
"## codeXchange AI: Transform Code with a Click!\n", |
||||||
|
"\n", |
||||||
|
"**Created by Blaise Alako**\n", |
||||||
|
"\n", |
||||||
|
"Get ready to revolutionize your coding experience with **codeXchange AI**—a web-based Gradio app that converts code between programming languages in a flash! Powered by cutting-edge frontier and open-source LLMs, this tool is a game-changer for beginners diving into new languages, intermediates streamlining projects, and advanced users pushing the limits of innovation. Just paste or upload your code, choose your target language, and watch the magic unfold!\n", |
||||||
|
"\n", |
||||||
|
"**Why codeXchange AI?**\n", |
||||||
|
"- **Effortless**: No downloads—just pure web-based magic.\n", |
||||||
|
"- **Brilliant**: AI-driven conversions that nail accuracy.\n", |
||||||
|
"- **Adaptable**: Add new languages or models with ease.\n", |
||||||
|
"\n", |
||||||
|
"Explore the source code [codeXchange AI](https://github.com/alakob/ai_code_converter) and experience the thrill!\n", |
||||||
|
"\n", |
||||||
|
"---\n", |
||||||
|
"\n", |
||||||
|
"### Table of Contents\n", |
||||||
|
"1. [Explore the Interface](#explore-the-interface)\n", |
||||||
|
"2. [Upload and Convert](#upload-and-convert)\n", |
||||||
|
"3. [See the Results](#see-the-results)\n", |
||||||
|
"4. [Unleash Advanced Features](#unleash-advanced-features)\n", |
||||||
|
"5. [Performance That Wows](#performance-that-wows)\n", |
||||||
|
"6. [Get Started Now](#get-started-now)\n", |
||||||
|
"\n", |
||||||
|
"---\n", |
||||||
|
"\n", |
||||||
|
"### Explore the Interface\n", |
||||||
|
"\n", |
||||||
|
"#### A Sleek Starting Point\n", |
||||||
|
"Step into the world of codeXchange AI with its stunningly simple interface, designed to make your coding journey a breeze!\n", |
||||||
|
"\n", |
||||||
|
" \n", |
||||||
|
"*Screenshot: The app’s clean starting screen, ready for your code.*\n", |
||||||
|
"\n", |
||||||
|
"With options to upload files or pick example snippets, you’re just a click away from transforming your code.\n", |
||||||
|
"\n", |
||||||
|
"---\n", |
||||||
|
"\n", |
||||||
|
"### Upload and Convert\n", |
||||||
|
"\n", |
||||||
|
"#### Load Your Code with Ease\n", |
||||||
|
"Whether you’re a beginner or a pro, uploading your code is a snap. Drag and drop a file, or select a preloaded snippet to kick things off.\n", |
||||||
|
"\n", |
||||||
|
" \n", |
||||||
|
"*Screenshot: The upload section with a dropdown for example snippets.*\n", |
||||||
|
"\n", |
||||||
|
"Choose your input language, pick your target, and hit “Convert”—it’s that easy to bridge the language gap!\n", |
||||||
|
"\n", |
||||||
|
"---\n", |
||||||
|
"\n", |
||||||
|
"### See the Results\n", |
||||||
|
"\n", |
||||||
|
"#### Witness the Transformation\n", |
||||||
|
"Watch codeXchange AI work its magic! It converts your code with precision, adding helpful documentation to make the output crystal clear.\n", |
||||||
|
"\n", |
||||||
|
" \n", |
||||||
|
"*Screenshot: A converted result with documentation, ready to run.*\n", |
||||||
|
"\n", |
||||||
|
"From Python to C++ or beyond, the app ensures your code is ready to shine in its new language.\n", |
||||||
|
"\n", |
||||||
|
"---\n", |
||||||
|
"\n", |
||||||
|
"### Unleash Advanced Features\n", |
||||||
|
"\n", |
||||||
|
"#### Power Up Your Workflow\n", |
||||||
|
"For those who love to tinker, codeXchange AI offers exciting customization! Select different models, adjust the “Temperature” for creative flair, and even add new languages to the mix.\n", |
||||||
|
"\n", |
||||||
|
" \n", |
||||||
|
"*Screenshot: Interface showcasing model selection, temperature slider, and more.*\n", |
||||||
|
"\n", |
||||||
|
"Download your converted code with a single click and take your projects to the next level!\n", |
||||||
|
"\n", |
||||||
|
"---\n", |
||||||
|
"\n", |
||||||
|
"### Performance That Wows\n", |
||||||
|
"\n", |
||||||
|
"#### Speed That Impresses\n", |
||||||
|
"codeXchange AI doesn’t just convert—it optimizes! Check out the performance boost when running your code in a new language, with execution times that’ll leave you amazed.\n", |
||||||
|
"\n", |
||||||
|
" \n", |
||||||
|
"*Screenshot: Execution results highlighting speed improvements.*\n", |
||||||
|
"\n", |
||||||
|
"From 31.49 seconds in Python to just 2.32 seconds in C++—see the difference for yourself!\n", |
||||||
|
"\n", |
||||||
|
"---\n", |
||||||
|
"\n", |
||||||
|
"### Get Started Now\n", |
||||||
|
"\n", |
||||||
|
"Ready to transform your coding game? Jump into [codeXchange AI source code](https://github.com/alakob/ai_code_converter) Convert, run, and download your code in seconds. Whether you’re just starting out, managing complex projects, or innovating at an advanced level, this app is your ultimate coding companion.\n", |
||||||
|
"\n", |
||||||
|
"---\n" |
||||||
|
] |
||||||
|
} |
||||||
|
], |
||||||
|
"metadata": { |
||||||
|
"language_info": { |
||||||
|
"name": "python" |
||||||
|
} |
||||||
|
}, |
||||||
|
"nbformat": 4, |
||||||
|
"nbformat_minor": 2 |
||||||
|
} |
@ -1,23 +0,0 @@ |
|||||||
|
|
||||||
services: |
|
||||||
ai_code_converter: |
|
||||||
build: . |
|
||||||
ports: |
|
||||||
- "${PORT:-7860}:7860" |
|
||||||
volumes: |
|
||||||
- ./logs:/app/logs |
|
||||||
- ./downloads:/app/downloads |
|
||||||
environment: |
|
||||||
- OPENAI_API_KEY=${OPENAI_API_KEY} |
|
||||||
- ANTHROPIC_API_KEY=${ANTHROPIC_API_KEY} |
|
||||||
- GOOGLE_API_KEY=${GOOGLE_API_KEY} |
|
||||||
- DEEPSEEK_API_KEY=${DEEPSEEK_API_KEY} |
|
||||||
- GROQ_API_KEY=${GROQ_API_KEY} |
|
||||||
- PORT=${PORT:-7860} |
|
||||||
healthcheck: |
|
||||||
test: ["CMD", "curl", "-f", "http://localhost:7860/healthz"] |
|
||||||
interval: 30s |
|
||||||
timeout: 30s |
|
||||||
retries: 3 |
|
||||||
start_period: 5s |
|
||||||
restart: unless-stopped |
|
@ -1,12 +0,0 @@ |
|||||||
# CodeXchange AI Documentation |
|
||||||
|
|
||||||
This directory contains comprehensive documentation for the CodeXchange AI project. |
|
||||||
|
|
||||||
## Contents |
|
||||||
|
|
||||||
- [Supported Languages](./languages.md) - Details on all supported programming languages |
|
||||||
- [Configuration Guide](./configuration.md) - How to configure the application |
|
||||||
- [Development Guide](./development.md) - Guide for developers extending the application |
|
||||||
- [Contributing Guidelines](./contributing.md) - How to contribute to the project |
|
||||||
- [Project Structure](./project_structure.md) - Overview of the codebase architecture |
|
||||||
- [Architecture Diagram](./architecture_diagram.md) - Visual representation of the application architecture and component relationships |
|
@ -1,297 +0,0 @@ |
|||||||
# Architecture Diagram |
|
||||||
|
|
||||||
This diagram illustrates the architecture and component relationships of the CodeXchange AI application. |
|
||||||
|
|
||||||
> **Note:** For detailed information about the CI/CD pipeline, see [CI/CD Pipeline Architecture](ci_cd_pipeline.md). |
|
||||||
|
|
||||||
## Application Flow Diagram |
|
||||||
|
|
||||||
```mermaid |
|
||||||
graph TD |
|
||||||
%% Main Entry Points |
|
||||||
A[run.py] --> B[main.py] |
|
||||||
B --> C[CodeConverterApp] |
|
||||||
|
|
||||||
%% Core Components |
|
||||||
C --> D[Gradio UI] |
|
||||||
C --> E[AIModelStreamer] |
|
||||||
C --> F[CodeExecutor] |
|
||||||
C --> G[LanguageDetector] |
|
||||||
C --> H[FileHandler] |
|
||||||
|
|
||||||
%% AI Models |
|
||||||
E --> I[OpenAI GPT] |
|
||||||
E --> J[Anthropic Claude] |
|
||||||
E --> K[Google Gemini] |
|
||||||
E --> L[DeepSeek] |
|
||||||
E --> M[GROQ] |
|
||||||
|
|
||||||
%% Language Processing |
|
||||||
G --> N[Language Validation] |
|
||||||
F --> O[Code Execution] |
|
||||||
|
|
||||||
%% File Operations |
|
||||||
H --> P[File Upload/Download] |
|
||||||
H --> Q[ZIP Creation] |
|
||||||
|
|
||||||
%% Configuration |
|
||||||
R[config.py] --> C |
|
||||||
R --> E |
|
||||||
R --> F |
|
||||||
|
|
||||||
%% Template |
|
||||||
S[template.j2] --> C |
|
||||||
|
|
||||||
%% User Interactions |
|
||||||
D --> T[Code Input] |
|
||||||
D --> U[Language Selection] |
|
||||||
D --> V[Model Selection] |
|
||||||
D --> W[Code Conversion] |
|
||||||
D --> X[Code Execution] |
|
||||||
D --> Y[File Download] |
|
||||||
|
|
||||||
%% Logging |
|
||||||
Z[logger.py] --> C |
|
||||||
Z --> E |
|
||||||
Z --> F |
|
||||||
Z --> G |
|
||||||
Z --> H |
|
||||||
|
|
||||||
%% Styling |
|
||||||
style A fill:#f9d77e,stroke:#333,stroke-width:2px |
|
||||||
style B fill:#f9d77e,stroke:#333,stroke-width:2px |
|
||||||
style C fill:#f9d77e,stroke:#333,stroke-width:2px |
|
||||||
style D fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
style E fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
style F fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
style G fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
style H fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
style I fill:#ffb6c1,stroke:#333,stroke-width:2px |
|
||||||
style J fill:#ffb6c1,stroke:#333,stroke-width:2px |
|
||||||
style K fill:#ffb6c1,stroke:#333,stroke-width:2px |
|
||||||
style L fill:#ffb6c1,stroke:#333,stroke-width:2px |
|
||||||
style M fill:#ffb6c1,stroke:#333,stroke-width:2px |
|
||||||
style R fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style S fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style Z fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
``` |
|
||||||
|
|
||||||
## Component Interaction Sequence |
|
||||||
|
|
||||||
```mermaid |
|
||||||
sequenceDiagram |
|
||||||
participant User |
|
||||||
participant UI as Gradio UI |
|
||||||
participant App as CodeConverterApp |
|
||||||
participant AI as AIModelStreamer |
|
||||||
participant Executor as CodeExecutor |
|
||||||
participant Detector as LanguageDetector |
|
||||||
participant Files as FileHandler |
|
||||||
|
|
||||||
User->>UI: Enter Source Code |
|
||||||
User->>UI: Select Source Language |
|
||||||
User->>UI: Select Target Language |
|
||||||
User->>UI: Select AI Model |
|
||||||
User->>UI: Click Convert |
|
||||||
|
|
||||||
UI->>App: Request Code Conversion |
|
||||||
App->>Detector: Validate Source Language |
|
||||||
Detector-->>App: Validation Result |
|
||||||
|
|
||||||
App->>App: Create Prompt from Template |
|
||||||
App->>AI: Send Prompt to Selected Model |
|
||||||
AI-->>App: Stream Converted Code |
|
||||||
App-->>UI: Display Converted Code |
|
||||||
|
|
||||||
User->>UI: Click Run Original |
|
||||||
UI->>App: Request Code Execution |
|
||||||
App->>Executor: Execute Original Code |
|
||||||
Executor-->>App: Execution Result |
|
||||||
App-->>UI: Display Execution Result |
|
||||||
|
|
||||||
User->>UI: Click Run Converted |
|
||||||
UI->>App: Request Code Execution |
|
||||||
App->>Executor: Execute Converted Code |
|
||||||
Executor-->>App: Execution Result |
|
||||||
App-->>UI: Display Execution Result |
|
||||||
|
|
||||||
User->>UI: Click Download |
|
||||||
UI->>App: Request Download |
|
||||||
App->>Files: Create ZIP with Files |
|
||||||
Files-->>App: ZIP File |
|
||||||
App-->>UI: Provide Download Link |
|
||||||
UI-->>User: Download Files |
|
||||||
``` |
|
||||||
|
|
||||||
## Class Diagram |
|
||||||
|
|
||||||
```mermaid |
|
||||||
classDiagram |
|
||||||
class CodeConverterApp { |
|
||||||
-AIModelStreamer ai_streamer |
|
||||||
-CodeExecutor executor |
|
||||||
-LanguageDetector detector |
|
||||||
-FileHandler file_handler |
|
||||||
-GradioInterface demo |
|
||||||
+__init__() |
|
||||||
+_setup_environment() |
|
||||||
+_initialize_components() |
|
||||||
+_create_gradio_interface() |
|
||||||
+convert_code() |
|
||||||
+execute_code() |
|
||||||
+download_files() |
|
||||||
+run() |
|
||||||
} |
|
||||||
|
|
||||||
class AIModelStreamer { |
|
||||||
-OpenAI openai |
|
||||||
-Anthropic claude |
|
||||||
-OpenAI deepseek |
|
||||||
-OpenAI groq |
|
||||||
-GenerativeModel gemini |
|
||||||
+__init__() |
|
||||||
+stream_gpt() |
|
||||||
+stream_claude() |
|
||||||
+stream_gemini() |
|
||||||
+stream_deepseek() |
|
||||||
+stream_groq() |
|
||||||
+stream_completion() |
|
||||||
} |
|
||||||
|
|
||||||
class CodeExecutor { |
|
||||||
-dict executors |
|
||||||
+__init__() |
|
||||||
+execute() |
|
||||||
+execute_python() |
|
||||||
+execute_javascript() |
|
||||||
+execute_java() |
|
||||||
+execute_cpp() |
|
||||||
+execute_julia() |
|
||||||
+execute_go() |
|
||||||
+execute_ruby() |
|
||||||
+execute_swift() |
|
||||||
+execute_rust() |
|
||||||
+execute_csharp() |
|
||||||
+execute_typescript() |
|
||||||
+execute_r() |
|
||||||
+execute_perl() |
|
||||||
+execute_lua() |
|
||||||
+execute_php() |
|
||||||
+execute_kotlin() |
|
||||||
+execute_sql() |
|
||||||
} |
|
||||||
|
|
||||||
class LanguageDetector { |
|
||||||
+detect_python() |
|
||||||
+detect_javascript() |
|
||||||
+detect_java() |
|
||||||
+detect_cpp() |
|
||||||
+detect_julia() |
|
||||||
+detect_go() |
|
||||||
+detect_ruby() |
|
||||||
+detect_swift() |
|
||||||
+detect_rust() |
|
||||||
+detect_csharp() |
|
||||||
+detect_typescript() |
|
||||||
+detect_r() |
|
||||||
+detect_perl() |
|
||||||
+detect_lua() |
|
||||||
+detect_php() |
|
||||||
+detect_kotlin() |
|
||||||
+detect_sql() |
|
||||||
+validate_language() |
|
||||||
} |
|
||||||
|
|
||||||
class FileHandler { |
|
||||||
+create_readme() |
|
||||||
+create_zip() |
|
||||||
+handle_upload() |
|
||||||
+handle_download() |
|
||||||
} |
|
||||||
|
|
||||||
CodeConverterApp --> AIModelStreamer |
|
||||||
CodeConverterApp --> CodeExecutor |
|
||||||
CodeConverterApp --> LanguageDetector |
|
||||||
CodeConverterApp --> FileHandler |
|
||||||
``` |
|
||||||
|
|
||||||
## Supported Languages and Models |
|
||||||
|
|
||||||
```mermaid |
|
||||||
graph LR |
|
||||||
subgraph "AI Models" |
|
||||||
M1[GPT] |
|
||||||
M2[Claude] |
|
||||||
M3[Gemini] |
|
||||||
M4[DeepSeek] |
|
||||||
M5[GROQ] |
|
||||||
end |
|
||||||
|
|
||||||
subgraph "Supported Languages" |
|
||||||
L1[Python] |
|
||||||
L2[JavaScript] |
|
||||||
L3[Java] |
|
||||||
L4[C++] |
|
||||||
L5[Julia] |
|
||||||
L6[Go] |
|
||||||
L7[Ruby] |
|
||||||
L8[Swift] |
|
||||||
L9[Rust] |
|
||||||
L10[C#] |
|
||||||
L11[TypeScript] |
|
||||||
L12[R] |
|
||||||
L13[Perl] |
|
||||||
L14[Lua] |
|
||||||
L15[PHP] |
|
||||||
L16[Kotlin] |
|
||||||
L17[SQL] |
|
||||||
end |
|
||||||
|
|
||||||
subgraph "Fully Implemented" |
|
||||||
L1 |
|
||||||
L2 |
|
||||||
L3 |
|
||||||
L4 |
|
||||||
L5 |
|
||||||
L6 |
|
||||||
end |
|
||||||
|
|
||||||
subgraph "Template Ready" |
|
||||||
L7 |
|
||||||
L8 |
|
||||||
L9 |
|
||||||
L10 |
|
||||||
L11 |
|
||||||
L12 |
|
||||||
L13 |
|
||||||
L14 |
|
||||||
L15 |
|
||||||
L16 |
|
||||||
L17 |
|
||||||
end |
|
||||||
|
|
||||||
style M1 fill:#ffb6c1,stroke:#333,stroke-width:2px |
|
||||||
style M2 fill:#ffb6c1,stroke:#333,stroke-width:2px |
|
||||||
style M3 fill:#ffb6c1,stroke:#333,stroke-width:2px |
|
||||||
style M4 fill:#ffb6c1,stroke:#333,stroke-width:2px |
|
||||||
style M5 fill:#ffb6c1,stroke:#333,stroke-width:2px |
|
||||||
|
|
||||||
style L1 fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
style L2 fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
style L3 fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
style L4 fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
style L5 fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
style L6 fill:#a8d5ba,stroke:#333,stroke-width:2px |
|
||||||
|
|
||||||
style L7 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style L8 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style L9 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style L10 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style L11 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style L12 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style L13 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style L14 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style L15 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style L16 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
style L17 fill:#d0e0e3,stroke:#333,stroke-width:2px |
|
||||||
``` |
|
@ -1,86 +0,0 @@ |
|||||||
# CI/CD Pipeline Architecture |
|
||||||
|
|
||||||
This document outlines the continuous integration and continuous deployment (CI/CD) pipeline implemented for CodeXchange AI. |
|
||||||
|
|
||||||
## Pipeline Overview |
|
||||||
|
|
||||||
The CI/CD pipeline automates testing, building, and deployment processes using GitHub Actions. It follows a trunk-based development model with protection for the main branch. |
|
||||||
|
|
||||||
```mermaid |
|
||||||
graph TD |
|
||||||
Code[Developer Code] --> PR[Pull Request] |
|
||||||
PR --> Tests[Automated Tests] |
|
||||||
Tests --> DockerBuild[Docker Build & Validation] |
|
||||||
DockerBuild --> |On merge to develop| StagingDeploy[Staging Deployment] |
|
||||||
StagingDeploy --> |On release creation| ProdDeploy[Production Deployment] |
|
||||||
|
|
||||||
%% Pipeline Components |
|
||||||
subgraph "CI Pipeline" |
|
||||||
Tests |
|
||||||
DockerBuild |
|
||||||
end |
|
||||||
|
|
||||||
subgraph "CD Pipeline" |
|
||||||
StagingDeploy |
|
||||||
ProdDeploy |
|
||||||
end |
|
||||||
``` |
|
||||||
|
|
||||||
## Workflow Components |
|
||||||
|
|
||||||
### 1. Python Testing Workflow |
|
||||||
|
|
||||||
The testing workflow (`python-test.yml`) performs: |
|
||||||
- Syntax validation and linting with flake8 |
|
||||||
- Unit and integration tests with pytest |
|
||||||
- Code coverage analysis |
|
||||||
- Matrix testing across Python 3.9, 3.10, and 3.11 |
|
||||||
|
|
||||||
### 2. Docker Build Workflow |
|
||||||
|
|
||||||
The Docker workflow (`docker-build.yml`) performs: |
|
||||||
- Dockerfile validation |
|
||||||
- Container image building |
|
||||||
- Security scanning with Trivy |
|
||||||
- Vulnerability assessment |
|
||||||
|
|
||||||
### 3. Staging Deployment |
|
||||||
|
|
||||||
The staging workflow (`deploy-staging.yml`): |
|
||||||
- Triggered on pushes to the develop branch |
|
||||||
- Builds and tags Docker images with branch name and commit hash |
|
||||||
- Pushes images to Docker Hub |
|
||||||
- Deploys to the staging environment |
|
||||||
|
|
||||||
### 4. Production Deployment |
|
||||||
|
|
||||||
The production workflow (`deploy-production.yml`): |
|
||||||
- Triggered on release publication |
|
||||||
- Builds and tags Docker images with semantic version |
|
||||||
- Pushes images to Docker Hub with version tags |
|
||||||
- Deploys to the production environment with approval gate |
|
||||||
|
|
||||||
## Security Considerations |
|
||||||
|
|
||||||
- Sensitive credentials stored as GitHub Secrets |
|
||||||
- Docker Hub authentication using access tokens, not passwords |
|
||||||
- Security scanning for both code and container images |
|
||||||
- Protected branches requiring CI checks to pass before merging |
|
||||||
|
|
||||||
## Development Workflow |
|
||||||
|
|
||||||
1. Create feature branch from develop |
|
||||||
2. Implement changes with tests |
|
||||||
3. Open pull request to develop |
|
||||||
4. Pass all CI checks |
|
||||||
5. Merge to develop (triggers staging deployment) |
|
||||||
6. Create release for production deployment |
|
||||||
|
|
||||||
## Required Repository Secrets |
|
||||||
|
|
||||||
The following secrets must be configured in the GitHub repository: |
|
||||||
|
|
||||||
| Secret Name | Purpose | |
|
||||||
|-------------|---------| |
|
||||||
| `DOCKERHUB_USERNAME` | Docker Hub username for image publishing | |
|
||||||
| `DOCKERHUB_TOKEN` | Docker Hub authentication token | |
|
@ -1,82 +0,0 @@ |
|||||||
# Configuration Guide |
|
||||||
|
|
||||||
## Environment Variables |
|
||||||
|
|
||||||
Create a `.env` file in the root directory: |
|
||||||
|
|
||||||
```bash |
|
||||||
OPENAI_API_KEY=your_openai_key_here |
|
||||||
ANTHROPIC_API_KEY=your_anthropic_key_here |
|
||||||
GOOGLE_API_KEY=your_google_key_here |
|
||||||
DEEPSEEK_API_KEY=your_deepseek_key_here |
|
||||||
GROQ_API_KEY=your_groq_key_here |
|
||||||
PORT=7860 # Optional, default port for the web interface |
|
||||||
``` |
|
||||||
|
|
||||||
## Model Configuration |
|
||||||
|
|
||||||
Model names are configured in `src/ai_code_converter/config.py`: |
|
||||||
|
|
||||||
```python |
|
||||||
# Model configurations |
|
||||||
OPENAI_MODEL = "gpt-4o-mini" # OpenAI model name |
|
||||||
CLAUDE_MODEL = "claude-3-sonnet-20240307" # Anthropic Claude model |
|
||||||
DEEPSEEK_MODEL = "deepseek-chat" # DeepSeek model |
|
||||||
GEMINI_MODEL = "gemini-1.5-flash" # Google Gemini model |
|
||||||
GROQ_MODEL = "llama3-70b-8192" # GROQ model |
|
||||||
``` |
|
||||||
|
|
||||||
You can modify these values to use different model versions based on your requirements and API access. |
|
||||||
|
|
||||||
## Prerequisites |
|
||||||
|
|
||||||
The following dependencies are required for full functionality: |
|
||||||
|
|
||||||
- Python 3.10+ |
|
||||||
- Node.js and npm (with TypeScript) |
|
||||||
- Java JDK 17+ |
|
||||||
- Julia 1.9+ |
|
||||||
- Go 1.21+ |
|
||||||
- GCC/G++ |
|
||||||
- Perl |
|
||||||
- Lua 5.3+ |
|
||||||
- PHP |
|
||||||
- R |
|
||||||
- Ruby |
|
||||||
- Rust (rustc and cargo) |
|
||||||
- Mono (for C#) |
|
||||||
- Swift 5.9+ |
|
||||||
- Kotlin |
|
||||||
- SQLite3 |
|
||||||
|
|
||||||
Using Docker is recommended as it includes all necessary dependencies. |
|
||||||
|
|
||||||
## Docker Configuration |
|
||||||
|
|
||||||
The application includes Docker support for easy deployment. The `docker-compose.yml` file defines the service configuration: |
|
||||||
|
|
||||||
```yaml |
|
||||||
version: '3' |
|
||||||
services: |
|
||||||
ai_code_converter: |
|
||||||
build: . |
|
||||||
ports: |
|
||||||
- "${PORT:-7860}:7860" |
|
||||||
volumes: |
|
||||||
- ./logs:/app/logs |
|
||||||
env_file: |
|
||||||
- .env |
|
||||||
restart: unless-stopped |
|
||||||
``` |
|
||||||
|
|
||||||
You can customize the port mapping and volume mounts as needed. |
|
||||||
|
|
||||||
## Application Settings |
|
||||||
|
|
||||||
Additional application settings can be configured in `src/ai_code_converter/config.py`: |
|
||||||
|
|
||||||
- UI theme and styling |
|
||||||
- Default language selections |
|
||||||
- Model temperature settings |
|
||||||
- Execution timeouts |
|
||||||
- Logging configuration |
|
@ -1,89 +0,0 @@ |
|||||||
# Contributing Guidelines |
|
||||||
|
|
||||||
Thank you for your interest in contributing to the CodeXchange AI project! This document provides guidelines and instructions for contributing to the project. |
|
||||||
|
|
||||||
## How to Contribute |
|
||||||
|
|
||||||
1. Fork the repository |
|
||||||
2. Create a feature branch (`git checkout -b feature/amazing-feature`) |
|
||||||
3. Commit your changes (`git commit -m 'Add amazing feature'`) |
|
||||||
4. Push to the branch (`git push origin feature/amazing-feature`) |
|
||||||
5. Open a Pull Request |
|
||||||
|
|
||||||
## Development Workflow |
|
||||||
|
|
||||||
1. Check the issues page for open tasks or create a new issue for the feature/bug you want to work on |
|
||||||
2. Assign yourself to the issue |
|
||||||
3. Implement your changes following the best practices outlined below |
|
||||||
4. Write tests for your changes |
|
||||||
5. Update documentation as needed |
|
||||||
6. Submit a pull request referencing the issue |
|
||||||
|
|
||||||
## Best Practices |
|
||||||
|
|
||||||
### Code Style |
|
||||||
|
|
||||||
- Follow existing patterns for consistency |
|
||||||
- Follow PEP 8 style guidelines for Python code |
|
||||||
- Use descriptive variable and function names |
|
||||||
- Add type hints for all new functions |
|
||||||
- Keep functions small and focused on a single responsibility |
|
||||||
- Use docstrings for all public functions and classes |
|
||||||
|
|
||||||
### Error Handling |
|
||||||
|
|
||||||
- Add comprehensive error handling |
|
||||||
- Use specific exception types |
|
||||||
- Provide helpful error messages |
|
||||||
- Log errors with appropriate context |
|
||||||
|
|
||||||
### Logging |
|
||||||
|
|
||||||
- Include detailed logging |
|
||||||
- Use the existing logging framework |
|
||||||
- Log at appropriate levels (DEBUG, INFO, WARNING, ERROR) |
|
||||||
- Include relevant context in log messages |
|
||||||
|
|
||||||
### Documentation |
|
||||||
|
|
||||||
- Update documentation for any changes |
|
||||||
- Document new features, configuration options, and APIs |
|
||||||
- Keep the README and docs directory in sync |
|
||||||
- Use clear, concise language |
|
||||||
|
|
||||||
### Testing |
|
||||||
|
|
||||||
- Write unit tests for new functionality |
|
||||||
- Ensure all tests pass before submitting a PR |
|
||||||
- Test edge cases and error conditions |
|
||||||
- Aim for good test coverage |
|
||||||
|
|
||||||
## Pull Request Process |
|
||||||
|
|
||||||
1. Ensure your code follows the style guidelines |
|
||||||
2. Update documentation as needed |
|
||||||
3. Include tests for new functionality |
|
||||||
4. Link the PR to any related issues |
|
||||||
5. Wait for code review and address any feedback |
|
||||||
|
|
||||||
## Code Review |
|
||||||
|
|
||||||
All submissions require review. We use GitHub pull requests for this purpose: |
|
||||||
|
|
||||||
1. Reviewers will check code quality, test coverage, and documentation |
|
||||||
2. Address any comments or requested changes |
|
||||||
3. Once approved, maintainers will merge your PR |
|
||||||
|
|
||||||
## Acknowledgments |
|
||||||
|
|
||||||
We would like to thank the following organizations and projects that make CodeXchange AI possible: |
|
||||||
|
|
||||||
- OpenAI for GPT models |
|
||||||
- Anthropic for Claude |
|
||||||
- Google for Gemini |
|
||||||
- DeepSeek and GROQ for their AI models |
|
||||||
- The Gradio team for the web interface framework |
|
||||||
|
|
||||||
## License |
|
||||||
|
|
||||||
By contributing to this project, you agree that your contributions will be licensed under the project's MIT License. |
|
@ -1,180 +0,0 @@ |
|||||||
# Development Guide |
|
||||||
|
|
||||||
This guide provides instructions for extending the CodeXchange AI application with new languages and AI models. |
|
||||||
|
|
||||||
Before diving into development, it's recommended to review the [Architecture Diagram](./architecture_diagram.md) to understand the component relationships and application flow. |
|
||||||
|
|
||||||
## Adding New Programming Languages |
|
||||||
|
|
||||||
1. Update Language Configuration (`config.py`): |
|
||||||
```python |
|
||||||
SUPPORTED_LANGUAGES = [..., "NewLanguage"] |
|
||||||
LANGUAGE_MAPPING = {..., "NewLanguage": "language_highlight_name"} |
|
||||||
``` |
|
||||||
|
|
||||||
2. Add Language Detection (`core/language_detection.py`): |
|
||||||
```python |
|
||||||
class LanguageDetector: |
|
||||||
@staticmethod |
|
||||||
def detect_new_language(code: str) -> bool: |
|
||||||
patterns = [r'pattern1', r'pattern2', r'pattern3'] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
``` |
|
||||||
|
|
||||||
3. Add Execution Support (`core/code_execution.py`): |
|
||||||
```python |
|
||||||
def execute_new_language(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.ext', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
file_path = f.name |
|
||||||
try: |
|
||||||
result = subprocess.run( |
|
||||||
["compiler/interpreter", file_path], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
return result.stdout, None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(file_path) |
|
||||||
``` |
|
||||||
|
|
||||||
4. Update the Dockerfile: |
|
||||||
```dockerfile |
|
||||||
# Add necessary dependencies for the new language |
|
||||||
RUN apt-get update && apt-get install -y --no-install-recommends \ |
|
||||||
new-language-package \ |
|
||||||
&& rm -rf /var/lib/apt/lists/* |
|
||||||
|
|
||||||
# Verify the installation |
|
||||||
RUN echo "New Language: $(new-language --version 2>/dev/null || echo 'NOT VERIFIED')" |
|
||||||
``` |
|
||||||
|
|
||||||
5. Update the UI Components in `app.py`: |
|
||||||
```python |
|
||||||
def _initialize_components(self): |
|
||||||
# Add the new language to dropdown options |
|
||||||
self.source_language = gr.Dropdown( |
|
||||||
choices=["Python", "JavaScript", ..., "NewLanguage"], |
|
||||||
... |
|
||||||
) |
|
||||||
self.target_language = gr.Dropdown( |
|
||||||
choices=["Python", "JavaScript", ..., "NewLanguage"], |
|
||||||
... |
|
||||||
) |
|
||||||
``` |
|
||||||
|
|
||||||
6. Add Language-Specific Instructions in `template.j2`: |
|
||||||
```jinja |
|
||||||
{% if target_language == "NewLanguage" %} |
|
||||||
# NewLanguage-specific conversion instructions |
|
||||||
- Follow NewLanguage best practices |
|
||||||
- Use idiomatic NewLanguage patterns |
|
||||||
- Handle NewLanguage-specific edge cases |
|
||||||
{% endif %} |
|
||||||
``` |
|
||||||
|
|
||||||
## Adding New AI Models |
|
||||||
|
|
||||||
1. Update Model Configuration (`config.py`): |
|
||||||
```python |
|
||||||
NEW_MODEL = "model-name-version" |
|
||||||
MODELS = [..., "NewModel"] |
|
||||||
``` |
|
||||||
|
|
||||||
2. Add Model Integration (`models/ai_streaming.py`): |
|
||||||
```python |
|
||||||
def stream_new_model(self, prompt: str) -> Generator[str, None, None]: |
|
||||||
try: |
|
||||||
response = self.new_model_client.generate( |
|
||||||
prompt=prompt, |
|
||||||
stream=True |
|
||||||
) |
|
||||||
reply = "" |
|
||||||
for chunk in response: |
|
||||||
fragment = chunk.text |
|
||||||
reply += fragment |
|
||||||
yield reply |
|
||||||
except Exception as e: |
|
||||||
logger.error(f"New Model API error: {str(e)}", exc_info=True) |
|
||||||
yield f"Error with New Model API: {str(e)}" |
|
||||||
``` |
|
||||||
|
|
||||||
3. Add API Client Initialization: |
|
||||||
```python |
|
||||||
def __init__(self, api_keys: dict): |
|
||||||
# Initialize existing clients |
|
||||||
... |
|
||||||
|
|
||||||
# Initialize new model client |
|
||||||
if "NEW_MODEL_API_KEY" in api_keys: |
|
||||||
self.new_model_client = NewModelClient( |
|
||||||
api_key=api_keys["NEW_MODEL_API_KEY"] |
|
||||||
) |
|
||||||
``` |
|
||||||
|
|
||||||
4. Update the Model Selection Logic: |
|
||||||
```python |
|
||||||
def stream_completion(self, model: str, prompt: str) -> Generator[str, None, None]: |
|
||||||
if model == "NewModel": |
|
||||||
yield from self.stream_new_model(prompt) |
|
||||||
else: |
|
||||||
# Existing model handling |
|
||||||
... |
|
||||||
``` |
|
||||||
|
|
||||||
## Testing |
|
||||||
|
|
||||||
1. Add test cases for new components: |
|
||||||
- Unit tests for language detection |
|
||||||
- Integration tests for code execution |
|
||||||
- End-to-end tests for UI components |
|
||||||
|
|
||||||
2. Test language detection with sample code: |
|
||||||
- Positive examples (valid code in the target language) |
|
||||||
- Negative examples (code from other languages) |
|
||||||
- Edge cases (minimal valid code snippets) |
|
||||||
|
|
||||||
3. Test code execution with various examples: |
|
||||||
- Simple "Hello World" programs |
|
||||||
- Programs with external dependencies |
|
||||||
- Programs with different runtime characteristics |
|
||||||
- Error handling cases |
|
||||||
|
|
||||||
4. Test model streaming with different prompts: |
|
||||||
- Short prompts |
|
||||||
- Long prompts |
|
||||||
- Edge cases (empty prompts, very complex code) |
|
||||||
- Error handling |
|
||||||
|
|
||||||
5. Verify error handling and edge cases: |
|
||||||
- API rate limiting |
|
||||||
- Network failures |
|
||||||
- Invalid inputs |
|
||||||
- Resource constraints |
|
||||||
|
|
||||||
## Logging |
|
||||||
|
|
||||||
The application uses a structured logging system: |
|
||||||
|
|
||||||
- JSON formatted logs with timestamps |
|
||||||
- Stored in `logs` directory |
|
||||||
- Separate console and file logging |
|
||||||
- Detailed execution metrics |
|
||||||
|
|
||||||
To add logging for new components: |
|
||||||
|
|
||||||
```python |
|
||||||
import logging |
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
def new_function(): |
|
||||||
try: |
|
||||||
logger.info("Starting operation", extra={"component": "new_component"}) |
|
||||||
# Function logic |
|
||||||
logger.info("Operation completed", extra={"component": "new_component", "metrics": {...}}) |
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Error: {str(e)}", exc_info=True, extra={"component": "new_component"}) |
|
||||||
``` |
|
@ -1,68 +0,0 @@ |
|||||||
# Supported Languages |
|
||||||
|
|
||||||
CodeXchange AI currently supports the following programming languages: |
|
||||||
|
|
||||||
## Language Support Table |
|
||||||
|
|
||||||
| Language | Execution Method | File Extension | |
|
||||||
|------------|----------------------------------------|----------------| |
|
||||||
| Python | Direct execution in restricted env | .py | |
|
||||||
| JavaScript | Node.js | .js | |
|
||||||
| Java | javac + java | .java | |
|
||||||
| C++ | g++ + executable | .cpp | |
|
||||||
| Julia | julia | .jl | |
|
||||||
| Go | go run | .go | |
|
||||||
| Ruby | ruby | .rb | |
|
||||||
| Swift | swift | .swift | |
|
||||||
| Rust | rustc + executable | .rs | |
|
||||||
| C# | csc (Mono) | .cs | |
|
||||||
| TypeScript | tsc + node | .ts | |
|
||||||
| R | Rscript | .R | |
|
||||||
| Perl | perl | .pl | |
|
||||||
| Lua | lua5.3 | .lua | |
|
||||||
| PHP | php | .php | |
|
||||||
| Kotlin | kotlinc + kotlin | .kt | |
|
||||||
| SQL | sqlite3 | .sql | |
|
||||||
|
|
||||||
## Currently Implemented Languages |
|
||||||
|
|
||||||
While the application has templates and instructions for all the languages listed above, the following languages are currently fully implemented with language detection and execution support: |
|
||||||
|
|
||||||
- Python |
|
||||||
- JavaScript |
|
||||||
- Java |
|
||||||
- C++ |
|
||||||
- Julia |
|
||||||
- Go |
|
||||||
|
|
||||||
## Language-Specific Notes |
|
||||||
|
|
||||||
### Python |
|
||||||
- Executed directly in a restricted environment |
|
||||||
- Supports most standard libraries |
|
||||||
- Execution timeout: 30 seconds |
|
||||||
|
|
||||||
### JavaScript |
|
||||||
- Executed using Node.js |
|
||||||
- Supports ES6+ features |
|
||||||
- No external npm packages are installed during execution |
|
||||||
|
|
||||||
### Java |
|
||||||
- Requires a class with a main method |
|
||||||
- Class name must match filename |
|
||||||
- Compiled with javac before execution |
|
||||||
|
|
||||||
### C++ |
|
||||||
- Compiled with g++ |
|
||||||
- Standard C++17 support |
|
||||||
- Execution timeout: 30 seconds |
|
||||||
|
|
||||||
### Julia |
|
||||||
- Executed with the julia interpreter |
|
||||||
- Supports Julia 1.9+ |
|
||||||
- Limited package support during execution |
|
||||||
|
|
||||||
### Go |
|
||||||
- Executed with go run |
|
||||||
- Supports Go 1.21+ |
|
||||||
- Standard library support only |
|
@ -1,108 +0,0 @@ |
|||||||
# Project Structure |
|
||||||
|
|
||||||
This document provides an overview of the CodeXchange AI project structure and architecture. |
|
||||||
|
|
||||||
For a visual representation of the application architecture and component relationships, please refer to the [Architecture Diagram](./architecture_diagram.md). |
|
||||||
|
|
||||||
## Directory Structure |
|
||||||
|
|
||||||
``` |
|
||||||
ai_code_converter/ |
|
||||||
├── README.md # Project documentation |
|
||||||
├── requirements.txt # Python dependencies |
|
||||||
├── run.py # Application entry point |
|
||||||
├── Dockerfile # Docker configuration |
|
||||||
├── docker-compose.yml # Docker Compose configuration |
|
||||||
├── .env.example # Environment variables template |
|
||||||
├── docs/ # Detailed documentation |
|
||||||
└── src/ # Source code directory |
|
||||||
└── ai_code_converter/ |
|
||||||
├── main.py # Main application logic |
|
||||||
├── app.py # Gradio interface setup |
|
||||||
├── config.py # Model and app configuration |
|
||||||
├── template.j2 # Prompt template |
|
||||||
├── core/ # Core functionality |
|
||||||
│ ├── __init__.py |
|
||||||
│ ├── language_detection.py # Language validation |
|
||||||
│ └── code_execution.py # Code execution |
|
||||||
├── models/ # AI model integration |
|
||||||
│ ├── __init__.py |
|
||||||
│ └── ai_streaming.py # API clients and streaming |
|
||||||
└── utils/ # Utility functions |
|
||||||
├── __init__.py |
|
||||||
└── logging.py # Logging configuration |
|
||||||
``` |
|
||||||
|
|
||||||
## Component Descriptions |
|
||||||
|
|
||||||
### Entry Points |
|
||||||
|
|
||||||
- **run.py**: The main entry point for the application. It imports and initializes the necessary modules and starts the application. |
|
||||||
|
|
||||||
- **main.py**: Contains the main application logic, initializes the application components, and starts the Gradio interface. |
|
||||||
|
|
||||||
### Core Components |
|
||||||
|
|
||||||
- **app.py**: Sets up the Gradio interface and defines UI components. Contains the `CodeConverterApp` class that handles the UI and code conversion logic. |
|
||||||
|
|
||||||
- **config.py**: Contains configuration for models, languages, and application settings. Defines supported languages, model names, and UI styling. |
|
||||||
|
|
||||||
- **template.j2**: A Jinja2 template used to create prompts for the LLMs with language-specific instructions for code conversion. |
|
||||||
|
|
||||||
### Core Directory |
|
||||||
|
|
||||||
The `core` directory contains modules for core functionality: |
|
||||||
|
|
||||||
- **language_detection.py**: Contains the `LanguageDetector` class with static methods to validate if code matches the expected language patterns. |
|
||||||
|
|
||||||
- **code_execution.py**: Handles the execution of code in different programming languages. Contains language-specific execution methods. |
|
||||||
|
|
||||||
### Models Directory |
|
||||||
|
|
||||||
The `models` directory contains modules for AI model integration: |
|
||||||
|
|
||||||
- **ai_streaming.py**: Handles API calls to various LLMs (GPT, Claude, Gemini, DeepSeek, GROQ). Contains methods for streaming responses from different AI providers. |
|
||||||
|
|
||||||
### Utils Directory |
|
||||||
|
|
||||||
The `utils` directory contains utility modules: |
|
||||||
|
|
||||||
- **logging.py**: Configures the logging system for the application. Sets up console and file handlers with appropriate formatting. |
|
||||||
|
|
||||||
## Application Flow |
|
||||||
|
|
||||||
1. **Initialization**: |
|
||||||
- `run.py` imports the main module |
|
||||||
- `main.py` initializes the application components |
|
||||||
- `app.py` sets up the Gradio interface |
|
||||||
|
|
||||||
2. **User Interaction**: |
|
||||||
- User selects source and target languages |
|
||||||
- User enters or uploads source code |
|
||||||
- User selects AI model and temperature |
|
||||||
- User clicks "Convert" |
|
||||||
|
|
||||||
3. **Code Conversion**: |
|
||||||
- Source language is validated using `language_detection.py` |
|
||||||
- Prompt is created using `template.j2` |
|
||||||
- AI model is called using `ai_streaming.py` |
|
||||||
- Response is streamed back to the UI |
|
||||||
|
|
||||||
4. **Code Execution** (optional): |
|
||||||
- User clicks "Run" on original or converted code |
|
||||||
- Code is executed using appropriate method in `code_execution.py` |
|
||||||
- Output is displayed in the UI |
|
||||||
|
|
||||||
## Design Patterns |
|
||||||
|
|
||||||
- **Singleton Pattern**: Used for API clients to ensure only one instance exists |
|
||||||
- **Factory Pattern**: Used for creating language-specific execution methods |
|
||||||
- **Strategy Pattern**: Used for selecting the appropriate AI model |
|
||||||
- **Observer Pattern**: Used for streaming responses from AI models |
|
||||||
|
|
||||||
## Dependencies |
|
||||||
|
|
||||||
- **Gradio**: Web interface framework |
|
||||||
- **Jinja2**: Template engine for creating prompts |
|
||||||
- **OpenAI, Anthropic, Google, DeepSeek, GROQ APIs**: AI model providers |
|
||||||
- **Various language interpreters and compilers**: For code execution |
|
@ -1,332 +0,0 @@ |
|||||||
import gradio as gr |
|
||||||
|
|
||||||
# Define custom CSS with dark theme fixes, updated to use html.dark |
|
||||||
custom_css = """ |
|
||||||
/* Root variables for light theme */ |
|
||||||
:root { |
|
||||||
--background: #ffffff; |
|
||||||
--secondary-background: #f7f7f7; |
|
||||||
--tertiary-background: #f0f0f0; |
|
||||||
--text: #000000; |
|
||||||
--secondary-text: #5d5d5d; |
|
||||||
--border: #e0e0e0; |
|
||||||
--accent: #ff7b2c; |
|
||||||
--accent-hover: #ff6a14; |
|
||||||
--button-text: #ffffff; |
|
||||||
--code-bg: #f7f7f7; |
|
||||||
--code-text: #000000; |
|
||||||
--dropdown-bg: #ffffff; |
|
||||||
--slider-track: #e0e0e0; |
|
||||||
--slider-thumb: #ff7b2c; |
|
||||||
--collapsible-header: #f0f0f0; |
|
||||||
--primary-button-bg: #4a6ee0; /* Blue */ |
|
||||||
--primary-button-hover: #3a5ec8; |
|
||||||
--secondary-button-bg: #444444; |
|
||||||
--secondary-button-hover: #555555; |
|
||||||
--danger-button-bg: #e74c3c; /* Red */ |
|
||||||
--danger-button-hover: #c0392b; |
|
||||||
--success-button-bg: #e67e22; /* Orange */ |
|
||||||
--success-button-hover: #d35400; |
|
||||||
} |
|
||||||
|
|
||||||
/* Dark theme variables using html.dark */ |
|
||||||
html.dark { |
|
||||||
--background: #1a1a1a; |
|
||||||
--secondary-background: #252525; |
|
||||||
--tertiary-background: #2a2a2a; |
|
||||||
--text: #ffffff; |
|
||||||
--secondary-text: #cccccc; |
|
||||||
--border: #444444; |
|
||||||
--accent: #ff7b2c; |
|
||||||
--accent-hover: #ff6a14; |
|
||||||
--button-text: #ffffff; |
|
||||||
--code-bg: #252525; |
|
||||||
--code-text: #ffffff; |
|
||||||
--dropdown-bg: #2a2a2a; |
|
||||||
--slider-track: #444444; |
|
||||||
--slider-thumb: #ff7b2c; |
|
||||||
--collapsible-header: #333333; |
|
||||||
--primary-button-bg: #4a6ee0; |
|
||||||
--primary-button-hover: #3a5ec8; |
|
||||||
--secondary-button-bg: #444444; |
|
||||||
--secondary-button-hover: #555555; |
|
||||||
--danger-button-bg: #e74c3c; |
|
||||||
--danger-button-hover: #c0392b; |
|
||||||
--success-button-bg: #e67e22; |
|
||||||
--success-button-hover: #d35400; |
|
||||||
} |
|
||||||
|
|
||||||
/* Base styles */ |
|
||||||
body { |
|
||||||
background-color: var(--background) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
transition: all 0.3s ease; |
|
||||||
} |
|
||||||
|
|
||||||
.gradio-container { |
|
||||||
background-color: var(--background) !important; |
|
||||||
max-width: 100% !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Headers */ |
|
||||||
h1, h2, h3, h4, h5, h6, .gr-header { |
|
||||||
color: var(--text) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Panels and blocks */ |
|
||||||
.gr-panel, .gr-form, .gr-box, .gr-block { |
|
||||||
background-color: var(--secondary-background) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
border-color: var(--border) !important; |
|
||||||
border-radius: 6px !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Validation messages section */ |
|
||||||
.gr-accordion .gr-panel { |
|
||||||
background-color: var(--secondary-background) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
border-color: #e74c3c !important; /* Red border */ |
|
||||||
} |
|
||||||
|
|
||||||
.gr-accordion-header { |
|
||||||
background-color: var(--collapsible-header) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Code editors */ |
|
||||||
.codebox, .code-editor, .cm-editor { |
|
||||||
background-color: var(--code-bg) !important; |
|
||||||
color: var(--code-text) !important; |
|
||||||
border: 1px solid var(--border) !important; |
|
||||||
border-radius: 4px !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Syntax highlighting */ |
|
||||||
.cm-editor .cm-content, .cm-editor .cm-line { |
|
||||||
color: var(--code-text) !important; |
|
||||||
} |
|
||||||
.cm-editor .cm-keyword { color: #ff79c6 !important; } /* Pink */ |
|
||||||
.cm-editor .cm-number { color: #bd93f9 !important; } /* Purple */ |
|
||||||
.cm-editor .cm-string { color: #f1fa8c !important; } /* Yellow */ |
|
||||||
.cm-editor .cm-comment { color: #6272a4 !important; } /* Gray */ |
|
||||||
|
|
||||||
/* Buttons */ |
|
||||||
.gr-button { |
|
||||||
background-color: var(--tertiary-background) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
border-color: var(--border) !important; |
|
||||||
border-radius: 4px !important; |
|
||||||
} |
|
||||||
.gr-button.success { |
|
||||||
background-color: var(--success-button-bg) !important; |
|
||||||
color: var(--button-text) !important; |
|
||||||
} |
|
||||||
.gr-button.success:hover { |
|
||||||
background-color: var(--success-button-hover) !important; |
|
||||||
} |
|
||||||
.gr-button.danger { |
|
||||||
background-color: var(--danger-button-bg) !important; |
|
||||||
color: var(--button-text) !important; |
|
||||||
} |
|
||||||
.gr-button.danger:hover { |
|
||||||
background-color: var(--danger-button-hover) !important; |
|
||||||
} |
|
||||||
.gr-button.secondary { |
|
||||||
background-color: var(--secondary-button-bg) !important; |
|
||||||
color: var(--button-text) !important; |
|
||||||
} |
|
||||||
.gr-button.secondary:hover { |
|
||||||
background-color: var(--secondary-button-hover) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* File upload */ |
|
||||||
.gr-file, .gr-file-upload { |
|
||||||
background-color: var(--secondary-background) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
border-color: var(--border) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Dropdowns */ |
|
||||||
.gr-dropdown, .gr-dropdown-container, .gr-dropdown select, .gr-dropdown option { |
|
||||||
background-color: var(--dropdown-bg) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
border-color: var(--border) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Slider */ |
|
||||||
.gr-slider { |
|
||||||
background-color: var(--background) !important; |
|
||||||
} |
|
||||||
.gr-slider-track { |
|
||||||
background-color: var(--slider-track) !important; |
|
||||||
} |
|
||||||
.gr-slider-handle { |
|
||||||
background-color: var(--slider-thumb) !important; |
|
||||||
} |
|
||||||
.gr-slider-value { |
|
||||||
color: var(--text) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Code output */ |
|
||||||
.gr-code { |
|
||||||
background-color: var(--code-bg) !important; |
|
||||||
color: var(--code-text) !important; |
|
||||||
border-color: var(--border) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Footer */ |
|
||||||
.footer { |
|
||||||
color: var(--secondary-text) !important; |
|
||||||
} |
|
||||||
.footer a { |
|
||||||
color: var(--accent) !important; |
|
||||||
} |
|
||||||
""" |
|
||||||
|
|
||||||
# JavaScript for theme toggling and initialization |
|
||||||
js_code = """ |
|
||||||
<script> |
|
||||||
function toggleTheme(theme) { |
|
||||||
var url = new URL(window.location.href); |
|
||||||
if (theme === "dark") { |
|
||||||
url.searchParams.set('__theme', 'dark'); |
|
||||||
} else { |
|
||||||
url.searchParams.delete('__theme'); |
|
||||||
} |
|
||||||
window.location.href = url.href; |
|
||||||
} |
|
||||||
|
|
||||||
// Set the radio button based on current theme |
|
||||||
document.addEventListener('DOMContentLoaded', function() { |
|
||||||
var urlParams = new URLSearchParams(window.location.search); |
|
||||||
var currentTheme = urlParams.get('__theme'); |
|
||||||
if (currentTheme === 'dark') { |
|
||||||
document.querySelector('#theme_radio_container input[value="dark"]').checked = true; |
|
||||||
} else { |
|
||||||
document.querySelector('#theme_radio_container input[value="light"]').checked = true; |
|
||||||
} |
|
||||||
}); |
|
||||||
</script> |
|
||||||
""" |
|
||||||
|
|
||||||
# Language and model options |
|
||||||
INPUT_LANGUAGES = ["Python", "JavaScript", "Java", "TypeScript", "Swift", "C#", "Ruby", "Go", "Rust", "PHP"] |
|
||||||
OUTPUT_LANGUAGES = ["Python", "JavaScript", "Java", "TypeScript", "Swift", "C#", "Ruby", "Go", "Rust", "PHP", "Julia"] |
|
||||||
MODELS = ["GPT", "Claude", "CodeLlama", "Llama", "Gemini"] |
|
||||||
DOC_STYLES = ["standard", "detailed", "minimal"] |
|
||||||
|
|
||||||
# Build the interface |
|
||||||
with gr.Blocks(css=custom_css, theme=gr.themes.Base()) as demo: |
|
||||||
# Inject the JavaScript code |
|
||||||
gr.HTML(js_code) |
|
||||||
|
|
||||||
# States for dynamic button text |
|
||||||
input_lang_state = gr.State("Python") |
|
||||||
output_lang_state = gr.State("JavaScript") |
|
||||||
|
|
||||||
# Header |
|
||||||
with gr.Row(elem_classes="header-container"): |
|
||||||
gr.HTML("<h1 class='header-title'>AI CodeXchange</h1>") |
|
||||||
# Theme selection radio and apply button |
|
||||||
theme_radio = gr.Radio(["light", "dark"], label="Theme", elem_id="theme_radio_container", value="dark") |
|
||||||
theme_button = gr.Button("Apply Theme") |
|
||||||
|
|
||||||
# Validation Messages |
|
||||||
with gr.Accordion("Validation Messages", open=True): |
|
||||||
with gr.Row(): |
|
||||||
with gr.Column(): |
|
||||||
input_code = gr.Code(language="python", label="Code In", lines=15, elem_classes="code-container") |
|
||||||
with gr.Column(): |
|
||||||
output_code = gr.Code(language="javascript", label="Converted Code", lines=15, elem_classes="code-container") |
|
||||||
|
|
||||||
# Configuration Options |
|
||||||
with gr.Row(): |
|
||||||
input_lang = gr.Dropdown(INPUT_LANGUAGES, label="Code In", value="Python") |
|
||||||
output_lang = gr.Dropdown(OUTPUT_LANGUAGES, label="Code Out", value="JavaScript") |
|
||||||
model = gr.Dropdown(MODELS, label="Model", value="GPT") |
|
||||||
temperature = gr.Slider(minimum=0, maximum=1, step=0.1, value=0.7, label="Temperature") |
|
||||||
|
|
||||||
# Document Options |
|
||||||
with gr.Row(): |
|
||||||
document_check = gr.Checkbox(label="Document", value=True) |
|
||||||
doc_style = gr.Dropdown(DOC_STYLES, label="Document Style", value="standard") |
|
||||||
|
|
||||||
# File Upload |
|
||||||
with gr.Accordion("Upload", open=True): |
|
||||||
file_upload = gr.File(label="Drop File Here - or - Click to Upload") |
|
||||||
|
|
||||||
# Action Buttons |
|
||||||
with gr.Row(elem_classes="button-row"): |
|
||||||
convert_btn = gr.Button("Convert", elem_classes="success") |
|
||||||
clear_btn = gr.Button("Clear All", elem_classes="danger") |
|
||||||
|
|
||||||
# Run Buttons |
|
||||||
with gr.Row(elem_classes="button-row"): |
|
||||||
run_source = gr.Button("Run Source Code", elem_classes="secondary") |
|
||||||
run_target = gr.Button("Run Target Code", elem_classes="secondary") |
|
||||||
|
|
||||||
# Results |
|
||||||
with gr.Row(): |
|
||||||
source_result = gr.Code(label="Source Code Result", language="python", lines=10, elem_classes="code-container") |
|
||||||
target_result = gr.Code(label="Converted Code Result", language="javascript", lines=10, elem_classes="code-container") |
|
||||||
|
|
||||||
# Download |
|
||||||
with gr.Accordion("Download", open=True): |
|
||||||
with gr.Row(): |
|
||||||
dl_source = gr.Button("Download Source Code") |
|
||||||
dl_target = gr.Button("Download Converted Code") |
|
||||||
|
|
||||||
# Footer |
|
||||||
with gr.Row(elem_classes="footer"): |
|
||||||
gr.HTML("<div>Use via API</div><div>•</div><div>Built with Gradio</div><div>•</div><div>Settings</div>") |
|
||||||
|
|
||||||
# Theme toggle event |
|
||||||
theme_button.click( |
|
||||||
fn=None, |
|
||||||
inputs=None, |
|
||||||
outputs=[], |
|
||||||
js=""" |
|
||||||
var theme = document.querySelector('#theme_radio_container input:checked').value; |
|
||||||
toggleTheme(theme); |
|
||||||
""" |
|
||||||
) |
|
||||||
|
|
||||||
# Existing event handlers |
|
||||||
def convert_code(input_code, in_lang, out_lang, model, temp, doc, doc_style): |
|
||||||
return f"// Converted from {in_lang} to {out_lang} using {model}\n// Temperature: {temp}\n// Documentation: {doc} ({doc_style if doc else 'N/A'})" |
|
||||||
|
|
||||||
convert_btn.click(fn=convert_code, inputs=[input_code, input_lang_state, output_lang_state, model, temperature, document_check, doc_style], outputs=[output_code]) |
|
||||||
|
|
||||||
def update_convert_btn_text(in_lang, out_lang): |
|
||||||
return f"Convert {in_lang} to {out_lang}", in_lang, out_lang |
|
||||||
|
|
||||||
input_lang.change(fn=update_convert_btn_text, inputs=[input_lang, output_lang], outputs=[convert_btn, input_lang_state, output_lang_state]) |
|
||||||
output_lang.change(fn=update_convert_btn_text, inputs=[input_lang, output_lang], outputs=[convert_btn, input_lang_state, output_lang_state]) |
|
||||||
|
|
||||||
def update_run_btn_text(in_lang, out_lang): |
|
||||||
return f"Run {in_lang}", f"Run {out_lang}" |
|
||||||
|
|
||||||
input_lang.change(fn=update_run_btn_text, inputs=[input_lang, output_lang], outputs=[run_source, run_target]) |
|
||||||
output_lang.change(fn=update_run_btn_text, inputs=[input_lang, output_lang], outputs=[run_source, run_target]) |
|
||||||
|
|
||||||
def clear_all(): |
|
||||||
return "", "", "", "" |
|
||||||
|
|
||||||
clear_btn.click(fn=clear_all, inputs=[], outputs=[input_code, output_code, source_result, target_result]) |
|
||||||
|
|
||||||
def run_code(code, lang): |
|
||||||
return f"// Running {lang} code...\n// Results would appear here" |
|
||||||
|
|
||||||
run_source.click(fn=run_code, inputs=[input_code, input_lang_state], outputs=[source_result]) |
|
||||||
run_target.click(fn=run_code, inputs=[output_code, output_lang_state], outputs=[target_result]) |
|
||||||
|
|
||||||
def handle_file_upload(file): |
|
||||||
if file is None: |
|
||||||
return "" |
|
||||||
with open(file.name, "r") as f: |
|
||||||
return f.read() |
|
||||||
|
|
||||||
file_upload.change(fn=handle_file_upload, inputs=[file_upload], outputs=[input_code]) |
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
demo.launch() |
|
@ -1,6 +0,0 @@ |
|||||||
[pytest] |
|
||||||
testpaths = tests |
|
||||||
python_files = test_*.py |
|
||||||
python_classes = Test* |
|
||||||
python_functions = test_* |
|
||||||
addopts = --cov=src/ai_code_converter --cov-report=term --cov-report=xml -v |
|
@ -1,81 +0,0 @@ |
|||||||
openai>=1.0.0 |
|
||||||
anthropic>=0.3.0 |
|
||||||
google-generativeai>=0.1.0 |
|
||||||
python-dotenv>=1.0.0 |
|
||||||
jinja2>=3.0.0 |
|
||||||
aiofiles==23.2.1 |
|
||||||
annotated-types==0.7.0 |
|
||||||
anthropic==0.49.0 |
|
||||||
anyio==4.8.0 |
|
||||||
cachetools==5.5.1 |
|
||||||
certifi==2025.1.31 |
|
||||||
charset-normalizer==3.4.1 |
|
||||||
click==8.1.8 |
|
||||||
distro==1.9.0 |
|
||||||
exceptiongroup==1.2.2 |
|
||||||
fastapi==0.115.8 |
|
||||||
ffmpy==0.5.0 |
|
||||||
filelock==3.17.0 |
|
||||||
fsspec==2025.2.0 |
|
||||||
google-ai-generativelanguage==0.6.15 |
|
||||||
google-api-core==2.24.1 |
|
||||||
google-api-python-client==2.160.0 |
|
||||||
google-auth==2.38.0 |
|
||||||
google-auth-httplib2==0.2.0 |
|
||||||
google-generativeai==0.8.4 |
|
||||||
googleapis-common-protos==1.66.0 |
|
||||||
gradio>=4.0.0 |
|
||||||
gradio_client==1.7.0 |
|
||||||
grpcio==1.70.0 |
|
||||||
grpcio-status==1.70.0 |
|
||||||
h11==0.14.0 |
|
||||||
httpcore==1.0.7 |
|
||||||
httplib2==0.22.0 |
|
||||||
httpx==0.28.1 |
|
||||||
huggingface-hub==0.28.1 |
|
||||||
idna==3.10 |
|
||||||
Jinja2==3.1.5 |
|
||||||
jiter==0.8.2 |
|
||||||
markdown-it-py==3.0.0 |
|
||||||
MarkupSafe==2.1.5 |
|
||||||
mdurl==0.1.2 |
|
||||||
numpy==2.2.2 |
|
||||||
openai==1.61.1 |
|
||||||
orjson==3.10.15 |
|
||||||
packaging==24.2 |
|
||||||
pandas==2.2.3 |
|
||||||
pillow==11.1.0 |
|
||||||
proto-plus==1.26.0 |
|
||||||
protobuf==5.29.3 |
|
||||||
pyasn1==0.6.1 |
|
||||||
pyasn1_modules==0.4.1 |
|
||||||
pydantic==2.10.6 |
|
||||||
pydantic-settings==2.7.1 |
|
||||||
pydantic_core==2.27.2 |
|
||||||
pydub==0.25.1 |
|
||||||
Pygments==2.19.1 |
|
||||||
pyparsing==3.2.1 |
|
||||||
python-dateutil==2.9.0.post0 |
|
||||||
python-dotenv==1.0.1 |
|
||||||
python-multipart==0.0.20 |
|
||||||
pytz==2025.1 |
|
||||||
PyYAML==6.0.2 |
|
||||||
requests==2.32.3 |
|
||||||
rich==13.9.4 |
|
||||||
rsa==4.9 |
|
||||||
ruff==0.9.6 |
|
||||||
safehttpx==0.1.6 |
|
||||||
semantic-version==2.10.0 |
|
||||||
shellingham==1.5.4 |
|
||||||
six==1.17.0 |
|
||||||
sniffio==1.3.1 |
|
||||||
starlette==0.45.3 |
|
||||||
tomlkit==0.13.2 |
|
||||||
tqdm==4.67.1 |
|
||||||
typer==0.15.1 |
|
||||||
typing_extensions==4.12.2 |
|
||||||
tzdata==2025.1 |
|
||||||
uritemplate==4.1.1 |
|
||||||
urllib3==2.3.0 |
|
||||||
uvicorn==0.34.0 |
|
||||||
websockets==14.2 |
|
@ -1,318 +0,0 @@ |
|||||||
#!/bin/bash |
|
||||||
# |
|
||||||
# CodeXchange AI Docker Wrapper Script |
|
||||||
# This script simplifies running the CodeXchange AI application using Docker. |
|
||||||
# |
|
||||||
|
|
||||||
set -e |
|
||||||
|
|
||||||
# Color codes for terminal output |
|
||||||
GREEN='\033[0;32m' |
|
||||||
YELLOW='\033[0;33m' |
|
||||||
RED='\033[0;31m' |
|
||||||
BLUE='\033[0;34m' |
|
||||||
NC='\033[0m' # No Color |
|
||||||
|
|
||||||
# Script version |
|
||||||
VERSION="1.0.0" |
|
||||||
|
|
||||||
# Default values |
|
||||||
ENV_FILE=".env" |
|
||||||
PORT=7860 |
|
||||||
BUILD_ONLY=false |
|
||||||
DETACHED=false |
|
||||||
FOLLOW_LOGS=false |
|
||||||
STOP=false |
|
||||||
RESTART=false |
|
||||||
DOWN=false |
|
||||||
API_KEY_REMIND=false |
|
||||||
|
|
||||||
# Display script banner |
|
||||||
display_banner() { |
|
||||||
echo -e "${BLUE}" |
|
||||||
echo "╔═══════════════════════════════════════════════════╗" |
|
||||||
echo "║ CodeXchange AI - Docker Launcher ║" |
|
||||||
echo "╚═══════════════════════════════════════════════════╝" |
|
||||||
echo -e "${NC}" |
|
||||||
} |
|
||||||
|
|
||||||
# Display help message |
|
||||||
display_help() { |
|
||||||
echo -e "Usage: $0 [OPTIONS]" |
|
||||||
echo |
|
||||||
echo "Options:" |
|
||||||
echo " -b, --build Build the Docker image without running the container" |
|
||||||
echo " -d, --detach Run container in detached mode (background)" |
|
||||||
echo " -e, --env FILE Specify an environment file (default: .env)" |
|
||||||
echo " -p, --port PORT Specify the port to expose (default: 7860)" |
|
||||||
echo " -l, --logs Follow the container logs after starting" |
|
||||||
echo " -s, --stop Stop the running container" |
|
||||||
echo " -r, --restart Restart the container" |
|
||||||
echo " -D, --down Stop and remove the container" |
|
||||||
echo " -k, --keys Check for API keys and show setup instructions if missing" |
|
||||||
echo " -h, --help Display this help message" |
|
||||||
echo " -v, --version Display script version" |
|
||||||
echo |
|
||||||
echo "Examples:" |
|
||||||
echo " $0 Build and run the container" |
|
||||||
echo " $0 -d -p 8080 Run in detached mode on port 8080" |
|
||||||
echo " $0 -b Build the image only" |
|
||||||
echo " $0 -s Stop the running container" |
|
||||||
echo |
|
||||||
} |
|
||||||
|
|
||||||
# Check prerequisites |
|
||||||
check_prerequisites() { |
|
||||||
echo -e "${BLUE}Checking prerequisites...${NC}" |
|
||||||
|
|
||||||
# Check for Docker |
|
||||||
if ! command -v docker &> /dev/null; then |
|
||||||
echo -e "${RED}Error: Docker is not installed or not in PATH.${NC}" |
|
||||||
echo "Please install Docker to continue: https://docs.docker.com/get-docker/" |
|
||||||
exit 1 |
|
||||||
fi |
|
||||||
|
|
||||||
# Check for docker-compose |
|
||||||
if ! command -v docker-compose &> /dev/null; then |
|
||||||
echo -e "${YELLOW}Warning: docker-compose not found. Checking for Docker Compose V2...${NC}" |
|
||||||
if ! docker compose version &> /dev/null; then |
|
||||||
echo -e "${RED}Error: Docker Compose not found.${NC}" |
|
||||||
echo "Please install Docker Compose to continue: https://docs.docker.com/compose/install/" |
|
||||||
exit 1 |
|
||||||
else |
|
||||||
echo -e "${GREEN}Docker Compose V2 found.${NC}" |
|
||||||
COMPOSE_CMD="docker compose" |
|
||||||
fi |
|
||||||
else |
|
||||||
COMPOSE_CMD="docker-compose" |
|
||||||
fi |
|
||||||
|
|
||||||
echo -e "${GREEN}Prerequisites satisfied.${NC}" |
|
||||||
} |
|
||||||
|
|
||||||
# Check for environment variables |
|
||||||
check_env_file() { |
|
||||||
# Check if the specified .env file exists |
|
||||||
if [ ! -f "$ENV_FILE" ]; then |
|
||||||
echo -e "${YELLOW}Warning: $ENV_FILE file not found.${NC}" |
|
||||||
|
|
||||||
# If it's the default .env and .env.example exists, offer to copy it |
|
||||||
if [ "$ENV_FILE" = ".env" ] && [ -f ".env.example" ]; then |
|
||||||
echo -e "Would you like to create a .env file from .env.example? (y/n)" |
|
||||||
read -r response |
|
||||||
if [[ "$response" =~ ^([yY][eE][sS]|[yY])$ ]]; then |
|
||||||
cp .env.example .env |
|
||||||
echo -e "${GREEN}.env file created from .env.example. Please edit it to add your API keys.${NC}" |
|
||||||
API_KEY_REMIND=true |
|
||||||
fi |
|
||||||
else |
|
||||||
echo -e "${YELLOW}Please create an environment file with your API keys.${NC}" |
|
||||||
API_KEY_REMIND=true |
|
||||||
fi |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
# Check for required API keys |
|
||||||
check_api_keys() { |
|
||||||
if [ "$API_KEY_REMIND" = true ] || [ "$1" = true ]; then |
|
||||||
echo -e "${YELLOW}API Key Requirements:${NC}" |
|
||||||
echo "The CodeXchange AI requires API keys for the following services:" |
|
||||||
echo " - OPENAI_API_KEY (Required for OpenAI GPT models)" |
|
||||||
echo " - ANTHROPIC_API_KEY (Required for Claude models)" |
|
||||||
echo " - GOOGLE_API_KEY (Required for Google Gemini models)" |
|
||||||
echo " - DEEPSEEK_API_KEY (Required for DeepSeek models)" |
|
||||||
echo " - GROQ_API_KEY (Required for GROQ models)" |
|
||||||
echo |
|
||||||
echo -e "Please ensure these keys are set in your ${BLUE}$ENV_FILE${NC} file." |
|
||||||
echo "You only need keys for the models you plan to use." |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
# Parse command line arguments |
|
||||||
parse_arguments() { |
|
||||||
while [[ $# -gt 0 ]]; do |
|
||||||
case $1 in |
|
||||||
-b|--build) |
|
||||||
BUILD_ONLY=true |
|
||||||
shift |
|
||||||
;; |
|
||||||
-d|--detach) |
|
||||||
DETACHED=true |
|
||||||
shift |
|
||||||
;; |
|
||||||
-e|--env) |
|
||||||
ENV_FILE="$2" |
|
||||||
shift 2 |
|
||||||
;; |
|
||||||
-p|--port) |
|
||||||
PORT="$2" |
|
||||||
shift 2 |
|
||||||
;; |
|
||||||
-l|--logs) |
|
||||||
FOLLOW_LOGS=true |
|
||||||
shift |
|
||||||
;; |
|
||||||
-s|--stop) |
|
||||||
STOP=true |
|
||||||
shift |
|
||||||
;; |
|
||||||
-r|--restart) |
|
||||||
RESTART=true |
|
||||||
shift |
|
||||||
;; |
|
||||||
-D|--down) |
|
||||||
DOWN=true |
|
||||||
shift |
|
||||||
;; |
|
||||||
-k|--keys) |
|
||||||
check_api_keys true |
|
||||||
exit 0 |
|
||||||
;; |
|
||||||
-h|--help) |
|
||||||
display_banner |
|
||||||
display_help |
|
||||||
exit 0 |
|
||||||
;; |
|
||||||
-v|--version) |
|
||||||
echo "CodeXchange AI Docker Wrapper v$VERSION" |
|
||||||
exit 0 |
|
||||||
;; |
|
||||||
*) |
|
||||||
echo -e "${RED}Error: Unknown option $1${NC}" |
|
||||||
display_help |
|
||||||
exit 1 |
|
||||||
;; |
|
||||||
esac |
|
||||||
done |
|
||||||
} |
|
||||||
|
|
||||||
# Build the Docker image |
|
||||||
build_image() { |
|
||||||
echo -e "${BLUE}Building the Docker image...${NC}" |
|
||||||
|
|
||||||
# Export PORT from the environment for docker-compose |
|
||||||
export PORT=$PORT |
|
||||||
|
|
||||||
if [ -f "$ENV_FILE" ]; then |
|
||||||
echo -e "${GREEN}Using environment file: $ENV_FILE${NC}" |
|
||||||
OPTS="--env-file $ENV_FILE" |
|
||||||
else |
|
||||||
OPTS="" |
|
||||||
fi |
|
||||||
|
|
||||||
# Build the image |
|
||||||
$COMPOSE_CMD $OPTS build |
|
||||||
|
|
||||||
echo -e "${GREEN}Docker image built successfully.${NC}" |
|
||||||
} |
|
||||||
|
|
||||||
# Run the container |
|
||||||
run_container() { |
|
||||||
echo -e "${BLUE}Starting the CodeXchange AI...${NC}" |
|
||||||
|
|
||||||
# Export PORT from the environment for docker-compose |
|
||||||
export PORT=$PORT |
|
||||||
|
|
||||||
if [ -f "$ENV_FILE" ]; then |
|
||||||
OPTS="--env-file $ENV_FILE" |
|
||||||
else |
|
||||||
OPTS="" |
|
||||||
fi |
|
||||||
|
|
||||||
# Add detach flag if specified |
|
||||||
if [ "$DETACHED" = true ]; then |
|
||||||
OPTS="$OPTS -d" |
|
||||||
fi |
|
||||||
|
|
||||||
# Run the container |
|
||||||
$COMPOSE_CMD $OPTS up |
|
||||||
|
|
||||||
# Follow logs if detached and requested |
|
||||||
if [ "$DETACHED" = true ] && [ "$FOLLOW_LOGS" = true ]; then |
|
||||||
$COMPOSE_CMD logs -f |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
# Stop the container |
|
||||||
stop_container() { |
|
||||||
echo -e "${BLUE}Stopping the CodeXchange AI...${NC}" |
|
||||||
$COMPOSE_CMD stop |
|
||||||
echo -e "${GREEN}Container stopped.${NC}" |
|
||||||
} |
|
||||||
|
|
||||||
# Restart the container |
|
||||||
restart_container() { |
|
||||||
echo -e "${BLUE}Restarting the CodeXchange AI...${NC}" |
|
||||||
$COMPOSE_CMD restart |
|
||||||
echo -e "${GREEN}Container restarted.${NC}" |
|
||||||
|
|
||||||
if [ "$FOLLOW_LOGS" = true ]; then |
|
||||||
$COMPOSE_CMD logs -f |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
# Bring down the container |
|
||||||
down_container() { |
|
||||||
echo -e "${BLUE}Stopping and removing the CodeXchange AI container...${NC}" |
|
||||||
$COMPOSE_CMD down |
|
||||||
echo -e "${GREEN}Container stopped and removed.${NC}" |
|
||||||
} |
|
||||||
|
|
||||||
# Display access information |
|
||||||
display_access_info() { |
|
||||||
echo -e "${GREEN}The CodeXchange AI is running!${NC}" |
|
||||||
echo -e "Access the application at: ${BLUE}http://localhost:$PORT${NC}" |
|
||||||
|
|
||||||
# Check if port is custom and update info |
|
||||||
if [ "$PORT" != "7860" ]; then |
|
||||||
echo -e "Running on custom port: ${BLUE}$PORT${NC}" |
|
||||||
fi |
|
||||||
|
|
||||||
# If running detached, provide instructions for logs |
|
||||||
if [ "$DETACHED" = true ]; then |
|
||||||
echo -e "Running in detached mode. Use ${YELLOW}$0 --logs${NC} to follow logs." |
|
||||||
fi |
|
||||||
|
|
||||||
echo -e "To stop the application, press ${YELLOW}Ctrl+C${NC} or run ${YELLOW}$0 --stop${NC}" |
|
||||||
} |
|
||||||
|
|
||||||
# Main function |
|
||||||
main() { |
|
||||||
display_banner |
|
||||||
check_prerequisites |
|
||||||
parse_arguments "$@" |
|
||||||
|
|
||||||
if [ "$DOWN" = true ]; then |
|
||||||
down_container |
|
||||||
exit 0 |
|
||||||
fi |
|
||||||
|
|
||||||
if [ "$STOP" = true ]; then |
|
||||||
stop_container |
|
||||||
exit 0 |
|
||||||
fi |
|
||||||
|
|
||||||
if [ "$RESTART" = true ]; then |
|
||||||
restart_container |
|
||||||
exit 0 |
|
||||||
fi |
|
||||||
|
|
||||||
check_env_file |
|
||||||
check_api_keys |
|
||||||
|
|
||||||
build_image |
|
||||||
|
|
||||||
if [ "$BUILD_ONLY" = false ]; then |
|
||||||
run_container |
|
||||||
|
|
||||||
# Only display access info if not in detached mode or if following logs |
|
||||||
if [ "$DETACHED" = false ] || [ "$FOLLOW_LOGS" = true ]; then |
|
||||||
display_access_info |
|
||||||
fi |
|
||||||
else |
|
||||||
echo -e "${GREEN}Build completed successfully. Use $0 to run the application.${NC}" |
|
||||||
fi |
|
||||||
} |
|
||||||
|
|
||||||
# Run main function with all arguments |
|
||||||
main "$@" |
|
@ -1,44 +0,0 @@ |
|||||||
"""Runner script for the CodeXchange AI.""" |
|
||||||
import sys |
|
||||||
from pathlib import Path |
|
||||||
from setuptools import setup, find_packages |
|
||||||
|
|
||||||
# Add src to Python path |
|
||||||
src_path = Path(__file__).parent |
|
||||||
sys.path.append(str(src_path)) |
|
||||||
|
|
||||||
from src.ai_code_converter.main import main |
|
||||||
from src.ai_code_converter.models.ai_streaming import AIModelStreamer |
|
||||||
from src.ai_code_converter.core.code_execution import CodeExecutor |
|
||||||
from src.ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
from src.ai_code_converter.core.file_utils import FileHandler |
|
||||||
from src.ai_code_converter.config import ( |
|
||||||
CUSTOM_CSS, |
|
||||||
LANGUAGE_MAPPING, |
|
||||||
MODELS, |
|
||||||
SUPPORTED_LANGUAGES, |
|
||||||
OPENAI_MODEL, |
|
||||||
CLAUDE_MODEL, |
|
||||||
DEEPSEEK_MODEL, |
|
||||||
GEMINI_MODEL, |
|
||||||
GROQ_MODEL |
|
||||||
) |
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
main() |
|
||||||
|
|
||||||
setup( |
|
||||||
name="ai_code_converter", |
|
||||||
version="0.1.0", |
|
||||||
packages=find_packages(where="src"), |
|
||||||
package_dir={"": "src"}, |
|
||||||
install_requires=[ |
|
||||||
"gradio>=4.0.0", |
|
||||||
"openai>=1.0.0", |
|
||||||
"anthropic>=0.3.0", |
|
||||||
"google-generativeai>=0.1.0", |
|
||||||
"python-dotenv>=1.0.0", |
|
||||||
"jinja2>=3.0.0" |
|
||||||
], |
|
||||||
python_requires=">=3.8", |
|
||||||
) |
|
After Width: | Height: | Size: 65 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 182 KiB |
After Width: | Height: | Size: 20 KiB |
After Width: | Height: | Size: 42 KiB |
@ -1,19 +0,0 @@ |
|||||||
from setuptools import setup, find_packages |
|
||||||
|
|
||||||
setup( |
|
||||||
name="ai_code_converter", |
|
||||||
version="1.0.0", |
|
||||||
packages=find_packages(), |
|
||||||
package_data={ |
|
||||||
'src.ai_code_converter': ['template.j2'], |
|
||||||
}, |
|
||||||
install_requires=[ |
|
||||||
'gradio', |
|
||||||
'openai', |
|
||||||
'anthropic', |
|
||||||
'google-generativeai', |
|
||||||
'python-dotenv', |
|
||||||
'jinja2', |
|
||||||
], |
|
||||||
python_requires='>=3.10', |
|
||||||
) |
|
@ -1 +0,0 @@ |
|||||||
"""CodeXchange AI - Application""" |
|
@ -1,3 +0,0 @@ |
|||||||
"""CodeXchange AI - package.""" |
|
||||||
|
|
||||||
__version__ = "1.0.0" |
|
File diff suppressed because it is too large
Load Diff
@ -1,443 +0,0 @@ |
|||||||
"""Configuration settings for the CodeXchange AI application.""" |
|
||||||
|
|
||||||
# Model configurations |
|
||||||
OPENAI_MODEL = "gpt-4o-mini" |
|
||||||
CLAUDE_MODEL = "claude-3-5-sonnet-20241022" |
|
||||||
DEEPSEEK_MODEL = "deepseek-chat" |
|
||||||
GEMINI_MODEL = "gemini-1.5-flash" |
|
||||||
GROQ_MODEL = "llama3-70b-8192" |
|
||||||
|
|
||||||
# Supported languages and models |
|
||||||
SUPPORTED_LANGUAGES = ["Python", "Julia", "JavaScript", "Go", "Java", "C++", "Ruby", "Swift", "Rust", "C#", "TypeScript", "R", "Perl", "Lua", "PHP", "Kotlin", "SQL"] |
|
||||||
MODELS = ["GPT", "Claude", "Gemini", "DeepSeek", "GROQ"] |
|
||||||
|
|
||||||
# Language mapping for syntax highlighting |
|
||||||
LANGUAGE_MAPPING = { |
|
||||||
"Python": "python", |
|
||||||
"JavaScript": "javascript", |
|
||||||
"Java": "python", |
|
||||||
"C++": "cpp", |
|
||||||
"Julia": "python", |
|
||||||
"Go": "c", |
|
||||||
"Ruby": "python", |
|
||||||
"Swift": "python", |
|
||||||
"Rust": "python", |
|
||||||
"C#": "python", |
|
||||||
"TypeScript": "typescript", |
|
||||||
"R": "r", |
|
||||||
"Perl": "python", |
|
||||||
"Lua": "python", |
|
||||||
"PHP": "python", |
|
||||||
"Kotlin": "python", |
|
||||||
"SQL": "sql" |
|
||||||
} |
|
||||||
|
|
||||||
# File extensions for each language |
|
||||||
LANGUAGE_FILE_EXTENSIONS = { |
|
||||||
"Python": ".py", |
|
||||||
"JavaScript": ".js", |
|
||||||
"Java": ".java", |
|
||||||
"C++": ".cpp", |
|
||||||
"Julia": ".jl", |
|
||||||
"Go": ".go", |
|
||||||
"Ruby": ".rb", |
|
||||||
"Swift": ".swift", |
|
||||||
"Rust": ".rs", |
|
||||||
"C#": ".cs", |
|
||||||
"TypeScript": ".ts", |
|
||||||
"R": ".r", |
|
||||||
"Perl": ".pl", |
|
||||||
"Lua": ".lua", |
|
||||||
"PHP": ".php", |
|
||||||
"Kotlin": ".kt", |
|
||||||
"SQL": ".sql" |
|
||||||
} |
|
||||||
|
|
||||||
# Documentation styles available for each language |
|
||||||
DOCUMENT_STYLES = { |
|
||||||
"Python": [ |
|
||||||
{"value": "standard", "label": "Standard (PEP 257)"}, |
|
||||||
{"value": "google", "label": "Google Style"}, |
|
||||||
{"value": "numpy", "label": "NumPy Style"} |
|
||||||
], |
|
||||||
"Julia": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "docsystem", "label": "Documenter.jl Style"} |
|
||||||
], |
|
||||||
"JavaScript": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "jsdoc", "label": "JSDoc Style"}, |
|
||||||
{"value": "tsdoc", "label": "TSDoc Style"} |
|
||||||
], |
|
||||||
"Go": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "godoc", "label": "GoDoc Style"} |
|
||||||
], |
|
||||||
"Java": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "javadoc", "label": "JavaDoc Style"} |
|
||||||
], |
|
||||||
"C++": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "doxygen", "label": "Doxygen Style"} |
|
||||||
], |
|
||||||
"Ruby": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "yard", "label": "YARD Style"}, |
|
||||||
{"value": "rdoc", "label": "RDoc Style"} |
|
||||||
], |
|
||||||
"Swift": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "markup", "label": "Swift Markup"} |
|
||||||
], |
|
||||||
"Rust": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "rustdoc", "label": "Rustdoc Style"} |
|
||||||
], |
|
||||||
"C#": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "xmldoc", "label": "XML Documentation"} |
|
||||||
], |
|
||||||
"TypeScript": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "tsdoc", "label": "TSDoc Style"} |
|
||||||
], |
|
||||||
"R": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "roxygen2", "label": "Roxygen2 Style"} |
|
||||||
], |
|
||||||
"Perl": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "pod", "label": "POD Style"} |
|
||||||
], |
|
||||||
"Lua": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "ldoc", "label": "LDoc Style"} |
|
||||||
], |
|
||||||
"PHP": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "phpdoc", "label": "PHPDoc Style"} |
|
||||||
], |
|
||||||
"Kotlin": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "kdoc", "label": "KDoc Style"} |
|
||||||
], |
|
||||||
"SQL": [ |
|
||||||
{"value": "standard", "label": "Standard"}, |
|
||||||
{"value": "block", "label": "Block Comment Style"} |
|
||||||
] |
|
||||||
} |
|
||||||
|
|
||||||
# Predefined code snippets for the UI |
|
||||||
PREDEFINED_SNIPPETS = { |
|
||||||
"Python Code Simple" : """ |
|
||||||
import time |
|
||||||
|
|
||||||
def calculate(iterations, param1, param2): |
|
||||||
result = 1.0 |
|
||||||
for i in range(1, iterations+1): |
|
||||||
j = i * param1 - param2 |
|
||||||
result -= (1/j) |
|
||||||
j = i * param1 + param2 |
|
||||||
result += (1/j) |
|
||||||
return result |
|
||||||
|
|
||||||
start_time = time.time() |
|
||||||
result = calculate(100_000_000, 4, 1) * 4 |
|
||||||
end_time = time.time() |
|
||||||
|
|
||||||
print(f"Result: {result:.12f}") |
|
||||||
print(f"Execution Time: {(end_time - start_time):.6f} seconds") |
|
||||||
""", |
|
||||||
"Python Code": """import time |
|
||||||
import random |
|
||||||
from typing import List, Tuple |
|
||||||
|
|
||||||
class LCG: |
|
||||||
#Linear Congruential Generator |
|
||||||
def __init__(self, seed: int): |
|
||||||
self.value = seed |
|
||||||
self.a = 1664525 |
|
||||||
self.c = 1013904223 |
|
||||||
self.m = 2**32 |
|
||||||
|
|
||||||
def next(self) -> int: |
|
||||||
# Generate next random number |
|
||||||
self.value = (self.a * self.value + self.c) % self.m |
|
||||||
return self.value |
|
||||||
|
|
||||||
def max_subarray_sum(n: int, seed: int, min_val: int, max_val: int) -> int: |
|
||||||
# Calculate maximum subarray sum for array of random numbers |
|
||||||
lcg = LCG(seed) |
|
||||||
random_numbers = [] |
|
||||||
|
|
||||||
# Generate random numbers |
|
||||||
for _ in range(n): |
|
||||||
random_numbers.append((lcg.next() % (max_val - min_val + 1)) + min_val) |
|
||||||
|
|
||||||
max_sum = float('-inf') |
|
||||||
|
|
||||||
# Calculate max subarray sum |
|
||||||
for i in range(n): |
|
||||||
current_sum = 0 |
|
||||||
for j in range(i, n): |
|
||||||
current_sum += random_numbers[j] |
|
||||||
if current_sum > max_sum: |
|
||||||
max_sum = current_sum |
|
||||||
|
|
||||||
return max_sum |
|
||||||
|
|
||||||
def total_max_subarray_sum(n: int, initial_seed: int, min_val: int, max_val: int) -> int: |
|
||||||
# Calculate total of maximum subarray sums over 20 iterations |
|
||||||
total_sum = 0 |
|
||||||
lcg = LCG(initial_seed) |
|
||||||
|
|
||||||
for _ in range(20): |
|
||||||
seed = lcg.next() |
|
||||||
total_sum += max_subarray_sum(n, seed, min_val, max_val) |
|
||||||
|
|
||||||
return total_sum |
|
||||||
|
|
||||||
# Main program |
|
||||||
def main(): |
|
||||||
n = 10000 |
|
||||||
initial_seed = 42 |
|
||||||
min_val = -10 |
|
||||||
max_val = 10 |
|
||||||
|
|
||||||
start_time = time.time() |
|
||||||
|
|
||||||
result = total_max_subarray_sum(n, initial_seed, min_val, max_val) |
|
||||||
|
|
||||||
end_time = time.time() |
|
||||||
duration = end_time - start_time |
|
||||||
|
|
||||||
print(f"Total Maximum Subarray Sum (20 runs): {result}") |
|
||||||
print(f"Execution Time: {duration:.6f} seconds") |
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
main()""", |
|
||||||
|
|
||||||
"C++ Code": """#include <iostream> |
|
||||||
#include <vector> |
|
||||||
#include <limits> |
|
||||||
#include <chrono> |
|
||||||
|
|
||||||
class LCG { |
|
||||||
private: |
|
||||||
uint32_t value; |
|
||||||
const uint32_t a = 1664525; |
|
||||||
const uint32_t c = 1013904223; |
|
||||||
const uint32_t m = 1 << 32; |
|
||||||
|
|
||||||
public: |
|
||||||
LCG(uint32_t seed) : value(seed) {} |
|
||||||
|
|
||||||
uint32_t next() { |
|
||||||
value = (a * value + c) % m; |
|
||||||
return value; |
|
||||||
} |
|
||||||
}; |
|
||||||
|
|
||||||
/* |
|
||||||
* Calculates maximum subarray sum for array of random numbers |
|
||||||
*/ |
|
||||||
int64_t max_subarray_sum(int n, uint32_t seed, int min_val, int max_val) { |
|
||||||
LCG lcg(seed); |
|
||||||
std::vector<int> random_numbers(n); |
|
||||||
|
|
||||||
// Generate random numbers |
|
||||||
for(int i = 0; i < n; i++) { |
|
||||||
random_numbers[i] = (lcg.next() % (max_val - min_val + 1)) + min_val; |
|
||||||
} |
|
||||||
|
|
||||||
int64_t max_sum = std::numeric_limits<int64_t>::min(); |
|
||||||
|
|
||||||
// Calculate max subarray sum |
|
||||||
for(int i = 0; i < n; i++) { |
|
||||||
int64_t current_sum = 0; |
|
||||||
for(int j = i; j < n; j++) { |
|
||||||
current_sum += random_numbers[j]; |
|
||||||
if(current_sum > max_sum) { |
|
||||||
max_sum = current_sum; |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
return max_sum; |
|
||||||
} |
|
||||||
|
|
||||||
/* |
|
||||||
* Calculates total of maximum subarray sums over 20 iterations |
|
||||||
*/ |
|
||||||
int64_t total_max_subarray_sum(int n, uint32_t initial_seed, int min_val, int max_val) { |
|
||||||
int64_t total_sum = 0; |
|
||||||
LCG lcg(initial_seed); |
|
||||||
|
|
||||||
for(int i = 0; i < 20; i++) { |
|
||||||
uint32_t seed = lcg.next(); |
|
||||||
total_sum += max_subarray_sum(n, seed, min_val, max_val); |
|
||||||
} |
|
||||||
return total_sum; |
|
||||||
} |
|
||||||
|
|
||||||
int main() { |
|
||||||
const int n = 10000; |
|
||||||
const uint32_t initial_seed = 42; |
|
||||||
const int min_val = -10; |
|
||||||
const int max_val = 10; |
|
||||||
|
|
||||||
auto start_time = std::chrono::high_resolution_clock::now(); |
|
||||||
|
|
||||||
int64_t result = total_max_subarray_sum(n, initial_seed, min_val, max_val); |
|
||||||
|
|
||||||
auto end_time = std::chrono::high_resolution_clock::now(); |
|
||||||
auto duration = std::chrono::duration_cast<std::chrono::microseconds>(end_time - start_time); |
|
||||||
|
|
||||||
std::cout << "Total Maximum Subarray Sum (20 runs): " << result << std::endl; |
|
||||||
std::cout << "Execution Time: " << duration.count() / 1000000.0 << " seconds" << std::endl; |
|
||||||
|
|
||||||
return 0; |
|
||||||
}""", |
|
||||||
"Java Code": """import java.util.ArrayList; |
|
||||||
|
|
||||||
public class MaxSubarraySum { |
|
||||||
/* Linear Congruential Generator implementation */ |
|
||||||
static class LCG { |
|
||||||
private long value; |
|
||||||
private final long a = 1664525; |
|
||||||
private final long c = 1013904223; |
|
||||||
private final long m = 1L << 32; |
|
||||||
|
|
||||||
public LCG(long seed) { |
|
||||||
this.value = seed; |
|
||||||
} |
|
||||||
|
|
||||||
public long next() { |
|
||||||
value = (a * value + c) % m; |
|
||||||
return value; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/* Calculates maximum subarray sum for given array of random numbers */ |
|
||||||
private static long maxSubarraySum(int n, long seed, int minVal, int maxVal) { |
|
||||||
LCG lcg = new LCG(seed); |
|
||||||
ArrayList<Long> randomNumbers = new ArrayList<>(); |
|
||||||
|
|
||||||
// Generate random numbers |
|
||||||
for (int i = 0; i < n; i++) { |
|
||||||
long num = lcg.next() % (maxVal - minVal + 1) + minVal; |
|
||||||
randomNumbers.add(num); |
|
||||||
} |
|
||||||
|
|
||||||
long maxSum = Long.MIN_VALUE; |
|
||||||
for (int i = 0; i < n; i++) { |
|
||||||
long currentSum = 0; |
|
||||||
for (int j = i; j < n; j++) { |
|
||||||
currentSum += randomNumbers.get(j); |
|
||||||
maxSum = Math.max(maxSum, currentSum); |
|
||||||
} |
|
||||||
} |
|
||||||
return maxSum; |
|
||||||
} |
|
||||||
|
|
||||||
/* Calculates total of maximum subarray sums for 20 different seeds */ |
|
||||||
private static long totalMaxSubarraySum(int n, long initialSeed, int minVal, int maxVal) { |
|
||||||
long totalSum = 0; |
|
||||||
LCG lcg = new LCG(initialSeed); |
|
||||||
|
|
||||||
for (int i = 0; i < 20; i++) { |
|
||||||
long seed = lcg.next(); |
|
||||||
totalSum += maxSubarraySum(n, seed, minVal, maxVal); |
|
||||||
} |
|
||||||
return totalSum; |
|
||||||
} |
|
||||||
|
|
||||||
public static void main(String[] args) { |
|
||||||
// Parameters |
|
||||||
int n = 10000; // Number of random numbers |
|
||||||
long initialSeed = 42; // Initial seed for the LCG |
|
||||||
int minVal = -10; // Minimum value of random numbers |
|
||||||
int maxVal = 10; // Maximum value of random numbers |
|
||||||
|
|
||||||
// Timing the function |
|
||||||
long startTime = System.nanoTime(); |
|
||||||
long result = totalMaxSubarraySum(n, initialSeed, minVal, maxVal); |
|
||||||
long endTime = System.nanoTime(); |
|
||||||
|
|
||||||
System.out.println("Total Maximum Subarray Sum (20 runs): " + result); |
|
||||||
System.out.printf("Execution Time: %.6f seconds%n", (endTime - startTime) / 1e9); |
|
||||||
} |
|
||||||
}""" |
|
||||||
} |
|
||||||
|
|
||||||
# Map snippets to their corresponding languages |
|
||||||
SNIPPET_LANGUAGE_MAP = { |
|
||||||
"Python Code": "Python", |
|
||||||
"Python Code Simple": "Python", |
|
||||||
"C++ Code": "C++", |
|
||||||
"Java Code": "Java" |
|
||||||
} |
|
||||||
|
|
||||||
# CSS styling |
|
||||||
CUSTOM_CSS = """ |
|
||||||
.code-container { |
|
||||||
height: 30vh; |
|
||||||
overflow: auto; |
|
||||||
border-radius: 4px; |
|
||||||
scrollbar-width: none; |
|
||||||
-ms-overflow-style: none; |
|
||||||
} |
|
||||||
|
|
||||||
.code-container::-webkit-scrollbar { |
|
||||||
display: none !important; |
|
||||||
width: 0 !important; |
|
||||||
height: 0 !important; |
|
||||||
background: transparent !important; |
|
||||||
} |
|
||||||
|
|
||||||
.code-container .scroll-hide::-webkit-scrollbar, |
|
||||||
.code-container > div::-webkit-scrollbar, |
|
||||||
.code-container textarea::-webkit-scrollbar, |
|
||||||
.code-container pre::-webkit-scrollbar, |
|
||||||
.code-container code::-webkit-scrollbar { |
|
||||||
display: none !important; |
|
||||||
width: 0 !important; |
|
||||||
height: 0 !important; |
|
||||||
background: transparent !important; |
|
||||||
} |
|
||||||
|
|
||||||
.code-container .language-select { |
|
||||||
overflow: auto !important; |
|
||||||
max-height: 100% !important; |
|
||||||
} |
|
||||||
|
|
||||||
.accordion { |
|
||||||
margin-top: 1rem !important; |
|
||||||
} |
|
||||||
|
|
||||||
.error-accordion { |
|
||||||
margin: 10px 0; |
|
||||||
border: 2px solid #ff4444 !important; |
|
||||||
border-radius: 4px !important; |
|
||||||
background-color: #ffffff !important; |
|
||||||
} |
|
||||||
|
|
||||||
.error-message { |
|
||||||
color: #ff4444; |
|
||||||
font-weight: bold; |
|
||||||
font-size: 16px; |
|
||||||
padding: 10px; |
|
||||||
} |
|
||||||
|
|
||||||
.gradio-container { |
|
||||||
padding-top: 1rem; |
|
||||||
} |
|
||||||
|
|
||||||
.header-text { |
|
||||||
text-align: center; |
|
||||||
font-size: 2rem; |
|
||||||
font-color: #283042; |
|
||||||
font-weight: bold; |
|
||||||
margin-bottom: 1rem; |
|
||||||
} |
|
||||||
""" |
|
@ -1 +0,0 @@ |
|||||||
"""Core functionality modules.""" |
|
@ -1,631 +0,0 @@ |
|||||||
"""Module for executing code in different programming languages.""" |
|
||||||
|
|
||||||
import contextlib |
|
||||||
import io |
|
||||||
import logging |
|
||||||
import os |
|
||||||
import re |
|
||||||
import subprocess |
|
||||||
import tempfile |
|
||||||
from typing import Optional |
|
||||||
from datetime import datetime |
|
||||||
from src.ai_code_converter.utils.logger import setup_logger |
|
||||||
from pathlib import Path |
|
||||||
|
|
||||||
# Initialize logger for this module |
|
||||||
logger = setup_logger(__name__) |
|
||||||
|
|
||||||
class CodeExecutor: |
|
||||||
"""Class for executing code in various programming languages.""" |
|
||||||
|
|
||||||
def __init__(self): |
|
||||||
"""Initialize the code executor.""" |
|
||||||
logger.info("Initializing CodeExecutor") |
|
||||||
self.executors = { |
|
||||||
"Python": self.execute_python, |
|
||||||
"JavaScript": self.execute_javascript, |
|
||||||
"Java": self.execute_java, |
|
||||||
"C++": self.execute_cpp, |
|
||||||
"Julia": self.execute_julia, |
|
||||||
"Go": self.execute_go, |
|
||||||
"Perl": self.execute_perl, |
|
||||||
"Lua": self.execute_lua, |
|
||||||
"PHP": self.execute_php, |
|
||||||
"Kotlin": self.execute_kotlin, |
|
||||||
"SQL": self.execute_sql, |
|
||||||
"R": self.execute_r, |
|
||||||
"Ruby": self.execute_ruby, |
|
||||||
"Swift": self.execute_swift, |
|
||||||
"Rust": self.execute_rust, |
|
||||||
"C#": self.execute_csharp, |
|
||||||
"TypeScript": self.execute_typescript |
|
||||||
} |
|
||||||
|
|
||||||
def execute(self, code: str, language: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute code with detailed logging.""" |
|
||||||
logger.info("="*50) |
|
||||||
logger.info(f"STARTING CODE EXECUTION: {language}") |
|
||||||
logger.info("="*50) |
|
||||||
logger.info(f"Code length: {len(code)} characters") |
|
||||||
|
|
||||||
if not code: |
|
||||||
logger.warning("No code provided for execution") |
|
||||||
return "No code to execute", None |
|
||||||
|
|
||||||
executor = self.executors.get(language) |
|
||||||
if not executor: |
|
||||||
logger.error(f"No executor found for language: {language}") |
|
||||||
return f"Execution not implemented for {language}", None |
|
||||||
|
|
||||||
try: |
|
||||||
logger.info(f"Executing {language} code") |
|
||||||
start_time = datetime.now() |
|
||||||
|
|
||||||
output, binary = executor(code) |
|
||||||
|
|
||||||
execution_time = (datetime.now() - start_time).total_seconds() |
|
||||||
logger.info(f"Execution completed in {execution_time:.2f} seconds") |
|
||||||
logger.info(f"Output length: {len(output)} characters") |
|
||||||
if binary: |
|
||||||
logger.info(f"Binary size: {len(binary)} bytes") |
|
||||||
logger.info("="*50) |
|
||||||
|
|
||||||
return f"{output}\nExecution completed in {execution_time:.2f} seconds", binary |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Error executing {language} code", exc_info=True) |
|
||||||
logger.info("="*50) |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
|
|
||||||
def execute_python(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute Python code in a safe environment.""" |
|
||||||
output = io.StringIO() |
|
||||||
with contextlib.redirect_stdout(output): |
|
||||||
try: |
|
||||||
# Create a shared namespace for globals and locals |
|
||||||
namespace = {} |
|
||||||
|
|
||||||
# Execute the code with shared namespace |
|
||||||
exec(code, namespace, namespace) |
|
||||||
|
|
||||||
# Get any stored output |
|
||||||
execution_output = output.getvalue() |
|
||||||
|
|
||||||
# If there's a result variable, append it to output |
|
||||||
if '_result' in namespace: |
|
||||||
execution_output += str(namespace['_result']) |
|
||||||
|
|
||||||
return execution_output, None |
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Python execution error: {str(e)}", exc_info=True) |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
output.close() |
|
||||||
|
|
||||||
def execute_javascript(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute JavaScript code using Node.js.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.js', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
js_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
result = subprocess.run( |
|
||||||
["node", js_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
return result.stdout, None |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(js_file) |
|
||||||
|
|
||||||
def execute_julia(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute Julia code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.jl', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
jl_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
result = subprocess.run( |
|
||||||
["julia", jl_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
return result.stdout, None |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(jl_file) |
|
||||||
|
|
||||||
def execute_cpp(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Compile and execute C++ code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.cpp', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
cpp_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
# Compile |
|
||||||
exe_file = cpp_file[:-4] # Remove .cpp |
|
||||||
if os.name == 'nt': # Windows |
|
||||||
exe_file += '.exe' |
|
||||||
|
|
||||||
compile_result = subprocess.run( |
|
||||||
["g++", cpp_file, "-o", exe_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
# Execute |
|
||||||
run_result = subprocess.run( |
|
||||||
[exe_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
# Read the compiled binary |
|
||||||
with open(exe_file, 'rb') as f: |
|
||||||
compiled_binary = f.read() |
|
||||||
|
|
||||||
return run_result.stdout, compiled_binary |
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(cpp_file) |
|
||||||
if os.path.exists(exe_file): |
|
||||||
os.unlink(exe_file) |
|
||||||
|
|
||||||
def execute_java(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Compile and execute Java code.""" |
|
||||||
logger.info("Starting Java code execution") |
|
||||||
|
|
||||||
# Create a temporary directory with proper permissions |
|
||||||
with tempfile.TemporaryDirectory() as temp_dir: |
|
||||||
try: |
|
||||||
# Extract class name |
|
||||||
class_match = re.search(r'public\s+class\s+(\w+)', code) |
|
||||||
if not class_match: |
|
||||||
logger.error("Could not find public class name in Java code") |
|
||||||
return "Error: Could not find public class name", None |
|
||||||
|
|
||||||
class_name = class_match.group(1) |
|
||||||
temp_path = Path(temp_dir) |
|
||||||
java_file = temp_path / f"{class_name}.java" |
|
||||||
class_file = temp_path / f"{class_name}.class" |
|
||||||
|
|
||||||
# Write code to file |
|
||||||
java_file.write_text(code) |
|
||||||
logger.info(f"Wrote Java source to {java_file}") |
|
||||||
|
|
||||||
# Compile |
|
||||||
logger.info("Compiling Java code") |
|
||||||
compile_result = subprocess.run( |
|
||||||
["javac", str(java_file)], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True, |
|
||||||
cwd=temp_dir # Set working directory to temp_dir |
|
||||||
) |
|
||||||
logger.info("Java compilation successful") |
|
||||||
|
|
||||||
# Verify class file exists |
|
||||||
if not class_file.exists(): |
|
||||||
logger.error(f"Class file {class_file} not found after compilation") |
|
||||||
return "Error: Compilation failed to produce class file", None |
|
||||||
|
|
||||||
# Read compiled bytecode |
|
||||||
compiled_binary = class_file.read_bytes() |
|
||||||
logger.info(f"Read compiled binary, size: {len(compiled_binary)} bytes") |
|
||||||
|
|
||||||
# Execute |
|
||||||
logger.info("Executing Java code") |
|
||||||
run_result = subprocess.run( |
|
||||||
["java", class_name], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True, |
|
||||||
cwd=temp_dir # Set working directory to temp_dir |
|
||||||
) |
|
||||||
logger.info("Java execution successful") |
|
||||||
|
|
||||||
# Return both output and compiled binary |
|
||||||
return run_result.stdout, compiled_binary |
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
logger.error(f"Java compilation/execution error: {e.stderr}") |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Unexpected error in Java execution: {str(e)}", exc_info=True) |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
|
|
||||||
def execute_go(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute Go code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.go', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
go_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
# Compile first |
|
||||||
exe_file = go_file[:-3] # Remove .go |
|
||||||
if os.name == 'nt': |
|
||||||
exe_file += '.exe' |
|
||||||
|
|
||||||
compile_result = subprocess.run( |
|
||||||
["go", "build", "-o", exe_file, go_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
# Read compiled binary |
|
||||||
with open(exe_file, 'rb') as f: |
|
||||||
compiled_binary = f.read() |
|
||||||
|
|
||||||
# Execute |
|
||||||
run_result = subprocess.run( |
|
||||||
[exe_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
return run_result.stdout, compiled_binary |
|
||||||
|
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(go_file) |
|
||||||
if os.path.exists(exe_file): |
|
||||||
os.unlink(exe_file) |
|
||||||
|
|
||||||
def execute_perl(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute Perl code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.pl', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
pl_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
result = subprocess.run( |
|
||||||
["perl", pl_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
return result.stdout, None |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(pl_file) |
|
||||||
|
|
||||||
def execute_lua(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute Lua code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.lua', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
lua_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
result = subprocess.run( |
|
||||||
["lua", lua_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
return result.stdout, None |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(lua_file) |
|
||||||
|
|
||||||
def execute_php(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute PHP code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.php', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
php_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
result = subprocess.run( |
|
||||||
["php", php_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
return result.stdout, None |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(php_file) |
|
||||||
|
|
||||||
def execute_kotlin(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Compile and execute Kotlin code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.kt', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
kt_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
# Extract main class name (best effort) |
|
||||||
class_match = re.search(r'class\s+(\w+)', code) |
|
||||||
class_name = class_match.group(1) if class_match else "MainKt" |
|
||||||
|
|
||||||
# Compile |
|
||||||
jar_file = kt_file[:-3] + ".jar" |
|
||||||
compile_result = subprocess.run( |
|
||||||
["kotlinc", kt_file, "-include-runtime", "-d", jar_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
# Read compiled bytecode |
|
||||||
with open(jar_file, 'rb') as f: |
|
||||||
compiled_binary = f.read() |
|
||||||
|
|
||||||
# Execute |
|
||||||
run_result = subprocess.run( |
|
||||||
["java", "-jar", jar_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
return run_result.stdout, compiled_binary |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(kt_file) |
|
||||||
jar_file = kt_file[:-3] + ".jar" |
|
||||||
if os.path.exists(jar_file): |
|
||||||
os.unlink(jar_file) |
|
||||||
|
|
||||||
def execute_sql(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute SQL code using SQLite.""" |
|
||||||
# Create a temporary database file |
|
||||||
db_file = tempfile.NamedTemporaryFile(suffix='.db', delete=False).name |
|
||||||
|
|
||||||
try: |
|
||||||
# Write SQL directly to the sqlite3 process via stdin |
|
||||||
process = subprocess.Popen( |
|
||||||
["sqlite3", db_file], |
|
||||||
stdin=subprocess.PIPE, |
|
||||||
stdout=subprocess.PIPE, |
|
||||||
stderr=subprocess.PIPE, |
|
||||||
text=True |
|
||||||
) |
|
||||||
|
|
||||||
# Send the SQL code to sqlite3 |
|
||||||
stdout, stderr = process.communicate(input=code) |
|
||||||
|
|
||||||
if process.returncode != 0: |
|
||||||
return f"Error: {stderr}", None |
|
||||||
|
|
||||||
# For SQL, we'll also run a simple query to show tables |
|
||||||
tables_result = subprocess.run( |
|
||||||
["sqlite3", db_file, ".tables"], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=False |
|
||||||
) |
|
||||||
|
|
||||||
# Combine the results |
|
||||||
output = stdout |
|
||||||
if tables_result.returncode == 0 and tables_result.stdout.strip(): |
|
||||||
output += "\n\nTables in database:\n" + tables_result.stdout |
|
||||||
|
|
||||||
# For each table, show schema |
|
||||||
for table in tables_result.stdout.split(): |
|
||||||
schema_result = subprocess.run( |
|
||||||
["sqlite3", db_file, f".schema {table}"], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=False |
|
||||||
) |
|
||||||
if schema_result.returncode == 0: |
|
||||||
output += "\n" + schema_result.stdout |
|
||||||
|
|
||||||
return output, None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
if os.path.exists(db_file): |
|
||||||
os.unlink(db_file) |
|
||||||
|
|
||||||
def execute_r(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute R code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.R', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
r_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
result = subprocess.run( |
|
||||||
["Rscript", r_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
return result.stdout, None |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(r_file) |
|
||||||
|
|
||||||
def execute_ruby(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute Ruby code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.rb', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
rb_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
result = subprocess.run( |
|
||||||
["ruby", rb_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
return result.stdout, None |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(rb_file) |
|
||||||
|
|
||||||
def execute_swift(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Execute Swift code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.swift', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
swift_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
result = subprocess.run( |
|
||||||
["swift", swift_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
return result.stdout, None |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(swift_file) |
|
||||||
|
|
||||||
def execute_rust(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Compile and execute Rust code.""" |
|
||||||
# Create a temporary directory for Rust project |
|
||||||
with tempfile.TemporaryDirectory() as temp_dir: |
|
||||||
# Create main.rs file |
|
||||||
main_rs = os.path.join(temp_dir, "main.rs") |
|
||||||
with open(main_rs, 'w') as f: |
|
||||||
f.write(code) |
|
||||||
|
|
||||||
try: |
|
||||||
# Compile |
|
||||||
exe_file = os.path.join(temp_dir, "rustapp") |
|
||||||
compile_result = subprocess.run( |
|
||||||
["rustc", main_rs, "-o", exe_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
# Read compiled binary |
|
||||||
with open(exe_file, 'rb') as f: |
|
||||||
compiled_binary = f.read() |
|
||||||
|
|
||||||
# Execute |
|
||||||
run_result = subprocess.run( |
|
||||||
[exe_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
return run_result.stdout, compiled_binary |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
|
|
||||||
def execute_csharp(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Compile and execute C# code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.cs', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
cs_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
# Compile to executable |
|
||||||
exe_file = cs_file[:-3] + ".exe" |
|
||||||
compile_result = subprocess.run( |
|
||||||
["mono-csc", cs_file, "-out:" + exe_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
# Read compiled binary |
|
||||||
with open(exe_file, 'rb') as f: |
|
||||||
compiled_binary = f.read() |
|
||||||
|
|
||||||
# Execute |
|
||||||
if os.name == 'nt': # Windows |
|
||||||
run_result = subprocess.run( |
|
||||||
[exe_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
else: # Unix-like |
|
||||||
run_result = subprocess.run( |
|
||||||
["mono", exe_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
return run_result.stdout, compiled_binary |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(cs_file) |
|
||||||
exe_file = cs_file[:-3] + ".exe" |
|
||||||
if os.path.exists(exe_file): |
|
||||||
os.unlink(exe_file) |
|
||||||
|
|
||||||
def execute_typescript(self, code: str) -> tuple[str, Optional[bytes]]: |
|
||||||
"""Compile and execute TypeScript code.""" |
|
||||||
with tempfile.NamedTemporaryFile(suffix='.ts', mode='w', delete=False) as f: |
|
||||||
f.write(code) |
|
||||||
ts_file = f.name |
|
||||||
|
|
||||||
try: |
|
||||||
# Compile TypeScript to JavaScript |
|
||||||
js_file = ts_file[:-3] + ".js" |
|
||||||
compile_result = subprocess.run( |
|
||||||
["tsc", ts_file, "--outFile", js_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
# Execute the compiled JavaScript |
|
||||||
run_result = subprocess.run( |
|
||||||
["node", js_file], |
|
||||||
capture_output=True, |
|
||||||
text=True, |
|
||||||
check=True |
|
||||||
) |
|
||||||
|
|
||||||
return run_result.stdout, None |
|
||||||
except subprocess.CalledProcessError as e: |
|
||||||
return f"Error: {e.stderr}", None |
|
||||||
except Exception as e: |
|
||||||
return f"Error: {str(e)}", None |
|
||||||
finally: |
|
||||||
os.unlink(ts_file) |
|
||||||
js_file = ts_file[:-3] + ".js" |
|
||||||
if os.path.exists(js_file): |
|
||||||
os.unlink(js_file) |
|
@ -1,250 +0,0 @@ |
|||||||
"""Module for handling file operations.""" |
|
||||||
|
|
||||||
import logging |
|
||||||
import tempfile |
|
||||||
import zipfile |
|
||||||
import platform |
|
||||||
from pathlib import Path |
|
||||||
from typing import Optional, Tuple |
|
||||||
import os |
|
||||||
import shutil |
|
||||||
import gradio as gr |
|
||||||
from datetime import datetime |
|
||||||
|
|
||||||
from src.ai_code_converter.utils.logger import setup_logger |
|
||||||
|
|
||||||
logger = setup_logger(__name__) |
|
||||||
|
|
||||||
class FileHandler: |
|
||||||
"""Class for handling file operations.""" |
|
||||||
|
|
||||||
def create_readme(self, language: str, files: list[str]) -> str: |
|
||||||
"""Create a README file with compilation instructions.""" |
|
||||||
system_info = platform.uname() |
|
||||||
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S") |
|
||||||
|
|
||||||
readme = f"""# {language} Code Compilation Instructions |
|
||||||
|
|
||||||
Generated on: {timestamp} |
|
||||||
|
|
||||||
## Compilation Environment |
|
||||||
- OS: {system_info.system} |
|
||||||
- Architecture: {system_info.machine} |
|
||||||
- Platform: {system_info.version} |
|
||||||
|
|
||||||
## Files Included |
|
||||||
{chr(10).join(f"- {file}" for file in files)} |
|
||||||
|
|
||||||
## Compilation Instructions |
|
||||||
|
|
||||||
""" |
|
||||||
if language == "C++": |
|
||||||
readme += """### Windows |
|
||||||
1. Install MinGW or Visual Studio with C++ support |
|
||||||
2. Open command prompt in this directory |
|
||||||
3. Run: `g++ main.cpp -o program.exe` |
|
||||||
4. Execute: `program.exe` |
|
||||||
|
|
||||||
### Linux |
|
||||||
1. Install GCC: `sudo apt-get install build-essential` (Ubuntu/Debian) |
|
||||||
2. Open terminal in this directory |
|
||||||
3. Run: `g++ main.cpp -o program` |
|
||||||
4. Execute: `./program` |
|
||||||
|
|
||||||
### macOS |
|
||||||
1. Install Xcode Command Line Tools: `xcode-select --install` |
|
||||||
2. Open terminal in this directory |
|
||||||
3. Run: `g++ main.cpp -o program` |
|
||||||
4. Execute: `./program` |
|
||||||
""" |
|
||||||
elif language == "Java": |
|
||||||
readme += """### All Platforms (Windows/Linux/macOS) |
|
||||||
1. Install JDK 11 or later |
|
||||||
2. Open terminal/command prompt in this directory |
|
||||||
3. Compile: `javac Main.java` |
|
||||||
4. Run: `java Main` |
|
||||||
|
|
||||||
Note: The class name in the Java file must be 'Main' for these instructions. |
|
||||||
""" |
|
||||||
elif language == "Go": |
|
||||||
readme += """### Windows |
|
||||||
1. Install Go from https://golang.org/ |
|
||||||
2. Open command prompt in this directory |
|
||||||
3. Run: `go build main.go` |
|
||||||
4. Execute: `main.exe` |
|
||||||
|
|
||||||
### Linux/macOS |
|
||||||
1. Install Go: |
|
||||||
- Linux: `sudo apt-get install golang` (Ubuntu/Debian) |
|
||||||
- macOS: `brew install go` (using Homebrew) |
|
||||||
2. Open terminal in this directory |
|
||||||
3. Run: `go build main.go` |
|
||||||
4. Execute: `./main` |
|
||||||
""" |
|
||||||
return readme |
|
||||||
|
|
||||||
def create_compilation_zip(self, code: str, language: str, compiled_code: Optional[bytes] = None) -> Tuple[Optional[str], Optional[str]]: |
|
||||||
"""Create a zip file containing source, compiled files, and README.""" |
|
||||||
try: |
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
|
||||||
project_name = f"ai_code_converter_{language.lower()}_{timestamp}" |
|
||||||
|
|
||||||
# Create temporary directory |
|
||||||
with tempfile.TemporaryDirectory() as temp_dir: |
|
||||||
temp_dir_path = Path(temp_dir) |
|
||||||
files_included = [] |
|
||||||
|
|
||||||
# Write source code with standardized names |
|
||||||
if language == "C++": |
|
||||||
source_file = temp_dir_path / "main.cpp" |
|
||||||
compiled_file = temp_dir_path / ("main.exe" if os.name == 'nt' else "main") |
|
||||||
files_included.extend(["main.cpp", "main.exe" if os.name == 'nt' else "main"]) |
|
||||||
elif language == "Java": |
|
||||||
source_file = temp_dir_path / "Main.java" |
|
||||||
compiled_file = temp_dir_path / "Main.class" |
|
||||||
files_included.extend(["Main.java", "Main.class"]) |
|
||||||
elif language == "Go": |
|
||||||
source_file = temp_dir_path / "main.go" |
|
||||||
compiled_file = temp_dir_path / ("main.exe" if os.name == 'nt' else "main") |
|
||||||
files_included.extend(["main.go", "main.exe" if os.name == 'nt' else "main"]) |
|
||||||
else: |
|
||||||
return None, None |
|
||||||
|
|
||||||
# Write source code |
|
||||||
source_file.write_text(code) |
|
||||||
|
|
||||||
# Write compiled code if available |
|
||||||
if compiled_code: |
|
||||||
logger.info(f"Writing compiled binary: {compiled_file}") |
|
||||||
try: |
|
||||||
# Ensure the file is writable |
|
||||||
compiled_file.parent.mkdir(parents=True, exist_ok=True) |
|
||||||
compiled_file.write_bytes(compiled_code) |
|
||||||
logger.info(f"Successfully wrote compiled binary: {compiled_file}") |
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Error writing compiled binary: {e}", exc_info=True) |
|
||||||
else: |
|
||||||
logger.warning("No compiled code available") |
|
||||||
|
|
||||||
# Create README |
|
||||||
readme_path = temp_dir_path / "README.md" |
|
||||||
readme_content = self.create_readme(language, files_included) |
|
||||||
readme_path.write_text(readme_content) |
|
||||||
files_included.append("README.md") |
|
||||||
|
|
||||||
# Create zip file with descriptive name |
|
||||||
zip_filename = f"{project_name}.zip" |
|
||||||
zip_path = temp_dir_path / zip_filename |
|
||||||
|
|
||||||
# Create zip file |
|
||||||
with zipfile.ZipFile(zip_path, 'w') as zf: |
|
||||||
for file in files_included: |
|
||||||
file_path = temp_dir_path / file |
|
||||||
if file_path.exists(): |
|
||||||
logger.info(f"Adding to zip: {file}") |
|
||||||
zf.write(file_path, file_path.name) |
|
||||||
else: |
|
||||||
logger.warning(f"File not found for zip: {file}") |
|
||||||
|
|
||||||
# Create a permanent location for the zip file |
|
||||||
downloads_dir = Path("downloads") |
|
||||||
downloads_dir.mkdir(exist_ok=True) |
|
||||||
|
|
||||||
final_zip_path = downloads_dir / zip_filename |
|
||||||
shutil.copy2(zip_path, final_zip_path) |
|
||||||
|
|
||||||
# Verify zip contents |
|
||||||
with zipfile.ZipFile(final_zip_path, 'r') as zf: |
|
||||||
logger.info(f"Zip file contents: {zf.namelist()}") |
|
||||||
|
|
||||||
return str(final_zip_path), zip_filename |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Error creating compilation zip: {str(e)}", exc_info=True) |
|
||||||
return None, None |
|
||||||
|
|
||||||
def prepare_download(self, code: str, language: str, compiled_code: Optional[bytes] = None) -> Tuple[Optional[str], Optional[str]]: |
|
||||||
"""Prepare code for download with consistent naming.""" |
|
||||||
try: |
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
|
||||||
downloads_dir = Path("downloads") |
|
||||||
downloads_dir.mkdir(exist_ok=True) |
|
||||||
|
|
||||||
# For compiled languages, create a zip with source and instructions |
|
||||||
if language in ["C++", "Java", "Go"]: |
|
||||||
logger.info(f"Creating compilation zip for {language}") |
|
||||||
# Pass compiled_code directly as bytes |
|
||||||
return self.create_compilation_zip( |
|
||||||
code=code, |
|
||||||
language=language, |
|
||||||
compiled_code=compiled_code if isinstance(compiled_code, bytes) else None |
|
||||||
) |
|
||||||
|
|
||||||
# For interpreted languages, create a single file with timestamp |
|
||||||
extension = self._get_file_extension(language) |
|
||||||
filename = f"ai_code_converter_{language.lower()}_{timestamp}{extension}" |
|
||||||
file_path = downloads_dir / filename |
|
||||||
|
|
||||||
# Write the file |
|
||||||
file_path.write_text(code) |
|
||||||
return str(file_path), filename |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Error preparing download: {str(e)}", exc_info=True) |
|
||||||
return None, None |
|
||||||
|
|
||||||
def load_file(self, file_path: str) -> str: |
|
||||||
"""Load code from a file.""" |
|
||||||
try: |
|
||||||
with open(file_path, 'r') as f: |
|
||||||
return f.read() |
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Error loading file: {str(e)}", exc_info=True) |
|
||||||
raise |
|
||||||
|
|
||||||
def _get_file_extension(self, language: str) -> str: |
|
||||||
"""Get file extension for a language.""" |
|
||||||
extensions = { |
|
||||||
"Python": ".py", |
|
||||||
"JavaScript": ".js", |
|
||||||
"Java": ".java", |
|
||||||
"C++": ".cpp", |
|
||||||
"Julia": ".jl", |
|
||||||
"Go": ".go" |
|
||||||
} |
|
||||||
return extensions.get(language, ".txt") |
|
||||||
|
|
||||||
def handle_file_upload(self, file: gr.File) -> tuple[str, str]: |
|
||||||
"""Handle file upload with detailed logging.""" |
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
if not file: |
|
||||||
logger.warning("File upload attempted but no file was provided") |
|
||||||
return "", "No file uploaded" |
|
||||||
|
|
||||||
try: |
|
||||||
logger.info(f"Processing uploaded file: {file.name}") |
|
||||||
logger.info(f"File size: {os.path.getsize(file.name)} bytes") |
|
||||||
|
|
||||||
# Create downloads directory if it doesn't exist |
|
||||||
downloads_dir = Path("downloads") |
|
||||||
downloads_dir.mkdir(exist_ok=True) |
|
||||||
|
|
||||||
# Copy uploaded file to downloads with timestamp |
|
||||||
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S") |
|
||||||
_, ext = os.path.splitext(file.name) |
|
||||||
new_filename = f"ai_code_converter_upload_{timestamp}{ext}" |
|
||||||
new_path = downloads_dir / new_filename |
|
||||||
|
|
||||||
with open(file.name, 'r') as src, open(new_path, 'w') as dst: |
|
||||||
content = src.read() |
|
||||||
dst.write(content) |
|
||||||
|
|
||||||
logger.info(f"File saved as: {new_path}") |
|
||||||
logger.info(f"Content length: {len(content)} characters") |
|
||||||
return content, None |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
error_msg = f"Error loading file: {str(e)}" |
|
||||||
logger.error(error_msg, exc_info=True) |
|
||||||
return "", error_msg |
|
@ -1,793 +0,0 @@ |
|||||||
"""Module for detecting programming languages in code snippets.""" |
|
||||||
|
|
||||||
import re |
|
||||||
import logging |
|
||||||
from typing import Tuple |
|
||||||
|
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
class LanguageDetector: |
|
||||||
"""Class for detecting programming languages in code snippets.""" |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_python(code: str) -> bool: |
|
||||||
"""Detect if code is Python.""" |
|
||||||
patterns = [ |
|
||||||
r'def\s+\w+\s*\([^)]*\)\s*:', # Function definition |
|
||||||
r'import\s+[\w\s,]+', # Import statements |
|
||||||
r'from\s+[\w.]+\s+import', # From import statements |
|
||||||
r'print\s*\([^)]*\)', # Print statements |
|
||||||
r':\s*$' # Line ending with colon |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_javascript(code: str) -> bool: |
|
||||||
"""Detect if code is JavaScript.""" |
|
||||||
patterns = [ |
|
||||||
r'function\s+\w+\s*\([^)]*\)', # Function declaration |
|
||||||
r'const\s+\w+\s*=', # Const declaration |
|
||||||
r'let\s+\w+\s*=', # Let declaration |
|
||||||
r'var\s+\w+\s*=', # Var declaration |
|
||||||
r'console\.(log|error|warn)' # Console methods |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_java(code: str) -> bool: |
|
||||||
"""Detect if code is Java.""" |
|
||||||
patterns = [ |
|
||||||
r'public\s+class\s+\w+', # Class declaration |
|
||||||
r'public\s+static\s+void\s+main', # Main method |
|
||||||
r'System\.(out|err)\.', # System output |
|
||||||
r'private|protected|public', # Access modifiers |
|
||||||
r'import\s+java\.' # Java imports |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_cpp(code: str) -> bool: |
|
||||||
"""Detect if code is C++.""" |
|
||||||
patterns = [ |
|
||||||
r'#include\s*<[^>]+>', # Include statements |
|
||||||
r'std::\w+', # STD namespace usage |
|
||||||
r'cout\s*<<', # Console output |
|
||||||
r'cin\s*>>', # Console input |
|
||||||
r'int\s+main\s*\(' # Main function |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_julia(code: str) -> bool: |
|
||||||
"""Detect if code is Julia.""" |
|
||||||
patterns = [ |
|
||||||
r'function\s+\w+\s*\([^)]*\)\s*end', # Function with end |
|
||||||
r'println\(', # Print function |
|
||||||
r'using\s+\w+', # Using statement |
|
||||||
r'module\s+\w+', # Module declaration |
|
||||||
r'struct\s+\w+' # Struct declaration |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_go(code: str) -> bool: |
|
||||||
"""Detect if code is Go.""" |
|
||||||
patterns = [ |
|
||||||
r'package\s+\w+', # Package declaration |
|
||||||
r'func\s+\w+\s*\(', # Function declaration |
|
||||||
r'import\s*\(', # Import block |
|
||||||
r'fmt\.', # fmt package usage |
|
||||||
r'type\s+\w+\s+struct' # Struct declaration |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_ruby(code: str) -> bool: |
|
||||||
"""Detect if code is Ruby.""" |
|
||||||
patterns = [ |
|
||||||
r'def\s+\w+\s*(?:\([^)]*\))?\s*$', # Method definition without end |
|
||||||
r'class\s+\w+(?:\s*<\s*\w+)?\s*$', # Class definition without end |
|
||||||
r'require\s+["\']\w+["\']', # Require statement |
|
||||||
r'\b(?:puts|print)\s', # Output methods |
|
||||||
r'\bdo\s*\|[^|]*\|', # Block with parameters |
|
||||||
r'\bend\b', # End keyword |
|
||||||
r':[a-zA-Z_]\w*\s*=>', # Symbol hash syntax |
|
||||||
r'[a-zA-Z_]\w*:\s*[^,\s]' # New hash syntax |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_swift(code: str) -> bool: |
|
||||||
"""Detect if code is Swift.""" |
|
||||||
patterns = [ |
|
||||||
r'import\s+(?:Foundation|UIKit|SwiftUI)', # Common Swift imports |
|
||||||
r'(?:var|let)\s+\w+\s*:\s*\w+', # Variable declaration with type |
|
||||||
r'func\s+\w+\s*\([^)]*\)\s*(?:->\s*\w+)?\s*\{', # Function declaration |
|
||||||
r'class\s+\w+(?:\s*:\s*\w+)?\s*\{', # Class declaration |
|
||||||
r'struct\s+\w+\s*\{', # Struct declaration |
|
||||||
r'@IBOutlet|@IBAction', # iOS annotations |
|
||||||
r'guard\s+let', # Guard statement |
|
||||||
r'if\s+let|if\s+var', # Optional binding |
|
||||||
r'override\s+func', # Method override |
|
||||||
r'\bimport\s+Swift\b', # Swift import |
|
||||||
r'\?\?', # Nil coalescing operator |
|
||||||
r'extension\s+\w+', # Extensions |
|
||||||
r'protocol\s+\w+', # Protocols |
|
||||||
r'enum\s+\w+\s*(?::\s*\w+)?\s*\{', # Enums |
|
||||||
r'case\s+\w+(?:\(.*?\))?', # Enum cases |
|
||||||
r'typealias\s+\w+', # Type aliases |
|
||||||
r'init\s*\(', # Initializer |
|
||||||
r'deinit\s*\{', # Deinitializer |
|
||||||
r'\$\d+', # String interpolation |
|
||||||
r'\bOptional<', # Optional type |
|
||||||
r'\bas\?', # Type casting |
|
||||||
r'\bas!', # Forced type casting |
|
||||||
r'convenience\s+init', # Convenience initializer |
|
||||||
r'required\s+init', # Required initializer |
|
||||||
r'\bUInt\d*\b', # Swift integer types |
|
||||||
r'\bInt\d*\b', # Swift integer types |
|
||||||
r'\barray<', # Swift arrays |
|
||||||
r'\bdictionary<', # Swift dictionaries |
|
||||||
r'@escaping', # Escaping closures |
|
||||||
r'\bweak\s+var', # Weak references |
|
||||||
r'\bunowned\b' # Unowned references |
|
||||||
] |
|
||||||
return any(re.search(pattern, code, re.IGNORECASE) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_rust(code: str) -> bool: |
|
||||||
"""Detect if code is Rust.""" |
|
||||||
patterns = [ |
|
||||||
r'fn\s+\w+\s*\([^)]*\)\s*(?:->\s*[^{]+)?\s*\{', # Function declaration |
|
||||||
r'let\s+mut\s+\w+', # Mutable variable declaration |
|
||||||
r'struct\s+\w+\s*\{[^}]*\}', # Struct definition |
|
||||||
r'impl\s+\w+(?:\s+for\s+\w+)?', # Implementation block |
|
||||||
r'use\s+[\w:]+', # Import/use statement |
|
||||||
r'pub\s+(?:fn|struct|enum|mod)', # Public items |
|
||||||
r'Vec<[^>]+>', # Vec generic type |
|
||||||
r'match\s+\w+\s*\{', # Match expression |
|
||||||
r'#\[\w+(?:\([^)]*\))?\]', # Attribute macros |
|
||||||
r'\bResult<', # Result type |
|
||||||
r'\bOption<', # Option type |
|
||||||
r'\bmod\s+\w+', # Module declaration |
|
||||||
r'&mut\s+\w+', # Mutable references |
|
||||||
r'&\w+', # Immutable references |
|
||||||
r'\|[^|]*\|\s*\{', # Closure syntax |
|
||||||
r'::\s*[A-Z]\w+', # Path to types |
|
||||||
r'::(?:<[^>]+>)?\s*\w+\(', # Method call with turbofish |
|
||||||
r'enum\s+\w+\s*\{', # Enum definition |
|
||||||
r'-\s*>\s*[\w<>:]+', # Return type arrow |
|
||||||
r'async\s+fn', # Async functions |
|
||||||
r'await', # Await syntax |
|
||||||
r'move\s*\|', # Move closures |
|
||||||
r'trait\s+\w+', # Trait definition |
|
||||||
r'\bSome\(', # Some variant |
|
||||||
r'\bNone\b', # None variant |
|
||||||
r'\bOk\(', # Ok variant |
|
||||||
r'\bErr\(', # Err variant |
|
||||||
r'\bcrate::\w+', # Crate references |
|
||||||
r'pub\(crate\)', # Crate visibility |
|
||||||
r'\bdyn\s+\w+', # Dynamic dispatch |
|
||||||
r'\bif\s+let\s+Some', # If let for Option |
|
||||||
r'\bif\s+let\s+Ok' # If let for Result |
|
||||||
] |
|
||||||
return any(re.search(pattern, code, re.IGNORECASE) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_csharp(code: str) -> bool: |
|
||||||
"""Detect if code is C#.""" |
|
||||||
patterns = [ |
|
||||||
r'using\s+[\w.]+;', # Using statement |
|
||||||
r'namespace\s+[\w.]+', # Namespace declaration |
|
||||||
r'(public|private|protected|internal)\s+(class|struct|interface|enum)', # Type declarations |
|
||||||
r'(public|private|protected|internal)\s+[\w<>\[\]]+\s+\w+\s*\(', # Method declaration |
|
||||||
r'Console\.(Write|WriteLine)', # Console output |
|
||||||
r'\bvar\s+\w+\s*=', # Var keyword |
|
||||||
r'new\s+\w+\s*\(', # Object instantiation |
|
||||||
r'\bawait\s+', # Async/await |
|
||||||
r'\btask<', # Task object |
|
||||||
r'\bdynamic\b', # Dynamic type |
|
||||||
r'\bstring\b', # String type |
|
||||||
r'\$".*?\{.*?\}.*?"', # String interpolation with $ |
|
||||||
r'\bIEnumerable<', # C# generics |
|
||||||
r'\bList<', # C# collections |
|
||||||
r'\bdictionary<', # C# collections |
|
||||||
r'\bforeach\s*\(', # foreach loops |
|
||||||
r'\bassert\.\w+\(', # Unit testing |
|
||||||
r'\[\w+\]', # Attributes |
|
||||||
r'\bdelegate\b', # Delegates |
|
||||||
r'\bevent\b', # Events |
|
||||||
r'\bpartial\b', # Partial classes |
|
||||||
r'\bvirtual\b', # Virtual methods |
|
||||||
r'\boverride\b', # Override methods |
|
||||||
r'\?\s*\w+\s*\??', # Nullable types |
|
||||||
r'<\w+>\s*where\s+\w+\s*:', # Generic constraints |
|
||||||
r'set\s*\{', # Property setters |
|
||||||
r'get\s*\{', # Property getters |
|
||||||
r'using\s*\(', # Using statements with blocks |
|
||||||
r'\bget;\s*set;', # Auto-properties |
|
||||||
r'\bselect\s+new\b' # LINQ expressions |
|
||||||
] |
|
||||||
return any(re.search(pattern, code, re.IGNORECASE) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_typescript(code: str) -> bool: |
|
||||||
"""Detect if code is TypeScript.""" |
|
||||||
# TypeScript-specific patterns (not commonly found in other languages) |
|
||||||
ts_patterns = [ |
|
||||||
r':\s*[A-Za-z]+(?:<[^>]+>)?\s*(?:=|;|\)|\})', # Type annotations |
|
||||||
r'interface\s+\w+\s*\{', # Interface declaration |
|
||||||
r'class\s+\w+(?:\s+implements|\s+extends)?', # Class with implements or extends |
|
||||||
r'(private|public|protected)\s+\w+', # Access modifiers |
|
||||||
r'\w+\s*<[^>]+>', # Generic types |
|
||||||
r'import\s+\{[^}]+\}\s+from', # ES6 import |
|
||||||
r'export\s+(interface|class|type|const|let)', # Exports |
|
||||||
r'type\s+\w+\s*=', # Type aliases |
|
||||||
r'enum\s+\w+', # Enums |
|
||||||
r'@\w+(?:\([^)]*\))?', # Decorators |
|
||||||
r'\w+\s*:\s*(?:string|number|boolean|any|void|never|unknown)', # Basic TypeScript types |
|
||||||
r'(?:string|number|boolean|any|void)\[\]', # Array type notation |
|
||||||
r'readonly\s+\w+', # Readonly modifier |
|
||||||
r'namespace\s+\w+', # TypeScript namespaces |
|
||||||
r'declare\s+(?:var|let|const|function|class|interface)', # Declarations |
|
||||||
r'<[^>]+>\(', # Generic function calls |
|
||||||
r'extends\s+\w+<', # Generic type inheritance |
|
||||||
r'implements\s+\w+', # Interface implementation |
|
||||||
r'as\s+(?:string|number|boolean|any)', # Type assertions |
|
||||||
r'\?\s*:', # Optional properties |
|
||||||
r'\w+\s*\?\s*:', # Optional parameters |
|
||||||
r'keyof\s+\w+', # keyof operator |
|
||||||
r'typeof\s+\w+', # typeof operator |
|
||||||
r'\bReadonly<', # Utility types |
|
||||||
r'\bPartial<', # Utility types |
|
||||||
r'\bRequired<', # Utility types |
|
||||||
r'\bRecord<', # Utility types |
|
||||||
r'\|\s*null', # Union with null |
|
||||||
r'\|\s*undefined', # Union with undefined |
|
||||||
r'\w+\s*&\s*\w+', # Intersection types |
|
||||||
r'import\s+type', # Import types |
|
||||||
r'export\s+type' # Export types |
|
||||||
] |
|
||||||
|
|
||||||
# Check for TypeScript-specific patterns |
|
||||||
ts_unique = any(re.search(pattern, code, re.IGNORECASE) for pattern in ts_patterns) |
|
||||||
|
|
||||||
# JavaScript patterns for basic JS syntax (TypeScript is a superset of JS) |
|
||||||
js_patterns = [ |
|
||||||
r'function\s+\w+\s*\([^)]*\)', # Function declaration |
|
||||||
r'const\s+\w+\s*=', # Const declaration |
|
||||||
r'let\s+\w+\s*=', # Let declaration |
|
||||||
r'var\s+\w+\s*=', # Var declaration |
|
||||||
r'console\.(log|error|warn)' # Console methods |
|
||||||
] |
|
||||||
|
|
||||||
js_general = any(re.search(pattern, code, re.IGNORECASE) for pattern in js_patterns) |
|
||||||
|
|
||||||
# For TypeScript detection, we need to differentiate between object property definitions (which exist in JS) |
|
||||||
# and type annotations (which are unique to TS) |
|
||||||
|
|
||||||
# First, check for specific patterns from other languages to avoid false positives |
|
||||||
|
|
||||||
# Lua-specific patterns |
|
||||||
lua_patterns = [ |
|
||||||
r'local\s+\w+\s*=', # Local variable declarations |
|
||||||
r'function\s*\([^)]*\)\s*', # Anonymous functions |
|
||||||
r'require\(["\']\w+["\'](\))', # Module imports |
|
||||||
r'end\b', # End keyword |
|
||||||
r'\bnil\b', # nil value |
|
||||||
r'\bipairs\(', # ipairs function |
|
||||||
r'\bpairs\(', # pairs function |
|
||||||
r'\s*\.\.\.?\s*' # String concatenation or varargs |
|
||||||
] |
|
||||||
|
|
||||||
# PHP-specific patterns |
|
||||||
php_patterns = [ |
|
||||||
r'<\?php', # PHP opening tag |
|
||||||
r'\$\w+', # PHP variables |
|
||||||
r'\-\>\w+', # PHP object access |
|
||||||
r'public\s+function', # PHP method declaration |
|
||||||
r'namespace\s+\w+\\', # PHP namespace with backslash |
|
||||||
r'use\s+\w+\\', # PHP use statements with backslash |
|
||||||
r'\$this\->' # PHP $this reference |
|
||||||
] |
|
||||||
|
|
||||||
# If the code contains clear Lua or PHP indicators, it's not TypeScript |
|
||||||
is_likely_lua = any(re.search(pattern, code) for pattern in lua_patterns) |
|
||||||
is_likely_php = any(re.search(pattern, code) for pattern in php_patterns) |
|
||||||
|
|
||||||
if is_likely_lua or is_likely_php: |
|
||||||
return False |
|
||||||
|
|
||||||
# Check for type annotations in context (not inside object literals) |
|
||||||
type_annotation_patterns = [ |
|
||||||
r'function\s+\w+\([^)]*\)\s*:\s*\w+', # Function return type |
|
||||||
r'const\s+\w+\s*:\s*\w+', # Variable with type annotation |
|
||||||
r'let\s+\w+\s*:\s*\w+', # Variable with type annotation |
|
||||||
r':\s*(?:string|number|boolean|any|void|null|undefined)\b', # Basic type annotations |
|
||||||
r':\s*[A-Z][\w]+(?![\w\(])', # Custom type annotations (type names typically start with capital letter) |
|
||||||
r':\s*[\w\[\]<>|&]+(?=\s*(?:[,\);=]|$))' # Complex type annotations followed by certain delimiters |
|
||||||
] |
|
||||||
|
|
||||||
has_type_annotation = any(re.search(pattern, code) for pattern in type_annotation_patterns) |
|
||||||
|
|
||||||
# Look for JavaScript syntax indicators |
|
||||||
js_object_literal = re.search(r'\{\s*\w+\s*:\s*[^:\{]+\s*(?:,|\})', code) is not None |
|
||||||
contains_js_imports = re.search(r'import\s+[{\w\s,}]+\s+from\s+["\']', code) is not None |
|
||||||
|
|
||||||
# Only return true for TypeScript-specific patterns or if we have type annotations |
|
||||||
# that are likely to be TypeScript and not other languages |
|
||||||
return ts_unique or (has_type_annotation and (contains_js_imports or js_general) and not (js_object_literal and not ts_unique)) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_r(code: str) -> bool: |
|
||||||
"""Detect if code is R.""" |
|
||||||
patterns = [ |
|
||||||
r'<-\s*(?:function|\w+)', # Assignment with <- |
|
||||||
r'library\([\w\.]+\)', # Library import |
|
||||||
r'(?:data|read)\.(?:frame|csv|table)', # Data frames |
|
||||||
r'\b(?:if|for|while)\s*\(', # Control structures |
|
||||||
r'\$\w+', # Variable access with $ |
|
||||||
r'\bNA\b|\bNULL\b|\bTRUE\b|\bFALSE\b', # R constants |
|
||||||
r'c\(.*?\)', # Vector creation with c() |
|
||||||
r'(?:plot|ggplot)\(', # Plotting functions |
|
||||||
r'\s*#.*$', # R comments |
|
||||||
r'%>%', # Pipe operator |
|
||||||
r'\bfactor\(', # Factor function |
|
||||||
r'\bstr\(', # Structure function |
|
||||||
r'\bas\.\w+\(', # Type conversion functions |
|
||||||
r'\w+\s*<-\s*\w+\[.+?\]' # Subsetting with brackets |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_perl(code: str) -> bool: |
|
||||||
"""Detect if code is Perl.""" |
|
||||||
patterns = [ |
|
||||||
r'\$\w+', # Scalar variables |
|
||||||
r'@\w+', # Array variables |
|
||||||
r'%\w+', # Hash variables |
|
||||||
r'use\s+[\w:]+\s*;', # Module imports |
|
||||||
r'\bsub\s+\w+\s*\{', # Subroutine definition |
|
||||||
r'\bmy\s+(?:\$|@|%)\w+', # Variable declarations |
|
||||||
r'=~\s*(?:m|s|tr)', # Regular expression operators |
|
||||||
r'print\s+(?:\$|@|%|")', # Print statements |
|
||||||
r'(?:if|unless|while|for|foreach)\s*\(', # Control structures |
|
||||||
r'\{.*?\}.*?\{.*?\}', # Block structure typical in Perl |
|
||||||
r'->\w+', # Method calls |
|
||||||
r'\b(?:shift|pop|push|splice)', # Array operations |
|
||||||
r';\s*$', # Statements ending with semicolon |
|
||||||
r'#.*$', # Comments |
|
||||||
r'\bdie\s+', # Die statements |
|
||||||
r'\bqw\s*\(', # qw() operator |
|
||||||
r'\$_', # Special $_ variable |
|
||||||
r'\bdefined\s+(?:\$|@|%)' # Defined operator |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_lua(code: str) -> bool: |
|
||||||
"""Detect if code is Lua.""" |
|
||||||
patterns = [ |
|
||||||
r'\blocal\s+\w+', # Local variable declarations |
|
||||||
r'\bfunction\s+\w+(?:\w*\.\w+)*\s*\(', # Function definitions |
|
||||||
r'(?:end|then|do|else)\b', # Lua keywords |
|
||||||
r'\brequire\s*\(["\w\.\']+\)', # Module imports |
|
||||||
r'\breturn\s+.+?$', # Return statements |
|
||||||
r'\bnil\b', # Nil value |
|
||||||
r'\bfor\s+\w+\s*=\s*\d+\s*,\s*\d+', # Numeric for loops |
|
||||||
r'\bfor\s+\w+(?:\s*,\s*\w+)*\s+in\b', # Generic for loops |
|
||||||
r'\bif\s+.+?\s+then\b', # If statements |
|
||||||
r'\belseif\s+.+?\s+then\b', # Elseif statements |
|
||||||
r'\btable\.(\w+)\b', # Table library functions |
|
||||||
r'\bstring\.(\w+)\b', # String library functions |
|
||||||
r'\bmath\.(\w+)\b', # Math library functions |
|
||||||
r'\bpairs\(\w+\)', # Pairs function |
|
||||||
r'\bipairs\(\w+\)', # Ipairs function |
|
||||||
r'\btostring\(', # Tostring function |
|
||||||
r'\btonumber\(', # Tonumber function |
|
||||||
r'\bprint\(', # Print function |
|
||||||
r'--.*$', # Comments |
|
||||||
r'\[\[.*?\]\]', # Multiline strings |
|
||||||
r'\{\s*[\w"\']+\s*=', # Table initialization |
|
||||||
r'\w+\[\w+\]', # Table index access |
|
||||||
r'\w+\.\.\w+' # String concatenation |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_php(code: str) -> bool: |
|
||||||
"""Detect if code is PHP.""" |
|
||||||
patterns = [ |
|
||||||
r'<\?php', # PHP opening tag |
|
||||||
r'\$\w+', # Variable with $ prefix |
|
||||||
r'function\s+\w+\s*\(', # Function definition |
|
||||||
r'echo\s+[\$\w\'\"]+', # Echo statement |
|
||||||
r'class\s+\w+(?:\s+extends|\s+implements)?', # Class definition |
|
||||||
r'(?:public|private|protected)\s+function', # Class methods |
|
||||||
r'(?:public|private|protected)\s+\$\w+', # Class properties |
|
||||||
r'namespace\s+[\w\\\\]+', # Namespace declaration |
|
||||||
r'use\s+[\w\\\\]+', # Use statement |
|
||||||
r'=>', # Array key => value syntax |
|
||||||
r'array\s*\(', # Array creation |
|
||||||
r'\[\s*[\'\"]*\w+[\'\"]*\s*\]', # Array access with [] |
|
||||||
r'require(?:_once)?\s*\(', # Require statements |
|
||||||
r'include(?:_once)?\s*\(', # Include statements |
|
||||||
r'new\s+\w+', # Object instantiation |
|
||||||
r'->', # Object property/method access |
|
||||||
r'::', # Static property/method access |
|
||||||
r'<?=.*?(?:\?>|$)', # Short echo syntax |
|
||||||
r'if\s*\(.+?\)\s*\{', # If statements |
|
||||||
r'foreach\s*\(\s*\$\w+', # Foreach loops |
|
||||||
r';$' # Statement ending with semicolon |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_kotlin(code: str) -> bool: |
|
||||||
"""Detect if code is Kotlin.""" |
|
||||||
patterns = [ |
|
||||||
r'fun\s+\w+\s*\(', # Function declaration |
|
||||||
r'val\s+\w+(?:\s*:\s*\w+)?', # Val declaration |
|
||||||
r'var\s+\w+(?:\s*:\s*\w+)?', # Var declaration |
|
||||||
r'class\s+\w+(?:\s*\((?:[^)]*)\))?', # Class declaration |
|
||||||
r'package\s+[\w\.]+', # Package declaration |
|
||||||
r'import\s+[\w\.]+', # Import statement |
|
||||||
r'object\s+\w+', # Object declaration |
|
||||||
r'interface\s+\w+', # Interface declaration |
|
||||||
r'data\s+class', # Data class |
|
||||||
r'(?:override|open|abstract|final)\s+fun', # Modified functions |
|
||||||
r'(?:companion|sealed)\s+object', # Special objects |
|
||||||
r'when\s*\(', # When expression |
|
||||||
r'(?:if|else|for|while)\s*\(', # Control structures |
|
||||||
r'->', # Lambda syntax |
|
||||||
r'[\w\.\(\)]+\.\w+\{', # Extension functions |
|
||||||
r'(?:List|Set|Map)<', # Generic collections |
|
||||||
r'(?:private|public|internal|protected)', # Visibility modifiers |
|
||||||
r'lateinit\s+var', # Lateinit vars |
|
||||||
r'(?:suspend|inline)\s+fun', # Special function modifiers |
|
||||||
r'@\w+(?:\([^)]*\))?' # Annotations |
|
||||||
] |
|
||||||
return any(re.search(pattern, code) for pattern in patterns) |
|
||||||
|
|
||||||
|
|
||||||
@staticmethod |
|
||||||
def detect_sql(code: str) -> bool: |
|
||||||
"""Detect if code is SQL.""" |
|
||||||
patterns = [ |
|
||||||
r'SELECT\s+[\w\*,\s]+\s+FROM', # SELECT statement |
|
||||||
r'INSERT\s+INTO\s+\w+', # INSERT statement |
|
||||||
r'UPDATE\s+\w+\s+SET', # UPDATE statement |
|
||||||
r'DELETE\s+FROM\s+\w+', # DELETE statement |
|
||||||
r'CREATE\s+TABLE\s+\w+', # CREATE TABLE statement |
|
||||||
r'ALTER\s+TABLE\s+\w+', # ALTER TABLE statement |
|
||||||
r'DROP\s+TABLE\s+\w+', # DROP TABLE statement |
|
||||||
r'TRUNCATE\s+TABLE\s+\w+', # TRUNCATE TABLE statement |
|
||||||
r'JOIN\s+\w+\s+ON', # JOIN clause |
|
||||||
r'WHERE\s+\w+\s*(?:=|<|>|<=|>=|<>|!=|LIKE|IN)', # WHERE clause |
|
||||||
r'GROUP\s+BY\s+\w+', # GROUP BY clause |
|
||||||
r'ORDER\s+BY\s+\w+\s+(?:ASC|DESC)?', # ORDER BY clause |
|
||||||
r'HAVING\s+\w+', # HAVING clause |
|
||||||
r'CONSTRAINT\s+\w+', # CONSTRAINT declaration |
|
||||||
r'PRIMARY\s+KEY', # PRIMARY KEY constraint |
|
||||||
r'FOREIGN\s+KEY', # FOREIGN KEY constraint |
|
||||||
r'(?:VARCHAR|INT|INTEGER|FLOAT|DATE|DATETIME|BOOLEAN|TEXT|BLOB)', # Common data types |
|
||||||
r'(?:COUNT|SUM|AVG|MIN|MAX)\s*\(', # Aggregate functions |
|
||||||
r'CASE\s+WHEN\s+.+?\s+THEN', # CASE statement |
|
||||||
r'BEGIN\s+TRANSACTION', # Transaction control |
|
||||||
r'COMMIT', # COMMIT statement |
|
||||||
r'ROLLBACK' # ROLLBACK statement |
|
||||||
] |
|
||||||
return any(re.search(pattern, code, re.IGNORECASE) for pattern in patterns) |
|
||||||
|
|
||||||
|
|
||||||
def __init__(self): |
|
||||||
"""Initialize language detector with detection functions.""" |
|
||||||
self.detectors = { |
|
||||||
"Python": self.detect_python, |
|
||||||
"JavaScript": self.detect_javascript, |
|
||||||
"Java": self.detect_java, |
|
||||||
"C++": self.detect_cpp, |
|
||||||
"Julia": self.detect_julia, |
|
||||||
"Go": self.detect_go, |
|
||||||
"Ruby": self.detect_ruby, |
|
||||||
"Swift": self.detect_swift, |
|
||||||
"Rust": self.detect_rust, |
|
||||||
"C#": self.detect_csharp, |
|
||||||
"TypeScript": self.detect_typescript, |
|
||||||
"R": self.detect_r, |
|
||||||
"Perl": self.detect_perl, |
|
||||||
"Lua": self.detect_lua, |
|
||||||
"PHP": self.detect_php, |
|
||||||
"Kotlin": self.detect_kotlin, |
|
||||||
"SQL": self.detect_sql |
|
||||||
} |
|
||||||
|
|
||||||
|
|
||||||
def detect_language(self, code: str) -> str: |
|
||||||
""" |
|
||||||
Detect the programming language of the given code. |
|
||||||
|
|
||||||
Args: |
|
||||||
code: Code snippet to analyze |
|
||||||
|
|
||||||
Returns: |
|
||||||
Detected language name or None if unknown |
|
||||||
""" |
|
||||||
# Initial matching - which language detectors return positive |
|
||||||
matches = {} |
|
||||||
|
|
||||||
# First pass: check which languages match |
|
||||||
for lang, detector in self.detectors.items(): |
|
||||||
if detector(code): |
|
||||||
matches[lang] = 0 |
|
||||||
|
|
||||||
if not matches: |
|
||||||
return None |
|
||||||
|
|
||||||
# If only one language matches, return it |
|
||||||
if len(matches) == 1: |
|
||||||
return list(matches.keys())[0] |
|
||||||
|
|
||||||
# Improved scoring system with distinctive language features |
|
||||||
# These patterns are selected to be highly distinctive to each language |
|
||||||
# Each pattern is assigned a weight based on how uniquely it identifies a language |
|
||||||
unique_patterns = { |
|
||||||
# C# distinctive features (to differentiate from Java and other languages) |
|
||||||
"C#": [ |
|
||||||
(r'using\s+[\w.]+;', 3), # Using statement |
|
||||||
(r'namespace\s+[\w.]+', 3), # Namespace |
|
||||||
(r'Console\.(Write|WriteLine)', 2), # Console output |
|
||||||
(r'\bvar\s+\w+\s*=', 3), # Var keyword |
|
||||||
(r'\bawait\s+', 4), # Async/await |
|
||||||
(r'\btask<', 4), # Task object |
|
||||||
(r'\bdynamic\b', 4), # Dynamic type |
|
||||||
(r'\$".*?\{.*?\}.*?"', 5), # String interpolation with $ |
|
||||||
(r'\bIEnumerable<', 4), # C# collections |
|
||||||
(r'\bList<', 3), # C# collections |
|
||||||
(r'\bforeach\s*\(', 2), # foreach loops |
|
||||||
(r'\bget;\s*set;', 5), # Auto-properties |
|
||||||
(r'\bselect\s+new\b', 4), # LINQ |
|
||||||
(r'\bwhere\s+\w+\s*=', 4), # LINQ |
|
||||||
(r'<\w+>\s*where\s+\w+\s*:', 5) # Generic constraints |
|
||||||
], |
|
||||||
|
|
||||||
# Rust distinctive features (to differentiate from C++) |
|
||||||
"Rust": [ |
|
||||||
(r'fn\s+\w+\s*\(', 3), # Function declaration |
|
||||||
(r'let\s+mut\s+\w+', 5), # Mutable variable |
|
||||||
(r'impl\s+\w+(?:\s+for\s+\w+)?', 6), # Implementation |
|
||||||
(r'use\s+[\w:]+', 2), # Use statement |
|
||||||
(r'pub\s+(?:fn|struct|enum|mod)', 4), # Public items |
|
||||||
(r'\bResult<', 5), # Result type |
|
||||||
(r'\bOption<', 5), # Option type |
|
||||||
(r'\bmod\s+\w+', 4), # Module declaration |
|
||||||
(r'&mut\s+\w+', 5), # Mutable references |
|
||||||
(r'trait\s+\w+', 6), # Trait definition |
|
||||||
(r'\bSome\(', 5), # Some variant |
|
||||||
(r'\bNone\b', 5), # None variant |
|
||||||
(r'\bOk\(', 5), # Ok variant |
|
||||||
(r'\bErr\(', 5), # Err variant |
|
||||||
(r'\bcrate::\w+', 5), # Crate references |
|
||||||
(r'\bif\s+let\s+Some', 6) # If let for Option |
|
||||||
], |
|
||||||
|
|
||||||
# Swift distinctive features (to differentiate from Kotlin) |
|
||||||
"Swift": [ |
|
||||||
(r'import\s+(?:Foundation|UIKit|SwiftUI)', 6), # Swift imports |
|
||||||
(r'@IBOutlet|@IBAction', 8), # iOS annotations |
|
||||||
(r'guard\s+let', 6), # Guard statement |
|
||||||
(r'\bOptional<', 6), # Optional type |
|
||||||
(r'\bas\?', 5), # Type casting |
|
||||||
(r'\bas!', 5), # Forced type casting |
|
||||||
(r'\?\?', 4), # Nil coalescing |
|
||||||
(r'extension\s+\w+', 4), # Extensions |
|
||||||
(r'protocol\s+\w+', 4), # Protocols |
|
||||||
(r'convenience\s+init', 6), # Convenience init |
|
||||||
(r'required\s+init', 6), # Required init |
|
||||||
(r'\bUInt\d*\b', 5), # Swift integer types |
|
||||||
(r'\bInt\d*\b', 4), # Swift integer types |
|
||||||
(r'\barray<', 3), # Swift arrays |
|
||||||
(r'\bdictionary<', 3), # Swift dictionaries |
|
||||||
(r'@escaping', 8) # Escaping closures |
|
||||||
], |
|
||||||
|
|
||||||
# TypeScript distinctive features (to differentiate from JavaScript and Python) |
|
||||||
"TypeScript": [ |
|
||||||
(r':\s*[A-Za-z]+(?:<[^>]+>)?\s*(?:=|;|\)|\})', 5), # Type annotations |
|
||||||
(r'interface\s+\w+\s*\{', 6), # Interface |
|
||||||
(r'type\s+\w+\s*=', 6), # Type aliases |
|
||||||
(r'enum\s+\w+', 5), # Enums |
|
||||||
(r'namespace\s+\w+', 6), # TypeScript namespaces |
|
||||||
(r'declare\s+(?:var|let|const|function|class|interface)', 7), # Declarations |
|
||||||
(r'as\s+(?:string|number|boolean|any)', 6), # Type assertions |
|
||||||
(r'\?\s*:', 5), # Optional properties |
|
||||||
(r'\w+\s*\?\s*:', 5), # Optional parameters |
|
||||||
(r'keyof\s+\w+', 7), # keyof operator |
|
||||||
(r'typeof\s+\w+', 6), # typeof operator |
|
||||||
(r'\bReadonly<', 7), # Utility types |
|
||||||
(r'\bPartial<', 7), # Utility types |
|
||||||
(r'\bRequired<', 7), # Utility types |
|
||||||
(r'\bRecord<', 7), # Utility types |
|
||||||
(r'\w+\s*&\s*\w+', 6), # Intersection types |
|
||||||
(r'import\s+type', 8), # Import types |
|
||||||
(r'export\s+type', 8) # Export types |
|
||||||
], |
|
||||||
|
|
||||||
# Keep other language patterns but add more weight to distinctive features |
|
||||||
"PHP": [(r'<\?php', 10), (r'\$\w+\s*=', 2), (r'function\s+\w+\s*\(.*?\)\s*\{', 2)], |
|
||||||
"SQL": [(r'(?i)SELECT\s+[\w\*,\s]+\s+FROM', 10), (r'(?i)INSERT\s+INTO', 8), (r'(?i)CREATE\s+TABLE', 8)], |
|
||||||
"Perl": [(r'\buse\s+[\w:]+\s*;', 6), (r'\bmy\s+(?:\$|@|%)', 8), (r'\bperl\b', 10)], |
|
||||||
"Lua": [(r'\blocal\s+\w+', 6), (r'\bfunction\s+\w+(?:\w*\.\w+)*\s*\(', 6), (r'\bend\s*$', 4)], |
|
||||||
"Kotlin": [(r'\bfun\s+\w+\s*\(', 6), (r'\bval\s+\w+(?:\s*:\s*\w+)?', 6), (r'data\s+class', 10)], |
|
||||||
"Ruby": [(r'\bdef\s+\w+\s*(?:\([^)]*\))?\s*$', 6), (r'\bend\b', 4), (r'\bdo\s*\|[^|]*\|', 6)], |
|
||||||
"R": [(r'<-\s*(?:function|\w+)', 8), (r'library\([\w\.]+\)', 8), (r'%>%', 10)], |
|
||||||
"Python": [(r'def\s+\w+\s*\([^)]*\)\s*:', 6), (r'import\s+[\w\s,]+', 4), (r'from\s+[\w.]+\s+import', 6)], |
|
||||||
"JavaScript": [(r'function\s+\w+\s*\([^)]*\)', 4), (r'const\s+\w+\s*=', 3), (r'let\s+\w+\s*=', 3)], |
|
||||||
"Java": [(r'public\s+class\s+\w+', 6), (r'public\s+static\s+void\s+main', 8), (r'System\.(out|err)\.', 6)], |
|
||||||
"C++": [(r'#include\s*<[^>]+>', 6), (r'std::\w+', 8), (r'int\s+main\s*\(', 4)], |
|
||||||
"Julia": [(r'function\s+\w+\s*\([^)]*\)\s*end', 8), (r'module\s+\w+', 6), (r'using\s+\w+', 4)], |
|
||||||
"Go": [(r'package\s+\w+', 6), (r'func\s+\w+\s*\(', 4), (r'import\s*\(', 4)] |
|
||||||
} |
|
||||||
|
|
||||||
# Apply the detailed scoring system |
|
||||||
for lang, patterns in unique_patterns.items(): |
|
||||||
if lang in matches: |
|
||||||
for pattern, weight in patterns: |
|
||||||
if re.search(pattern, code, re.IGNORECASE): |
|
||||||
matches[lang] += weight |
|
||||||
|
|
||||||
# Additional weighting for core language features |
|
||||||
# C# vs Java disambiguation |
|
||||||
if "C#" in matches and "Java" in matches: |
|
||||||
# C# specific features that are unlikely in Java |
|
||||||
csharp_specific = [ |
|
||||||
(r'\$"', 8), # String interpolation |
|
||||||
(r'\bvar\b', 6), # var keyword |
|
||||||
(r'\basync\b', 6), # async keyword |
|
||||||
(r'\bawait\b', 6), # await keyword |
|
||||||
(r'\bIEnumerable<', 6), # C# specific interfaces |
|
||||||
(r'\bget;\s*set;', 8), # Auto-properties |
|
||||||
(r'\bLINQ\b', 8), # LINQ |
|
||||||
(r'\busing\s+static', 8) # using static |
|
||||||
] |
|
||||||
for pattern, weight in csharp_specific: |
|
||||||
if re.search(pattern, code, re.IGNORECASE): |
|
||||||
matches["C#"] += weight |
|
||||||
|
|
||||||
# Java specific features that are unlikely in C# |
|
||||||
java_specific = [ |
|
||||||
(r'\bimport\s+java\.', 8), # Java imports |
|
||||||
(r'\bSystem\.out\.print', 6), # Java System.out |
|
||||||
(r'\bpublic\s+static\s+void\s+main', 8), # Java main method |
|
||||||
(r'\@Override\b', 6), # Java annotations |
|
||||||
(r'\bextends\s+\w+\s*\{', 6), # Java inheritance |
|
||||||
(r'\bimplements\s+\w+\s*\{', 6) # Java interface implementation |
|
||||||
] |
|
||||||
for pattern, weight in java_specific: |
|
||||||
if re.search(pattern, code, re.IGNORECASE): |
|
||||||
matches["Java"] += weight |
|
||||||
|
|
||||||
# Rust vs C++ disambiguation |
|
||||||
if "Rust" in matches and "C++" in matches: |
|
||||||
# Rust specific features that are unlikely in C++ |
|
||||||
rust_specific = [ |
|
||||||
(r'\bfn\b', 8), # fn keyword |
|
||||||
(r'\blet\b', 8), # let keyword |
|
||||||
(r'\bmut\b', 8), # mut keyword |
|
||||||
(r'\bimpl\b', 8), # impl keyword |
|
||||||
(r'\buse\b', 6), # use keyword |
|
||||||
(r'\bSome\(', 8), # Some variant |
|
||||||
(r'\bNone\b', 8), # None variant |
|
||||||
(r'\bResult<', 8), # Result type |
|
||||||
(r'\bOption<', 8) # Option type |
|
||||||
] |
|
||||||
for pattern, weight in rust_specific: |
|
||||||
if re.search(pattern, code, re.IGNORECASE): |
|
||||||
matches["Rust"] += weight |
|
||||||
|
|
||||||
# C++ specific features that are unlikely in Rust |
|
||||||
cpp_specific = [ |
|
||||||
(r'#include', 8), # C++ include |
|
||||||
(r'std::', 6), # C++ std namespace |
|
||||||
(r'\bclass\b', 6), # class keyword |
|
||||||
(r'\bpublic:\b', 8), # public: access specifier |
|
||||||
(r'\bprivate:\b', 8), # private: access specifier |
|
||||||
(r'\bprotected:\b', 8), # protected: access specifier |
|
||||||
(r'\btypedef\b', 8), # typedef keyword |
|
||||||
(r'\bnew\b', 4), # new keyword |
|
||||||
(r'\bdelete\b', 8) # delete keyword |
|
||||||
] |
|
||||||
for pattern, weight in cpp_specific: |
|
||||||
if re.search(pattern, code, re.IGNORECASE): |
|
||||||
matches["C++"] += weight |
|
||||||
|
|
||||||
# Swift vs Kotlin disambiguation |
|
||||||
if "Swift" in matches and "Kotlin" in matches: |
|
||||||
# Swift specific features that are unlikely in Kotlin |
|
||||||
swift_specific = [ |
|
||||||
(r'\bimport\s+(?:Foundation|UIKit|SwiftUI)', 10), # Swift imports |
|
||||||
(r'\bguard\b', 8), # guard keyword |
|
||||||
(r'\?\?', 8), # Nil coalescing operator |
|
||||||
(r'\bas\?', 8), # Optional downcasting |
|
||||||
(r'\bas!', 8), # Forced downcasting |
|
||||||
(r'@IBOutlet', 10), # Interface Builder |
|
||||||
(r'@IBAction', 10), # Interface Builder |
|
||||||
(r'@objc', 10), # Objective-C interop |
|
||||||
(r'\bUIViewController\b', 10) # UIKit |
|
||||||
] |
|
||||||
for pattern, weight in swift_specific: |
|
||||||
if re.search(pattern, code, re.IGNORECASE): |
|
||||||
matches["Swift"] += weight |
|
||||||
|
|
||||||
# Kotlin specific features that are unlikely in Swift |
|
||||||
kotlin_specific = [ |
|
||||||
(r'\bdata\s+class', 10), # Data class |
|
||||||
(r'\bfun\b', 8), # fun keyword |
|
||||||
(r'\bval\b', 6), # val keyword |
|
||||||
(r'\bvar\b', 4), # var keyword |
|
||||||
(r'\bcompanion\s+object', 10), # Companion object |
|
||||||
(r'\bwhen\b', 8), # when expression |
|
||||||
(r'\bcoroutine', 10), # Coroutines |
|
||||||
(r'\bsuspend\b', 10), # Suspend functions |
|
||||||
(r'\blateinit\b', 10), # Late initialization |
|
||||||
(r'\bimport\s+(?:kotlin|androidx|android)', 10) # Kotlin imports |
|
||||||
] |
|
||||||
for pattern, weight in kotlin_specific: |
|
||||||
if re.search(pattern, code, re.IGNORECASE): |
|
||||||
matches["Kotlin"] += weight |
|
||||||
|
|
||||||
# TypeScript vs JavaScript disambiguation (and Python confusion) |
|
||||||
if "TypeScript" in matches and ("JavaScript" in matches or "Python" in matches): |
|
||||||
# TypeScript specific features that are unlikely in JS or Python |
|
||||||
ts_specific = [ |
|
||||||
(r':\s*[A-Za-z]+', 8), # Type annotations |
|
||||||
(r'\binterface\b', 8), # interface keyword |
|
||||||
(r'\btype\b\s+\w+\s*=', 10), # type aliases |
|
||||||
(r'\bnamespace\b', 10), # namespace keyword |
|
||||||
(r'\benum\b', 8), # enum keyword |
|
||||||
(r'\bas\s+(?:string|number|boolean|any)', 10), # Type assertions |
|
||||||
(r'\?:\s*', 10), # Optional types |
|
||||||
(r'\bReadonly<', 10), # Utility types |
|
||||||
(r'\w+\s*&\s*\w+', 10), # Intersection types |
|
||||||
(r'\bimport\s+type', 10), # Import types |
|
||||||
(r'\[\w+\s*:\s*\w+\]', 10) # Typed arrays |
|
||||||
] |
|
||||||
for pattern, weight in ts_specific: |
|
||||||
if re.search(pattern, code, re.IGNORECASE): |
|
||||||
matches["TypeScript"] += weight |
|
||||||
# Remove Python if it's a false positive |
|
||||||
if "Python" in matches and matches["Python"] < matches["TypeScript"]: |
|
||||||
matches.pop("Python", None) |
|
||||||
|
|
||||||
# Return the language with the highest score |
|
||||||
if matches: |
|
||||||
return max(matches.items(), key=lambda x: x[1])[0] |
|
||||||
|
|
||||||
return None |
|
||||||
|
|
||||||
def validate_language(self, code: str, expected_lang: str) -> tuple[bool, str]: |
|
||||||
"""Validate if code matches the expected programming language.""" |
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
logger.info(f"Starting code validation for {expected_lang}") |
|
||||||
logger.info(f"Code length: {len(code)} characters") |
|
||||||
|
|
||||||
if not code or not expected_lang: |
|
||||||
logger.warning("Empty code or language not specified") |
|
||||||
return True, "" |
|
||||||
|
|
||||||
detector = self.detectors.get(expected_lang) |
|
||||||
if not detector: |
|
||||||
logger.warning(f"No detector found for language: {expected_lang}") |
|
||||||
return True, "" |
|
||||||
|
|
||||||
if detector(code): |
|
||||||
logger.info(f"Code successfully validated as {expected_lang}") |
|
||||||
return True, "" |
|
||||||
|
|
||||||
detected_lang = self.detect_language(code) |
|
||||||
error_msg = f"Code appears to be {detected_lang or 'unknown'} but {expected_lang} was selected" |
|
||||||
logger.error(f"Language validation failed: {error_msg}") |
|
||||||
return False, error_msg |
|
@ -1,31 +0,0 @@ |
|||||||
"""Main entry point for the CodeXchange AI application.""" |
|
||||||
|
|
||||||
from src.ai_code_converter.app import CodeConverterApp |
|
||||||
from src.ai_code_converter.utils.logger import setup_logger |
|
||||||
|
|
||||||
def main(): |
|
||||||
"""Initialize and run the application.""" |
|
||||||
# Initialize logger |
|
||||||
logger = setup_logger("ai_code_converter.main") |
|
||||||
|
|
||||||
try: |
|
||||||
logger.info("="*50) |
|
||||||
logger.info("Starting CodeXchange AI") |
|
||||||
logger.info("="*50) |
|
||||||
|
|
||||||
logger.info("Initializing application components") |
|
||||||
app = CodeConverterApp() |
|
||||||
|
|
||||||
logger.info("Starting Gradio interface") |
|
||||||
app.run(share=True) |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
logger.error("Application failed to start", exc_info=True) |
|
||||||
raise |
|
||||||
finally: |
|
||||||
logger.info("="*50) |
|
||||||
logger.info("Application shutdown") |
|
||||||
logger.info("="*50) |
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
main() |
|
@ -1 +0,0 @@ |
|||||||
"""Model-related modules.""" |
|
@ -1,301 +0,0 @@ |
|||||||
"""Module for handling AI model streaming responses.""" |
|
||||||
|
|
||||||
import logging |
|
||||||
import time |
|
||||||
from typing import Generator, Any, Callable, TypeVar, cast |
|
||||||
from anthropic import Anthropic, AnthropicError, APIError, RateLimitError, AuthenticationError |
|
||||||
import google.generativeai as genai |
|
||||||
from openai import OpenAI |
|
||||||
|
|
||||||
from src.ai_code_converter.config import ( |
|
||||||
OPENAI_MODEL, |
|
||||||
CLAUDE_MODEL, |
|
||||||
DEEPSEEK_MODEL, |
|
||||||
GEMINI_MODEL, |
|
||||||
GROQ_MODEL |
|
||||||
) |
|
||||||
|
|
||||||
logger = logging.getLogger(__name__) |
|
||||||
|
|
||||||
# Type variable for generic retry function |
|
||||||
T = TypeVar('T') |
|
||||||
|
|
||||||
def retry_with_exponential_backoff( |
|
||||||
max_retries: int = 5, |
|
||||||
initial_delay: float = 1.0, |
|
||||||
exponential_base: float = 2.0, |
|
||||||
jitter: bool = True, |
|
||||||
retryable_exceptions: tuple = (Exception,), |
|
||||||
retryable_return: Callable[[Any], bool] = None, |
|
||||||
) -> Callable: |
|
||||||
"""Retry decorator with exponential backoff |
|
||||||
|
|
||||||
Args: |
|
||||||
max_retries: Maximum number of retries |
|
||||||
initial_delay: Initial delay in seconds |
|
||||||
exponential_base: Base for exponential calculation |
|
||||||
jitter: Add random jitter to delay |
|
||||||
retryable_exceptions: Exceptions that trigger retry |
|
||||||
retryable_return: Function that takes the return value and returns |
|
||||||
True if it should be retried |
|
||||||
|
|
||||||
Returns: |
|
||||||
Decorator function |
|
||||||
""" |
|
||||||
def decorator(func: Callable) -> Callable: |
|
||||||
def wrapper(*args: Any, **kwargs: Any) -> Any: |
|
||||||
# Initialize variables |
|
||||||
num_retries = 0 |
|
||||||
delay = initial_delay |
|
||||||
|
|
||||||
# Loop until max retries reached |
|
||||||
while True: |
|
||||||
try: |
|
||||||
response = func(*args, **kwargs) |
|
||||||
|
|
||||||
# Check if we should retry based on response value |
|
||||||
if retryable_return and num_retries < max_retries: |
|
||||||
try: |
|
||||||
if retryable_return(response): |
|
||||||
num_retries += 1 |
|
||||||
logger.warning( |
|
||||||
f"Retrying {func.__name__} due to response condition " |
|
||||||
f"(attempt {num_retries} of {max_retries})" |
|
||||||
) |
|
||||||
time.sleep(delay) |
|
||||||
delay = calculate_next_delay(delay, exponential_base, jitter) |
|
||||||
continue |
|
||||||
except Exception as e: |
|
||||||
# If retryable_return itself fails, log and continue |
|
||||||
logger.warning(f"Error in retry condition: {e}") |
|
||||||
|
|
||||||
return response |
|
||||||
|
|
||||||
except retryable_exceptions as e: |
|
||||||
# Check if we've exceeded max retries |
|
||||||
if num_retries >= max_retries: |
|
||||||
logger.error( |
|
||||||
f"Maximum retries ({max_retries}) exceeded for {func.__name__}: {str(e)}" |
|
||||||
) |
|
||||||
raise |
|
||||||
|
|
||||||
# Handle specific error types with custom messages |
|
||||||
if hasattr(e, 'error') and isinstance(e.error, dict) and e.error.get('type') == 'overloaded_error': |
|
||||||
logger.warning( |
|
||||||
f"Service overloaded, retrying {func.__name__} " |
|
||||||
f"(attempt {num_retries + 1} of {max_retries})" |
|
||||||
) |
|
||||||
else: |
|
||||||
logger.warning( |
|
||||||
f"Exception in {func.__name__}, retrying " |
|
||||||
f"(attempt {num_retries + 1} of {max_retries}): {str(e)}" |
|
||||||
) |
|
||||||
|
|
||||||
# Increment retry count and delay |
|
||||||
num_retries += 1 |
|
||||||
time.sleep(delay) |
|
||||||
delay = calculate_next_delay(delay, exponential_base, jitter) |
|
||||||
|
|
||||||
return cast(Callable, wrapper) |
|
||||||
return decorator |
|
||||||
|
|
||||||
|
|
||||||
def calculate_next_delay(current_delay: float, exponential_base: float, jitter: bool) -> float: |
|
||||||
"""Calculate the next delay time using exponential backoff and optional jitter""" |
|
||||||
import random |
|
||||||
delay = current_delay * exponential_base |
|
||||||
# Add jitter - random value between -0.2 and +0.2 of the delay |
|
||||||
if jitter: |
|
||||||
delay = delay * (1 + random.uniform(-0.2, 0.2)) |
|
||||||
return delay |
|
||||||
|
|
||||||
|
|
||||||
class AIModelStreamer: |
|
||||||
"""Class for handling streaming responses from various AI models.""" |
|
||||||
|
|
||||||
def __init__(self, openai_client: OpenAI, claude_client: Anthropic, |
|
||||||
deepseek_client: OpenAI, groq_client: OpenAI, gemini_model: genai.GenerativeModel): |
|
||||||
"""Initialize with AI model clients.""" |
|
||||||
self.openai = openai_client |
|
||||||
self.claude = claude_client |
|
||||||
self.deepseek = deepseek_client |
|
||||||
self.groq = groq_client |
|
||||||
self.gemini = gemini_model |
|
||||||
self.max_retries = 5 |
|
||||||
|
|
||||||
@retry_with_exponential_backoff( |
|
||||||
max_retries=5, |
|
||||||
initial_delay=1.0, |
|
||||||
retryable_exceptions=(Exception,) |
|
||||||
) |
|
||||||
def _call_gpt_api(self, prompt: str): |
|
||||||
"""Call the GPT API with retry logic""" |
|
||||||
messages = [{"role": "user", "content": prompt}] |
|
||||||
return self.openai.chat.completions.create( |
|
||||||
model=OPENAI_MODEL, |
|
||||||
messages=messages, |
|
||||||
stream=True |
|
||||||
) |
|
||||||
|
|
||||||
def stream_gpt(self, prompt: str) -> Generator[str, None, None]: |
|
||||||
"""Stream responses from GPT model.""" |
|
||||||
try: |
|
||||||
stream = self._call_gpt_api(prompt) |
|
||||||
|
|
||||||
response = "" |
|
||||||
for chunk in stream: |
|
||||||
fragment = chunk.choices[0].delta.content or "" |
|
||||||
response += fragment |
|
||||||
yield response |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
logger.error(f"GPT API error: {str(e)}", exc_info=True) |
|
||||||
yield f"Error with GPT API: {str(e)}" |
|
||||||
|
|
||||||
@retry_with_exponential_backoff( |
|
||||||
max_retries=5, |
|
||||||
initial_delay=1.0, |
|
||||||
exponential_base=2.0, |
|
||||||
retryable_exceptions=(Exception,) |
|
||||||
) |
|
||||||
def _call_claude_api(self, prompt: str): |
|
||||||
"""Call the Claude API with retry logic""" |
|
||||||
return self.claude.messages.stream( |
|
||||||
model=CLAUDE_MODEL, |
|
||||||
max_tokens=4000, |
|
||||||
messages=[{"role": "user", "content": prompt}] |
|
||||||
) |
|
||||||
|
|
||||||
def stream_claude(self, prompt: str) -> Generator[str, None, None]: |
|
||||||
"""Stream responses from Claude model with retry for overloaded errors.""" |
|
||||||
retry_count = 0 |
|
||||||
max_retries = self.max_retries |
|
||||||
delay = 1.0 |
|
||||||
|
|
||||||
while True: |
|
||||||
try: |
|
||||||
result = self._call_claude_api(prompt) |
|
||||||
|
|
||||||
response = "" |
|
||||||
with result as stream: |
|
||||||
for text in stream.text_stream: |
|
||||||
response += text |
|
||||||
yield response |
|
||||||
|
|
||||||
# If we get here, we succeeded, so break out of retry loop |
|
||||||
break |
|
||||||
|
|
||||||
except (AnthropicError, APIError) as e: |
|
||||||
# Special handling for overloaded_error |
|
||||||
if hasattr(e, 'error') and getattr(e, 'error', {}).get('type') == 'overloaded_error': |
|
||||||
if retry_count < max_retries: |
|
||||||
retry_count += 1 |
|
||||||
wait_time = delay * (2 ** (retry_count - 1)) # Exponential backoff |
|
||||||
logger.warning(f"Claude API overloaded, retrying in {wait_time:.2f}s (attempt {retry_count}/{max_retries})") |
|
||||||
time.sleep(wait_time) |
|
||||||
continue |
|
||||||
|
|
||||||
# If reached maximum retries or not an overloaded error |
|
||||||
logger.error(f"Claude API error: {str(e)}", exc_info=True) |
|
||||||
yield f"Error with Claude API: {str(e)}" |
|
||||||
break |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Claude API error: {str(e)}", exc_info=True) |
|
||||||
yield f"Error with Claude API: {str(e)}" |
|
||||||
break |
|
||||||
|
|
||||||
@retry_with_exponential_backoff( |
|
||||||
max_retries=5, |
|
||||||
initial_delay=1.0, |
|
||||||
retryable_exceptions=(Exception,) |
|
||||||
) |
|
||||||
def _call_deepseek_api(self, prompt: str): |
|
||||||
"""Call the DeepSeek API with retry logic""" |
|
||||||
messages = [{"role": "user", "content": prompt}] |
|
||||||
return self.deepseek.chat.completions.create( |
|
||||||
model=DEEPSEEK_MODEL, |
|
||||||
messages=messages, |
|
||||||
stream=True, |
|
||||||
temperature=0.7, |
|
||||||
max_tokens=4000 |
|
||||||
) |
|
||||||
|
|
||||||
def stream_deepseek(self, prompt: str) -> Generator[str, None, None]: |
|
||||||
"""Stream responses from DeepSeek model.""" |
|
||||||
try: |
|
||||||
stream = self._call_deepseek_api(prompt) |
|
||||||
|
|
||||||
reply = "" |
|
||||||
for chunk in stream: |
|
||||||
fragment = chunk.choices[0].delta.content or "" |
|
||||||
reply += fragment |
|
||||||
yield reply |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
logger.error(f"DeepSeek API error: {str(e)}", exc_info=True) |
|
||||||
yield f"Error with DeepSeek API: {str(e)}" |
|
||||||
|
|
||||||
@retry_with_exponential_backoff( |
|
||||||
max_retries=5, |
|
||||||
initial_delay=1.0, |
|
||||||
retryable_exceptions=(Exception,) |
|
||||||
) |
|
||||||
def _call_groq_api(self, prompt: str): |
|
||||||
"""Call the GROQ API with retry logic""" |
|
||||||
messages = [{"role": "user", "content": prompt}] |
|
||||||
return self.groq.chat.completions.create( |
|
||||||
model=GROQ_MODEL, |
|
||||||
messages=messages, |
|
||||||
stream=True, |
|
||||||
temperature=0.7, |
|
||||||
max_tokens=4000 |
|
||||||
) |
|
||||||
|
|
||||||
def stream_groq(self, prompt: str) -> Generator[str, None, None]: |
|
||||||
"""Stream responses from GROQ model.""" |
|
||||||
try: |
|
||||||
stream = self._call_groq_api(prompt) |
|
||||||
|
|
||||||
reply = "" |
|
||||||
for chunk in stream: |
|
||||||
fragment = chunk.choices[0].delta.content or "" |
|
||||||
reply += fragment |
|
||||||
yield reply |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
logger.error(f"GROQ API error: {str(e)}", exc_info=True) |
|
||||||
yield f"Error with GROQ API: {str(e)}" |
|
||||||
|
|
||||||
@retry_with_exponential_backoff( |
|
||||||
max_retries=5, |
|
||||||
initial_delay=1.0, |
|
||||||
retryable_exceptions=(Exception,) |
|
||||||
) |
|
||||||
def _call_gemini_api(self, prompt: str): |
|
||||||
"""Call the Gemini API with retry logic""" |
|
||||||
return self.gemini.generate_content( |
|
||||||
prompt, |
|
||||||
generation_config={ |
|
||||||
"temperature": 0.7, |
|
||||||
"top_p": 1, |
|
||||||
"top_k": 1, |
|
||||||
"max_output_tokens": 4000, |
|
||||||
}, |
|
||||||
stream=True |
|
||||||
) |
|
||||||
|
|
||||||
def stream_gemini(self, prompt: str) -> Generator[str, None, None]: |
|
||||||
"""Stream responses from Gemini model.""" |
|
||||||
try: |
|
||||||
response = self._call_gemini_api(prompt) |
|
||||||
|
|
||||||
reply = "" |
|
||||||
for chunk in response: |
|
||||||
if chunk.text: |
|
||||||
reply += chunk.text |
|
||||||
yield reply |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
logger.error(f"Gemini API error: {str(e)}", exc_info=True) |
|
||||||
yield f"Error with Gemini API: {str(e)}" |
|
@ -1,48 +0,0 @@ |
|||||||
ai_converter_v2/ |
|
||||||
├── README.md # Project documentation |
|
||||||
├── requirements.txt # Python dependencies |
|
||||||
├── setup.py # Package installation configuration |
|
||||||
├── run.py # Application entry point |
|
||||||
├── Makefile # Build and development commands |
|
||||||
├── .env.example # Example environment variables |
|
||||||
├── .gitignore # Git ignore patterns |
|
||||||
└── src/ |
|
||||||
└── ai_code_converter/ |
|
||||||
├── __init__.py |
|
||||||
├── main.py # Main application initialization |
|
||||||
├── app.py # Gradio interface and core app logic |
|
||||||
├── config.py # Configuration settings |
|
||||||
├── template.j2 # Code conversion prompt template |
|
||||||
├── core/ # Core functionality modules |
|
||||||
│ ├── __init__.py |
|
||||||
│ ├── code_execution.py # Code execution logic |
|
||||||
│ ├── language_detection.py # Language detection |
|
||||||
│ └── file_utils.py # File operations |
|
||||||
├── models/ # AI model interfaces |
|
||||||
│ ├── __init__.py |
|
||||||
│ └── ai_streaming.py # Streaming implementations |
|
||||||
└── utils/ # Utility functions |
|
||||||
├── __init__.py |
|
||||||
└── logger.py # Logging configuration |
|
||||||
|
|
||||||
Key Components: |
|
||||||
- core/: Core functionality modules |
|
||||||
- code_execution.py: Handles code execution in different languages |
|
||||||
- language_detection.py: Detects and validates programming languages |
|
||||||
- file_utils.py: Handles file operations and downloads |
|
||||||
|
|
||||||
- models/: AI model implementations |
|
||||||
- ai_streaming.py: Streaming implementations for different AI models |
|
||||||
|
|
||||||
- utils/: Utility modules |
|
||||||
- logger.py: Logging configuration and setup |
|
||||||
|
|
||||||
- Configuration: |
|
||||||
- config.py: Central configuration settings |
|
||||||
- template.j2: Prompt template for code conversion |
|
||||||
- .env: Environment variables (API keys) |
|
||||||
|
|
||||||
- Entry Points: |
|
||||||
- run.py: Main entry point |
|
||||||
- main.py: Application initialization |
|
||||||
- app.py: Gradio interface implementation |
|
@ -1,287 +0,0 @@ |
|||||||
--- |
|
||||||
description: A template for converting code between different programming languages |
|
||||||
author: AI Conversion Assistant |
|
||||||
--- |
|
||||||
|
|
||||||
You're an AI assistant specialized in code conversion with expertise in: |
|
||||||
- Language-specific idioms, patterns and best practices |
|
||||||
- Performance optimization techniques for each target language |
|
||||||
- Memory management paradigms across different languages |
|
||||||
- Cross-platform compatibility considerations |
|
||||||
- Equivalent library and framework implementations |
|
||||||
- Data structure transformations between languages |
|
||||||
- Type system differences and appropriate conversions |
|
||||||
- Error handling strategies for each language ecosystem |
|
||||||
- Concurrency and parallelism models |
|
||||||
- Standard toolchains and build systems |
|
||||||
|
|
||||||
# CONTEXT |
|
||||||
You will be provided with code written in **{{ source_language }}**. |
|
||||||
Your task is to convert it to **{{ target_language }}**, ensuring that the output produces the same functionality and is optimized for performance. |
|
||||||
|
|
||||||
# INSTRUCTIONS |
|
||||||
- Respond only with **{{ target_language }}** code. |
|
||||||
{% if doc_enabled %}{% else %}- Provide minimal comments, focusing only on critical parts of the code.{% endif %} |
|
||||||
- Use base libraries and packages where possible. |
|
||||||
- Ensure that data types and syntax are correctly adapted between languages. |
|
||||||
- Avoid explanations outside of comments in the code. |
|
||||||
- Maintain identical behavior for functions like random number generation to ensure consistent output. |
|
||||||
|
|
||||||
{% if doc_enabled %} |
|
||||||
# DOCUMENTATION INSTRUCTIONS |
|
||||||
- Include comprehensive documentation in your response following the style specified below. |
|
||||||
- Document the purpose and functionality of classes, functions, and important code blocks. |
|
||||||
- Explain important parameters, return values, and exceptions. |
|
||||||
- Make documentation clear and helpful for new developers to understand the code. |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% if target_language == 'Python' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR PYTHON |
|
||||||
- Use Black's default settings |
|
||||||
- Normalize code structure |
|
||||||
- Produce clean, consistent code formatting |
|
||||||
- Use Pythonic idioms and list comprehensions where appropriate. |
|
||||||
- Ensure proper exception handling and type safety. |
|
||||||
- Follow PEP 8 styling conventions. |
|
||||||
- Correct Python indentation (4 spaces) |
|
||||||
- Proper syntax for Python |
|
||||||
- No syntax errors |
|
||||||
- Complete, runnable code |
|
||||||
{% if doc_style == 'google' %} |
|
||||||
- Use Google-style docstrings (summary line, blank line, Args:, Returns:, Raises:) |
|
||||||
{% elif doc_style == 'numpy' %} |
|
||||||
- Use NumPy-style docstrings (summary line, Parameters, Returns, Raises sections) |
|
||||||
{% else %} |
|
||||||
- Follow PEP 257 for docstrings (summary line, blank line, detailed description) |
|
||||||
{% endif %} |
|
||||||
- Ensure all output is done through print() statements |
|
||||||
- For functions that return values, print the return value |
|
||||||
- Use proper Python indentation |
|
||||||
- Include necessary imports at the top |
|
||||||
- Handle exceptions appropriately |
|
||||||
|
|
||||||
{% elif target_language == 'Julia' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR JULIA |
|
||||||
- Use Julia's multiple dispatch where beneficial. |
|
||||||
- Ensure correct handling of data types and performance optimizations. |
|
||||||
- Use built-in functions and packages like `Base` and `LinearAlgebra` if applicable. |
|
||||||
{% if doc_style == 'standard' %} |
|
||||||
- Use standard Julia docstrings with triple quotes """Summary\n\nDetailed description""" |
|
||||||
{% elif doc_style == 'docsystem' %} |
|
||||||
- Use Documenter.jl style docstrings with """Function description\n\n# Arguments\n- `arg1`: description\n# Returns\n- description""" |
|
||||||
{% else %} |
|
||||||
- Include simple docstrings with description of functionality |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% elif target_language == 'JavaScript' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR JAVASCRIPT |
|
||||||
- Use ES6+ features where applicable. |
|
||||||
- Ensure asynchronous functions use `async/await` correctly. |
|
||||||
- Follow best practices for variable scoping (`const`, `let`, `var`). |
|
||||||
{% if doc_style == 'jsdoc' %} |
|
||||||
- Use JSDoc comments with @param, @returns, and other appropriate tags |
|
||||||
{% elif doc_style == 'tsdoc' %} |
|
||||||
- Use TSDoc style comments compatible with TypeScript |
|
||||||
{% else %} |
|
||||||
- Use simple block comments with function descriptions |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% elif target_language == 'Go' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR GO |
|
||||||
- Use Go idioms such as goroutines for concurrency when needed. |
|
||||||
- Ensure proper handling of errors using Go's `error` type. |
|
||||||
- Optimize for performance using Go's built-in profiling tools. |
|
||||||
{% if doc_style == 'godoc' %} |
|
||||||
- Follow standard GoDoc comment style (starting with function name) |
|
||||||
{% else %} |
|
||||||
- Use clear comments for package-level and exported declarations |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% elif target_language == 'Java' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR JAVA |
|
||||||
- Use appropriate class and method structures. |
|
||||||
- Ensure proper handling of exceptions using `try-catch-finally`. |
|
||||||
- Optimize performance using multithreading where applicable. |
|
||||||
{% if doc_style == 'javadoc' %} |
|
||||||
- Use JavaDoc with @param, @return, @throws and other appropriate tags |
|
||||||
{% else %} |
|
||||||
- Use simple block comments with method descriptions |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% elif target_language == 'C++' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR C++ |
|
||||||
- Use `#include` directives for necessary libraries. |
|
||||||
- Pay attention to integer overflow issues. |
|
||||||
- Optimize for execution speed where possible using memory management techniques. |
|
||||||
{% if doc_style == 'doxygen' %} |
|
||||||
- Use Doxygen-style comments with @brief, @param, @return tags |
|
||||||
{% else %} |
|
||||||
- Use block comments with function descriptions |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% elif target_language == 'Ruby' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR RUBY |
|
||||||
- Use Ruby idioms like blocks, procs, and lambdas where appropriate. |
|
||||||
- Follow Ruby style guidelines (2 space indentation, snake_case for methods). |
|
||||||
- Use Ruby's built-in enumerable methods for collection operations. |
|
||||||
{% if doc_style == 'yard' %} |
|
||||||
- Use YARD documentation style with @param, @return, and other appropriate tags |
|
||||||
{% elif doc_style == 'rdoc' %} |
|
||||||
- Use RDoc documentation style with simple comment blocks |
|
||||||
{% else %} |
|
||||||
- Use simple comment blocks to document methods and classes |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% elif target_language == 'Swift' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR SWIFT |
|
||||||
- Use Swift's strong typing system and optional handling. |
|
||||||
- Implement proper error handling with do-catch blocks. |
|
||||||
- Follow Swift naming conventions (camelCase for variables, methods). |
|
||||||
{% if doc_style == 'markdown' %} |
|
||||||
- Use Swift's markdown documentation style with parameters and returns sections |
|
||||||
{% elif doc_style == 'headerDoc' %} |
|
||||||
- Use HeaderDoc style documentation |
|
||||||
{% else %} |
|
||||||
- Use triple-slash /// comments for documentation |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% elif target_language == 'Rust' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR RUST |
|
||||||
- Ensure memory safety with proper ownership, borrowing, and lifetimes. |
|
||||||
- Use pattern matching where appropriate. |
|
||||||
- Handle errors with Result and Option types. |
|
||||||
{% if doc_style == 'rustdoc' %} |
|
||||||
- Use standard Rust documentation with triple-slash /// comments |
|
||||||
{% else %} |
|
||||||
- Include documentation comments that explain functionality |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% elif target_language == 'C#' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR C# |
|
||||||
- Use appropriate .NET libraries and LINQ where beneficial. |
|
||||||
- Implement proper exception handling. |
|
||||||
- Use C# properties instead of getter/setter methods where appropriate. |
|
||||||
{% if doc_style == 'xml' %} |
|
||||||
- Use XML documentation comments with <summary>, <param>, <returns> tags |
|
||||||
{% else %} |
|
||||||
- Use simple comments to document classes and methods |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% elif target_language == 'TypeScript' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR TYPESCRIPT |
|
||||||
- Utilize TypeScript's static typing system. |
|
||||||
- Define appropriate interfaces and types. |
|
||||||
- Use ES6+ features and TypeScript-specific patterns. |
|
||||||
{% if doc_style == 'tsdoc' %} |
|
||||||
- Use TSDoc with @param, @returns, and other appropriate tags |
|
||||||
{% else %} |
|
||||||
- Include simple comments explaining functionality |
|
||||||
{% endif %} |
|
||||||
|
|
||||||
{% elif target_language == 'R' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR R |
|
||||||
- Use R's vectorized operations where possible for performance. |
|
||||||
- Leverage tidyverse packages when appropriate for data manipulation. |
|
||||||
- Follow R style guidelines (snake_case for variables, descriptive names). |
|
||||||
{% if doc_style == 'roxygen2' %} |
|
||||||
- Use roxygen2 style comments with @param, @return, @examples tags |
|
||||||
{% elif doc_style == 'r-native' %} |
|
||||||
- Use R's native documentation system with simple comments |
|
||||||
{% else %} |
|
||||||
- Include comments explaining functionality at the beginning of functions |
|
||||||
{% endif %} |
|
||||||
- Ensure compatibility with R's functional programming paradigm |
|
||||||
- Implement proper error handling with tryCatch() when necessary |
|
||||||
- Make appropriate use of R's specialized data structures like data.frames and lists |
|
||||||
|
|
||||||
{% elif target_language == 'Perl' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR PERL |
|
||||||
- Use Perl's powerful regular expression capabilities when appropriate. |
|
||||||
- Follow Perl's style guidelines including use of sigils and variable naming. |
|
||||||
- Leverage Perl's CPAN modules when beneficial. |
|
||||||
{% if doc_style == 'pod' %} |
|
||||||
- Use Plain Old Documentation (POD) style with =head1, =head2, =item tags |
|
||||||
{% else %} |
|
||||||
- Use block comments to document subroutines and functionality |
|
||||||
{% endif %} |
|
||||||
- Ensure proper handling of scalar vs. list context |
|
||||||
- Use Perl's error handling mechanisms with eval and die/warn |
|
||||||
- Implement appropriate memory management techniques |
|
||||||
|
|
||||||
{% elif target_language == 'Lua' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR LUA |
|
||||||
- Use Lua's lightweight table structure effectively. |
|
||||||
- Follow Lua coding style (no semicolons, use of 'local' variables). |
|
||||||
- Respect Lua's 1-based indexing for arrays and string manipulation. |
|
||||||
{% if doc_style == 'ldoc' %} |
|
||||||
- Use LDoc style comments with @param, @return, and other appropriate tags |
|
||||||
{% else %} |
|
||||||
- Use block comments to document functions and modules |
|
||||||
{% endif %} |
|
||||||
- Leverage Lua's coroutines for concurrent programming when appropriate |
|
||||||
- Implement proper error handling with pcall and xpcall |
|
||||||
- Optimize for Lua's garbage collection |
|
||||||
|
|
||||||
{% elif target_language == 'PHP' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR PHP |
|
||||||
- Follow PHP-FIG standards (PSR-1, PSR-12) for code style. |
|
||||||
- Use modern PHP features (namespaces, type declarations). |
|
||||||
- Implement appropriate error handling with try/catch blocks. |
|
||||||
{% if doc_style == 'phpdoc' %} |
|
||||||
- Use PHPDoc style comments with @param, @return, @throws tags |
|
||||||
{% else %} |
|
||||||
- Use block comments to document classes and methods |
|
||||||
{% endif %} |
|
||||||
- Include necessary composer dependencies |
|
||||||
- Consider performance implications of string operations and array handling |
|
||||||
- Apply appropriate security measures (input validation, output escaping) |
|
||||||
|
|
||||||
{% elif target_language == 'Kotlin' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR KOTLIN |
|
||||||
- Use Kotlin's null safety features and smart casts. |
|
||||||
- Apply functional programming concepts with lambda expressions. |
|
||||||
- Leverage Kotlin's extension functions and properties where appropriate. |
|
||||||
{% if doc_style == 'kdoc' %} |
|
||||||
- Use KDoc style comments with @param, @return, @throws tags |
|
||||||
{% else %} |
|
||||||
- Use block comments to document classes and functions |
|
||||||
{% endif %} |
|
||||||
- Take advantage of Kotlin's coroutines for asynchronous programming |
|
||||||
- Follow Kotlin conventions for naming and structure |
|
||||||
- Implement proper exception handling with try-catch blocks |
|
||||||
|
|
||||||
{% elif target_language == 'SQL' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR SQL |
|
||||||
- Optimize queries for performance with proper indexing hints. |
|
||||||
- Use appropriate SQL dialect features based on the specified database system. |
|
||||||
- Follow SQL style guidelines (uppercase keywords, proper indentation). |
|
||||||
{% if doc_style == 'standard' %} |
|
||||||
- Use standard SQL comment style with detailed descriptions |
|
||||||
{% elif doc_style == 'database-specific' %} |
|
||||||
- Use database-specific comment annotations (e.g., Oracle hints, MySQL comments) |
|
||||||
{% else %} |
|
||||||
- Include simple comments explaining query functionality |
|
||||||
{% endif %} |
|
||||||
- Ensure security by avoiding SQL injection vulnerabilities |
|
||||||
- Consider execution plan optimization in complex queries |
|
||||||
- Apply appropriate transaction handling when necessary |
|
||||||
|
|
||||||
{% endif %} |
|
||||||
|
|
||||||
# INPUT CODE: |
|
||||||
{{ input_code }} |
|
||||||
|
|
||||||
# EXPECTED OUTPUT: |
|
||||||
A fully functional **{{ target_language }}** implementation of the provided code. |
|
||||||
|
|
||||||
Convert this {{ source_language }} code to {{ target_language }}. |
|
||||||
Follow these rules: |
|
||||||
1. Maintain the same functionality |
|
||||||
2. Keep variable names similar when possible |
|
||||||
3. Use idiomatic {{ target_language }} patterns |
|
||||||
4. Include necessary imports |
|
||||||
5. Provide only the converted code without explanations |
|
||||||
|
|
||||||
Here's the code to convert: |
|
||||||
|
|
||||||
{{ input_code }} |
|
@ -1,78 +0,0 @@ |
|||||||
--- |
|
||||||
description: A template for converting code between different programming languages |
|
||||||
author: AI Conversion Assistant |
|
||||||
--- |
|
||||||
|
|
||||||
You're an AI assistant specialized in code conversion. |
|
||||||
|
|
||||||
# CONTEXT |
|
||||||
You will be provided with code written in **{{ source_language }}**. |
|
||||||
Your task is to convert it to **{{ target_language }}**, ensuring that the output produces the same functionality and is optimized for performance. |
|
||||||
|
|
||||||
# INSTRUCTIONS |
|
||||||
- Respond only with **{{ target_language }}** code. |
|
||||||
- Provide minimal but useful comments where necessary. |
|
||||||
- Ensure that data types and syntax are correctly adapted between languages. |
|
||||||
- Avoid explanations outside of comments in the code. |
|
||||||
- Maintain identical behavior for functions like random number generation to ensure consistent output. |
|
||||||
|
|
||||||
{% if target_language == 'Python' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR PYTHON |
|
||||||
- Use Pythonic idioms and list comprehensions where appropriate. |
|
||||||
- Ensure proper exception handling and type safety. |
|
||||||
- Follow PEP 8 styling conventions. |
|
||||||
- Ensure all output is done through print() statements |
|
||||||
- For functions that return values, print the return value |
|
||||||
- Use proper Python indentation |
|
||||||
- Include necessary imports at the top |
|
||||||
- Handle exceptions appropriately |
|
||||||
|
|
||||||
{% elif target_language == 'Julia' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR JULIA |
|
||||||
- Use Julia's multiple dispatch where beneficial. |
|
||||||
- Ensure correct handling of data types and performance optimizations. |
|
||||||
- Use built-in functions and packages like `Base` and `LinearAlgebra` if applicable. |
|
||||||
|
|
||||||
{% elif target_language == 'JavaScript' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR JAVASCRIPT |
|
||||||
- Use ES6+ features where applicable. |
|
||||||
- Ensure asynchronous functions use `async/await` correctly. |
|
||||||
- Follow best practices for variable scoping (`const`, `let`, `var`). |
|
||||||
|
|
||||||
{% elif target_language == 'Go' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR GO |
|
||||||
- Use Go idioms such as goroutines for concurrency when needed. |
|
||||||
- Ensure proper handling of errors using Go's `error` type. |
|
||||||
- Optimize for performance using Go's built-in profiling tools. |
|
||||||
|
|
||||||
{% elif target_language == 'Java' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR JAVA |
|
||||||
- Use appropriate class and method structures. |
|
||||||
- Ensure proper handling of exceptions using `try-catch-finally`. |
|
||||||
- Optimize performance using multithreading where applicable. |
|
||||||
|
|
||||||
{% elif target_language == 'C++' %} |
|
||||||
# ADDITIONAL INSTRUCTIONS FOR C++ |
|
||||||
- Use `#include` directives for necessary libraries. |
|
||||||
- Pay attention to integer overflow issues. |
|
||||||
- Optimize for execution speed where possible using memory management techniques. |
|
||||||
|
|
||||||
{% endif %} |
|
||||||
|
|
||||||
# INPUT CODE: |
|
||||||
{{ input_code }} |
|
||||||
|
|
||||||
# EXPECTED OUTPUT: |
|
||||||
A fully functional **{{ target_language }}** implementation of the provided code. |
|
||||||
|
|
||||||
Convert this {{ source_language }} code to {{ target_language }}. |
|
||||||
Follow these rules: |
|
||||||
1. Maintain the same functionality |
|
||||||
2. Keep variable names similar when possible |
|
||||||
3. Use idiomatic {{ target_language }} patterns |
|
||||||
4. Include necessary imports |
|
||||||
5. Provide only the converted code without explanations |
|
||||||
|
|
||||||
Here's the code to convert: |
|
||||||
|
|
||||||
{{ input_code }} |
|
@ -1 +0,0 @@ |
|||||||
"""Utility modules.""" |
|
@ -1,132 +0,0 @@ |
|||||||
"""Logging configuration for the CodeXchange AI.""" |
|
||||||
|
|
||||||
import json |
|
||||||
import logging |
|
||||||
import logging.handlers |
|
||||||
import os |
|
||||||
import sys |
|
||||||
import threading |
|
||||||
import time |
|
||||||
from datetime import datetime |
|
||||||
from functools import wraps |
|
||||||
from pathlib import Path |
|
||||||
from typing import Any, Callable |
|
||||||
|
|
||||||
class JSONFormatter(logging.Formatter): |
|
||||||
"""Custom JSON formatter for structured logging.""" |
|
||||||
|
|
||||||
def format(self, record: logging.LogRecord) -> str: |
|
||||||
"""Format log record as JSON.""" |
|
||||||
log_data = { |
|
||||||
"timestamp": self.formatTime(record), |
|
||||||
"level": record.levelname, |
|
||||||
"process_id": record.process, |
|
||||||
"thread_id": record.thread, |
|
||||||
"thread_name": record.threadName, |
|
||||||
"module": record.module, |
|
||||||
"function": record.funcName, |
|
||||||
"line": record.lineno, |
|
||||||
"message": record.getMessage() |
|
||||||
} |
|
||||||
|
|
||||||
if hasattr(record, 'duration'): |
|
||||||
log_data['duration'] = f"{record.duration:.4f}s" |
|
||||||
|
|
||||||
if record.exc_info: |
|
||||||
log_data['exception'] = self.formatException(record.exc_info) |
|
||||||
|
|
||||||
return json.dumps(log_data) |
|
||||||
|
|
||||||
def log_execution_time(logger: logging.Logger) -> Callable: |
|
||||||
"""Decorator to log function execution time.""" |
|
||||||
def decorator(func: Callable) -> Callable: |
|
||||||
@wraps(func) |
|
||||||
def wrapper(*args, **kwargs): |
|
||||||
start_time = time.time() |
|
||||||
|
|
||||||
# Log function entry |
|
||||||
logger.debug( |
|
||||||
"Function Entry | %s | Args: %s | Kwargs: %s", |
|
||||||
func.__name__, |
|
||||||
[str(arg) for arg in args], |
|
||||||
{k: str(v) for k, v in kwargs.items() if not any(sensitive in k.lower() for sensitive in ('password', 'key', 'token', 'secret'))} |
|
||||||
) |
|
||||||
|
|
||||||
try: |
|
||||||
result = func(*args, **kwargs) |
|
||||||
duration = time.time() - start_time |
|
||||||
|
|
||||||
# Log function exit |
|
||||||
logger.debug( |
|
||||||
"Function Exit | %s | Duration: %.4fs", |
|
||||||
func.__name__, |
|
||||||
duration |
|
||||||
) |
|
||||||
return result |
|
||||||
|
|
||||||
except Exception as e: |
|
||||||
duration = time.time() - start_time |
|
||||||
logger.error( |
|
||||||
"Function Error | %s | Duration: %.4fs | Error: %s", |
|
||||||
func.__name__, |
|
||||||
duration, |
|
||||||
str(e), |
|
||||||
exc_info=True |
|
||||||
) |
|
||||||
raise |
|
||||||
|
|
||||||
return wrapper |
|
||||||
return decorator |
|
||||||
|
|
||||||
def setup_logger(name: str) -> logging.Logger: |
|
||||||
"""Set up a logger with both file and console output.""" |
|
||||||
# Create logger |
|
||||||
logger = logging.getLogger(name) |
|
||||||
logger.setLevel(logging.DEBUG) |
|
||||||
|
|
||||||
# Clear any existing handlers |
|
||||||
logger.handlers = [] |
|
||||||
|
|
||||||
# Create logs directory |
|
||||||
log_dir = Path("logs") |
|
||||||
log_dir.mkdir(exist_ok=True) |
|
||||||
|
|
||||||
# Create formatters |
|
||||||
console_formatter = logging.Formatter( |
|
||||||
'[%(asctime)s] %(levelname)-8s [%(name)s:%(funcName)s:%(lineno)d] [PID:%(process)d-%(threadName)s] - %(message)s', |
|
||||||
datefmt='%Y-%m-%d %H:%M:%S' |
|
||||||
) |
|
||||||
|
|
||||||
json_formatter = JSONFormatter() |
|
||||||
|
|
||||||
# Console handler with color coding |
|
||||||
console_handler = logging.StreamHandler(sys.stdout) |
|
||||||
console_handler.setLevel(logging.INFO) |
|
||||||
console_handler.setFormatter(console_formatter) |
|
||||||
|
|
||||||
# File handler with daily rotation and JSON formatting |
|
||||||
log_file = log_dir / f"ai_converter_{datetime.now().strftime('%Y-%m-%d')}.json" |
|
||||||
file_handler = logging.handlers.RotatingFileHandler( |
|
||||||
log_file, |
|
||||||
maxBytes=10*1024*1024, # 10MB |
|
||||||
backupCount=30, # Keep 30 backup files |
|
||||||
encoding='utf-8' |
|
||||||
) |
|
||||||
file_handler.setLevel(logging.DEBUG) |
|
||||||
file_handler.setFormatter(json_formatter) |
|
||||||
|
|
||||||
# Add handlers |
|
||||||
logger.addHandler(console_handler) |
|
||||||
logger.addHandler(file_handler) |
|
||||||
|
|
||||||
# Log initialization |
|
||||||
logger.info("="*50) |
|
||||||
logger.info("Logger Initialized") |
|
||||||
logger.info(f"Logger Name: {name}") |
|
||||||
logger.info(f"Log File: {log_file}") |
|
||||||
logger.info(f"Process ID: {os.getpid()}") |
|
||||||
logger.info(f"Thread ID: {threading.get_ident()}") |
|
||||||
logger.info(f"Thread Name: {threading.current_thread().name}") |
|
||||||
logger.info("="*50) |
|
||||||
|
|
||||||
return logger |
|
@ -1,29 +0,0 @@ |
|||||||
"""Basic tests for CodeXchange AI application.""" |
|
||||||
|
|
||||||
import pytest |
|
||||||
import os |
|
||||||
import sys |
|
||||||
|
|
||||||
# Add project root to path |
|
||||||
sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) |
|
||||||
|
|
||||||
from src.ai_code_converter.config import SUPPORTED_LANGUAGES, DOCUMENT_STYLES |
|
||||||
|
|
||||||
|
|
||||||
def test_supported_languages(): |
|
||||||
"""Test that supported languages configuration is valid.""" |
|
||||||
assert isinstance(SUPPORTED_LANGUAGES, list) |
|
||||||
assert len(SUPPORTED_LANGUAGES) > 0 |
|
||||||
assert "Python" in SUPPORTED_LANGUAGES |
|
||||||
|
|
||||||
|
|
||||||
def test_document_styles(): |
|
||||||
"""Test that document styles configuration is valid.""" |
|
||||||
assert isinstance(DOCUMENT_STYLES, dict) |
|
||||||
assert len(DOCUMENT_STYLES) > 0 |
|
||||||
|
|
||||||
# Check that each language has at least one document style |
|
||||||
for language in SUPPORTED_LANGUAGES: |
|
||||||
assert language in DOCUMENT_STYLES, f"{language} missing from document styles" |
|
||||||
assert isinstance(DOCUMENT_STYLES[language], list) |
|
||||||
assert len(DOCUMENT_STYLES[language]) > 0 |
|
@ -1,101 +0,0 @@ |
|||||||
"""Test module for C# language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_csharp_detection(): |
|
||||||
"""Test the C# language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample C# code |
|
||||||
csharp_code = """ |
|
||||||
using System; |
|
||||||
using System.Collections.Generic; |
|
||||||
using System.Linq; |
|
||||||
using System.Threading.Tasks; |
|
||||||
|
|
||||||
namespace MyApp |
|
||||||
{ |
|
||||||
// A simple C# class |
|
||||||
public class Person |
|
||||||
{ |
|
||||||
// Properties |
|
||||||
public string Name { get; set; } |
|
||||||
public int Age { get; private set; } |
|
||||||
|
|
||||||
// Constructor |
|
||||||
public Person(string name, int age) |
|
||||||
{ |
|
||||||
Name = name; |
|
||||||
Age = age; |
|
||||||
} |
|
||||||
|
|
||||||
// Method |
|
||||||
public string Greet() |
|
||||||
{ |
|
||||||
return $"Hello, my name is {Name} and I am {Age} years old."; |
|
||||||
} |
|
||||||
|
|
||||||
// Method with out parameter |
|
||||||
public bool TryParse(string input, out int result) |
|
||||||
{ |
|
||||||
return int.TryParse(input, out result); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Interface |
|
||||||
public interface IRepository<T> where T : class |
|
||||||
{ |
|
||||||
Task<T> GetByIdAsync(int id); |
|
||||||
Task<IEnumerable<T>> GetAllAsync(); |
|
||||||
Task AddAsync(T entity); |
|
||||||
} |
|
||||||
|
|
||||||
// Async method |
|
||||||
public class DataProcessor |
|
||||||
{ |
|
||||||
public async Task ProcessDataAsync() |
|
||||||
{ |
|
||||||
await Task.Delay(1000); |
|
||||||
Console.WriteLine("Data processed!"); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
class Program |
|
||||||
{ |
|
||||||
static void Main(string[] args) |
|
||||||
{ |
|
||||||
// Variable declaration with var |
|
||||||
var person = new Person("John", 30); |
|
||||||
Console.WriteLine(person.Greet()); |
|
||||||
|
|
||||||
// LINQ query |
|
||||||
var numbers = new List<int> { 1, 2, 3, 4, 5 }; |
|
||||||
var evenNumbers = numbers.Where(n => n % 2 == 0).ToList(); |
|
||||||
|
|
||||||
// String interpolation |
|
||||||
string message = $"Found {evenNumbers.Count} even numbers."; |
|
||||||
Console.WriteLine(message); |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_csharp(csharp_code) == True |
|
||||||
assert detector.detect_language(csharp_code) == "C#" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(csharp_code, "C#") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_csharp_detection() |
|
||||||
print("All C# detection tests passed!") |
|
@ -1,189 +0,0 @@ |
|||||||
"""Test module for Kotlin language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_kotlin_detection(): |
|
||||||
"""Test the Kotlin language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample Kotlin code |
|
||||||
kotlin_code = """ |
|
||||||
package com.example.myapp |
|
||||||
|
|
||||||
import android.os.Bundle |
|
||||||
import android.widget.Button |
|
||||||
import android.widget.TextView |
|
||||||
import androidx.appcompat.app.AppCompatActivity |
|
||||||
import kotlinx.coroutines.* |
|
||||||
import kotlinx.coroutines.flow.* |
|
||||||
import java.util.* |
|
||||||
|
|
||||||
/** |
|
||||||
* Main Activity for the application |
|
||||||
*/ |
|
||||||
class MainActivity : AppCompatActivity() { |
|
||||||
|
|
||||||
// Properties |
|
||||||
private lateinit var textView: TextView |
|
||||||
private lateinit var button: Button |
|
||||||
private val viewModel: MainViewModel by viewModels() |
|
||||||
private val job = Job() |
|
||||||
private val coroutineScope = CoroutineScope(Dispatchers.Main + job) |
|
||||||
|
|
||||||
// Immutable property |
|
||||||
val API_KEY: String = "abc123" |
|
||||||
|
|
||||||
// Computed property |
|
||||||
val isActive: Boolean |
|
||||||
get() = viewModel.isActive && !isFinishing |
|
||||||
|
|
||||||
// Data class |
|
||||||
data class User( |
|
||||||
val id: Int, |
|
||||||
val name: String, |
|
||||||
val email: String, |
|
||||||
var isActive: Boolean = true |
|
||||||
) |
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) { |
|
||||||
super.onCreate(savedInstanceState) |
|
||||||
setContentView(R.layout.activity_main) |
|
||||||
|
|
||||||
// View binding |
|
||||||
textView = findViewById(R.id.textView) |
|
||||||
button = findViewById(R.id.button) |
|
||||||
|
|
||||||
// Click listener |
|
||||||
button.setOnClickListener { |
|
||||||
fetchData() |
|
||||||
} |
|
||||||
|
|
||||||
// Observe live data |
|
||||||
viewModel.userData.observe(this) { user -> |
|
||||||
updateUI(user) |
|
||||||
} |
|
||||||
|
|
||||||
// Extension function call |
|
||||||
"Hello, Kotlin!".printDebug() |
|
||||||
|
|
||||||
// Using when expression |
|
||||||
val result = when(viewModel.status) { |
|
||||||
Status.LOADING -> "Loading..." |
|
||||||
Status.SUCCESS -> "Success!" |
|
||||||
Status.ERROR -> "Error!" |
|
||||||
else -> "Unknown" |
|
||||||
} |
|
||||||
|
|
||||||
textView.text = result |
|
||||||
} |
|
||||||
|
|
||||||
// Suspend function |
|
||||||
private suspend fun fetchUserData(): User { |
|
||||||
return withContext(Dispatchers.IO) { |
|
||||||
// Simulate network delay |
|
||||||
delay(1000) |
|
||||||
User(1, "John Doe", "john@example.com") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Coroutine usage |
|
||||||
private fun fetchData() { |
|
||||||
coroutineScope.launch { |
|
||||||
try { |
|
||||||
textView.text = "Loading..." |
|
||||||
val user = fetchUserData() |
|
||||||
updateUI(user) |
|
||||||
} catch (e: Exception) { |
|
||||||
textView.text = "Error: ${e.message}" |
|
||||||
} |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Normal function |
|
||||||
private fun updateUI(user: User) { |
|
||||||
textView.text = "Welcome, ${user.name}!" |
|
||||||
|
|
||||||
// Smart cast |
|
||||||
val info: Any = user.email |
|
||||||
if (info is String) { |
|
||||||
// No need to cast, Kotlin knows it's a String |
|
||||||
textView.text = info.toUpperCase() |
|
||||||
} |
|
||||||
|
|
||||||
// Collection operations |
|
||||||
val numbers = listOf(1, 2, 3, 4, 5) |
|
||||||
val sum = numbers.filter { it % 2 == 0 }.sum() |
|
||||||
|
|
||||||
// String template |
|
||||||
val message = "Sum of even numbers: $sum" |
|
||||||
println(message) |
|
||||||
} |
|
||||||
|
|
||||||
// Higher-order function |
|
||||||
private inline fun performOperation( |
|
||||||
value: Int, |
|
||||||
operation: (Int) -> Int |
|
||||||
): Int { |
|
||||||
return operation(value) |
|
||||||
} |
|
||||||
|
|
||||||
// Companion object |
|
||||||
companion object { |
|
||||||
const val TAG = "MainActivity" |
|
||||||
|
|
||||||
fun newInstance(): MainActivity { |
|
||||||
return MainActivity() |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Enum class |
|
||||||
enum class Status { |
|
||||||
LOADING, |
|
||||||
SUCCESS, |
|
||||||
ERROR |
|
||||||
} |
|
||||||
|
|
||||||
// Interface definition |
|
||||||
interface OnDataLoadListener { |
|
||||||
fun onDataLoaded(data: Any) |
|
||||||
fun onError(message: String) |
|
||||||
} |
|
||||||
|
|
||||||
// Object declaration (singleton) |
|
||||||
object Logger { |
|
||||||
fun log(message: String) { |
|
||||||
println("[$TAG] $message") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Extension function |
|
||||||
fun String.printDebug() { |
|
||||||
println("Debug: $this") |
|
||||||
} |
|
||||||
|
|
||||||
override fun onDestroy() { |
|
||||||
super.onDestroy() |
|
||||||
job.cancel() // Cancel coroutines when activity is destroyed |
|
||||||
} |
|
||||||
} |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_kotlin(kotlin_code) == True |
|
||||||
assert detector.detect_language(kotlin_code) == "Kotlin" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(kotlin_code, "Kotlin") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_kotlin_detection() |
|
||||||
print("All Kotlin detection tests passed!") |
|
@ -1,164 +0,0 @@ |
|||||||
"""Test module for Lua language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_lua_detection(): |
|
||||||
"""Test the Lua language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample Lua code |
|
||||||
lua_code = """ |
|
||||||
-- Simple Lua script |
|
||||||
local function factorial(n) |
|
||||||
if n == 0 then |
|
||||||
return 1 |
|
||||||
else |
|
||||||
return n * factorial(n - 1) |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
-- Variables |
|
||||||
local name = "John" |
|
||||||
local age = 30 |
|
||||||
local is_active = true |
|
||||||
local value = nil |
|
||||||
|
|
||||||
-- Table creation |
|
||||||
local person = { |
|
||||||
name = "John", |
|
||||||
age = 30, |
|
||||||
email = "john@example.com", |
|
||||||
greet = function(self) |
|
||||||
return "Hello, " .. self.name |
|
||||||
end |
|
||||||
} |
|
||||||
|
|
||||||
-- Accessing table properties |
|
||||||
print(person.name) |
|
||||||
print(person["age"]) |
|
||||||
print(person:greet()) |
|
||||||
|
|
||||||
-- Metatables |
|
||||||
local mt = { |
|
||||||
__add = function(a, b) |
|
||||||
return { value = a.value + b.value } |
|
||||||
end |
|
||||||
} |
|
||||||
|
|
||||||
local obj1 = { value = 10 } |
|
||||||
local obj2 = { value = 20 } |
|
||||||
setmetatable(obj1, mt) |
|
||||||
local result = obj1 + obj2 |
|
||||||
print(result.value) -- 30 |
|
||||||
|
|
||||||
-- Control structures |
|
||||||
for i = 1, 10 do |
|
||||||
print(i) |
|
||||||
end |
|
||||||
|
|
||||||
local fruits = {"apple", "banana", "orange"} |
|
||||||
for i, fruit in ipairs(fruits) do |
|
||||||
print(i, fruit) |
|
||||||
end |
|
||||||
|
|
||||||
for key, value in pairs(person) do |
|
||||||
if type(value) ~= "function" then |
|
||||||
print(key, value) |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
local count = 1 |
|
||||||
while count <= 5 do |
|
||||||
print(count) |
|
||||||
count = count + 1 |
|
||||||
end |
|
||||||
|
|
||||||
-- Using modules |
|
||||||
local math = require("math") |
|
||||||
print(math.floor(3.14)) |
|
||||||
print(math.random()) |
|
||||||
|
|
||||||
-- String operations |
|
||||||
local message = "Hello, " .. name .. "!" |
|
||||||
print(message) |
|
||||||
print(string.upper(message)) |
|
||||||
print(string.sub(message, 1, 5)) |
|
||||||
print(string.find(message, "Hello")) |
|
||||||
|
|
||||||
-- Multiple return values |
|
||||||
local function get_person() |
|
||||||
return "John", 30, true |
|
||||||
end |
|
||||||
|
|
||||||
local name, age, active = get_person() |
|
||||||
print(name, age, active) |
|
||||||
|
|
||||||
-- Closures |
|
||||||
local function counter() |
|
||||||
local count = 0 |
|
||||||
return function() |
|
||||||
count = count + 1 |
|
||||||
return count |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
local c1 = counter() |
|
||||||
print(c1()) -- 1 |
|
||||||
print(c1()) -- 2 |
|
||||||
|
|
||||||
-- Error handling |
|
||||||
local status, err = pcall(function() |
|
||||||
error("Something went wrong") |
|
||||||
end) |
|
||||||
|
|
||||||
if not status then |
|
||||||
print("Error:", err) |
|
||||||
end |
|
||||||
|
|
||||||
-- Coroutines |
|
||||||
local co = coroutine.create(function() |
|
||||||
for i = 1, 3 do |
|
||||||
print("Coroutine", i) |
|
||||||
coroutine.yield() |
|
||||||
end |
|
||||||
end) |
|
||||||
|
|
||||||
coroutine.resume(co) -- Coroutine 1 |
|
||||||
coroutine.resume(co) -- Coroutine 2 |
|
||||||
coroutine.resume(co) -- Coroutine 3 |
|
||||||
|
|
||||||
-- Multi-line strings |
|
||||||
local multi_line = [[ |
|
||||||
This is a multi-line |
|
||||||
string in Lua. |
|
||||||
It can contain "quotes" without escaping. |
|
||||||
]] |
|
||||||
print(multi_line) |
|
||||||
|
|
||||||
-- Bit operations (Lua 5.3+) |
|
||||||
local a = 10 -- 1010 in binary |
|
||||||
local b = 6 -- 0110 in binary |
|
||||||
print(a & b) -- AND: 0010 = 2 |
|
||||||
print(a | b) -- OR: 1110 = 14 |
|
||||||
print(a ~ b) -- XOR: 1100 = 12 |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_lua(lua_code) == True |
|
||||||
assert detector.detect_language(lua_code) == "Lua" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(lua_code, "Lua") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_lua_detection() |
|
||||||
print("All Lua detection tests passed!") |
|
@ -1,174 +0,0 @@ |
|||||||
"""Test module for Perl language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_perl_detection(): |
|
||||||
"""Test the Perl language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample Perl code |
|
||||||
perl_code = """ |
|
||||||
#!/usr/bin/perl |
|
||||||
use strict; |
|
||||||
use warnings; |
|
||||||
use Data::Dumper; |
|
||||||
use File::Basename; |
|
||||||
use Getopt::Long; |
|
||||||
|
|
||||||
# Scalar variable |
|
||||||
my $name = "John Doe"; |
|
||||||
my $age = 30; |
|
||||||
my $pi = 3.14159; |
|
||||||
|
|
||||||
# Array variables |
|
||||||
my @fruits = ("apple", "banana", "orange"); |
|
||||||
my @numbers = (1..10); |
|
||||||
|
|
||||||
# Hash variables |
|
||||||
my %user = ( |
|
||||||
"name" => "John", |
|
||||||
"age" => 30, |
|
||||||
"email" => "john@example.com" |
|
||||||
); |
|
||||||
|
|
||||||
# Print statements |
|
||||||
print "Hello, $name!\\n"; |
|
||||||
print "Your age is $age\\n"; |
|
||||||
|
|
||||||
# Accessing array elements |
|
||||||
print "First fruit: $fruits[0]\\n"; |
|
||||||
print "Last fruit: $fruits[-1]\\n"; |
|
||||||
|
|
||||||
# Accessing hash elements |
|
||||||
print "User name: $user{name}\\n"; |
|
||||||
print "User email: $user{email}\\n"; |
|
||||||
|
|
||||||
# Subroutine definition |
|
||||||
sub greet { |
|
||||||
my ($person) = @_; |
|
||||||
print "Hello, $person!\\n"; |
|
||||||
return "Greeting sent"; |
|
||||||
} |
|
||||||
|
|
||||||
# Call the subroutine |
|
||||||
my $result = greet($name); |
|
||||||
print "Result: $result\\n"; |
|
||||||
|
|
||||||
# Control structures |
|
||||||
if ($age >= 18) { |
|
||||||
print "You are an adult.\\n"; |
|
||||||
} else { |
|
||||||
print "You are a minor.\\n"; |
|
||||||
} |
|
||||||
|
|
||||||
# Unless example |
|
||||||
unless ($age < 18) { |
|
||||||
print "Not a minor.\\n"; |
|
||||||
} |
|
||||||
|
|
||||||
# For loop |
|
||||||
for my $i (0..$#fruits) { |
|
||||||
print "Fruit $i: $fruits[$i]\\n"; |
|
||||||
} |
|
||||||
|
|
||||||
# Foreach loop |
|
||||||
foreach my $fruit (@fruits) { |
|
||||||
print "I like $fruit\\n"; |
|
||||||
} |
|
||||||
|
|
||||||
# While loop |
|
||||||
my $counter = 0; |
|
||||||
while ($counter < 5) { |
|
||||||
print "Counter: $counter\\n"; |
|
||||||
$counter++; |
|
||||||
} |
|
||||||
|
|
||||||
# Regular expressions |
|
||||||
my $text = "The quick brown fox"; |
|
||||||
if ($text =~ m/quick/) { |
|
||||||
print "Match found!\\n"; |
|
||||||
} |
|
||||||
|
|
||||||
# Substitution |
|
||||||
my $modified = $text; |
|
||||||
$modified =~ s/quick/slow/; |
|
||||||
print "Modified text: $modified\\n"; |
|
||||||
|
|
||||||
# Special variables |
|
||||||
print "Script name: $0\\n"; |
|
||||||
print "Command line arguments: @ARGV\\n"; |
|
||||||
print "Current line: $. \\n"; |
|
||||||
|
|
||||||
# File operations |
|
||||||
open(my $fh, '>', 'output.txt') or die "Cannot open file: $!"; |
|
||||||
print $fh "Hello, Perl!\\n"; |
|
||||||
close $fh; |
|
||||||
|
|
||||||
# Reading from standard input |
|
||||||
print "Enter your name: "; |
|
||||||
my $input = <STDIN>; |
|
||||||
chomp($input); # Remove newline |
|
||||||
print "Hello, $input!\\n"; |
|
||||||
|
|
||||||
# References |
|
||||||
my $array_ref = \\@fruits; |
|
||||||
print "First element via ref: ${$array_ref}[0]\\n"; |
|
||||||
|
|
||||||
my $hash_ref = \\%user; |
|
||||||
print "Name via ref: ${$hash_ref}{name}\\n"; |
|
||||||
|
|
||||||
# Using references for functions |
|
||||||
sub process_data { |
|
||||||
my ($data_ref) = @_; |
|
||||||
foreach my $key (keys %{$data_ref}) { |
|
||||||
print "Key: $key, Value: ${$data_ref}{$key}\\n"; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
process_data(\\%user); |
|
||||||
|
|
||||||
# Object-oriented style |
|
||||||
package Person; |
|
||||||
|
|
||||||
sub new { |
|
||||||
my ($class, $name, $age) = @_; |
|
||||||
return bless { name => $name, age => $age }, $class; |
|
||||||
} |
|
||||||
|
|
||||||
sub get_name { |
|
||||||
my ($self) = @_; |
|
||||||
return $self->{name}; |
|
||||||
} |
|
||||||
|
|
||||||
sub get_age { |
|
||||||
my ($self) = @_; |
|
||||||
return $self->{age}; |
|
||||||
} |
|
||||||
|
|
||||||
package main; |
|
||||||
my $person = Person->new("Bob", 25); |
|
||||||
print "Person name: " . $person->get_name() . "\\n"; |
|
||||||
print "Person age: " . $person->get_age() . "\\n"; |
|
||||||
|
|
||||||
exit 0; |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_perl(perl_code) == True |
|
||||||
assert detector.detect_language(perl_code) == "Perl" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(perl_code, "Perl") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_perl_detection() |
|
||||||
print("All Perl detection tests passed!") |
|
@ -1,184 +0,0 @@ |
|||||||
"""Test module for PHP language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_php_detection(): |
|
||||||
"""Test the PHP language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample PHP code |
|
||||||
php_code = r""" |
|
||||||
<?php |
|
||||||
// Define namespace |
|
||||||
namespace App\Controllers; |
|
||||||
|
|
||||||
// Import classes |
|
||||||
use App\Models\User; |
|
||||||
use App\Services\AuthService; |
|
||||||
use App\Exceptions\AuthException; |
|
||||||
|
|
||||||
/** |
|
||||||
* Authentication Controller |
|
||||||
* |
|
||||||
* Handles user authentication functionality |
|
||||||
*/ |
|
||||||
class AuthController |
|
||||||
{ |
|
||||||
private $authService; |
|
||||||
|
|
||||||
/** |
|
||||||
* Constructor |
|
||||||
*/ |
|
||||||
public function __construct(AuthService $authService) |
|
||||||
{ |
|
||||||
$this->authService = $authService; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Login user |
|
||||||
*/ |
|
||||||
public function login($request) |
|
||||||
{ |
|
||||||
// Get request data |
|
||||||
$email = $request->input('email'); |
|
||||||
$password = $request->input('password'); |
|
||||||
$remember = $request->input('remember', false); |
|
||||||
|
|
||||||
// Validate input |
|
||||||
if (empty($email) || empty($password)) { |
|
||||||
return [ |
|
||||||
'status' => 'error', |
|
||||||
'message' => 'Email and password are required' |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
try { |
|
||||||
// Attempt to login |
|
||||||
$user = $this->authService->authenticate($email, $password); |
|
||||||
|
|
||||||
// Create session |
|
||||||
$_SESSION['user_id'] = $user->id; |
|
||||||
|
|
||||||
// Set remember me cookie if requested |
|
||||||
if ($remember) { |
|
||||||
$token = $this->authService->createRememberToken($user->id); |
|
||||||
setcookie('remember_token', $token, time() + 86400 * 30, '/'); |
|
||||||
} |
|
||||||
|
|
||||||
return [ |
|
||||||
'status' => 'success', |
|
||||||
'user' => $user |
|
||||||
]; |
|
||||||
} catch (AuthException $e) { |
|
||||||
return [ |
|
||||||
'status' => 'error', |
|
||||||
'message' => $e->getMessage() |
|
||||||
]; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Register new user |
|
||||||
*/ |
|
||||||
public function register($request) |
|
||||||
{ |
|
||||||
// Get request data |
|
||||||
$name = $request->input('name'); |
|
||||||
$email = $request->input('email'); |
|
||||||
$password = $request->input('password'); |
|
||||||
|
|
||||||
// Validate input |
|
||||||
if (empty($name) || empty($email) || empty($password)) { |
|
||||||
return [ |
|
||||||
'status' => 'error', |
|
||||||
'message' => 'All fields are required' |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
// Check if email already exists |
|
||||||
$existingUser = User::findByEmail($email); |
|
||||||
if ($existingUser) { |
|
||||||
return [ |
|
||||||
'status' => 'error', |
|
||||||
'message' => 'Email already registered' |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
// Create user |
|
||||||
$user = new User(); |
|
||||||
$user->name = $name; |
|
||||||
$user->email = $email; |
|
||||||
$user->password = password_hash($password, PASSWORD_DEFAULT); |
|
||||||
$user->save(); |
|
||||||
|
|
||||||
// Login user |
|
||||||
$_SESSION['user_id'] = $user->id; |
|
||||||
|
|
||||||
return [ |
|
||||||
'status' => 'success', |
|
||||||
'user' => $user |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Logout user |
|
||||||
*/ |
|
||||||
public function logout() |
|
||||||
{ |
|
||||||
// Clear session |
|
||||||
unset($_SESSION['user_id']); |
|
||||||
session_destroy(); |
|
||||||
|
|
||||||
// Clear remember token cookie if it exists |
|
||||||
if (isset($_COOKIE['remember_token'])) { |
|
||||||
setcookie('remember_token', '', time() - 3600, '/'); |
|
||||||
} |
|
||||||
|
|
||||||
return [ |
|
||||||
'status' => 'success', |
|
||||||
'message' => 'Logged out successfully' |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
/** |
|
||||||
* Get current user profile |
|
||||||
*/ |
|
||||||
public function profile() |
|
||||||
{ |
|
||||||
if (!isset($_SESSION['user_id'])) { |
|
||||||
return [ |
|
||||||
'status' => 'error', |
|
||||||
'message' => 'Not authenticated' |
|
||||||
]; |
|
||||||
} |
|
||||||
|
|
||||||
$user = User::find($_SESSION['user_id']); |
|
||||||
|
|
||||||
return [ |
|
||||||
'status' => 'success', |
|
||||||
'user' => $user |
|
||||||
]; |
|
||||||
} |
|
||||||
} |
|
||||||
?> |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_php(php_code) == True |
|
||||||
assert detector.detect_language(php_code) == "PHP" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(php_code, "PHP") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_php_detection() |
|
||||||
print("All PHP detection tests passed!") |
|
@ -1,118 +0,0 @@ |
|||||||
"""Test module for R language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_r_detection(): |
|
||||||
"""Test the R language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample R code |
|
||||||
r_code = """ |
|
||||||
# Load necessary libraries |
|
||||||
library(tidyverse) |
|
||||||
library(ggplot2) |
|
||||||
library(dplyr) |
|
||||||
|
|
||||||
# Create a data frame |
|
||||||
data <- data.frame( |
|
||||||
name = c("Alice", "Bob", "Charlie", "David"), |
|
||||||
age = c(25, 30, 35, 40), |
|
||||||
score = c(85, 92, 78, 95) |
|
||||||
) |
|
||||||
|
|
||||||
# Basic data operations |
|
||||||
summary(data) |
|
||||||
str(data) |
|
||||||
head(data) |
|
||||||
|
|
||||||
# Create a function |
|
||||||
calculate_average <- function(x) { |
|
||||||
return(mean(x, na.rm = TRUE)) |
|
||||||
} |
|
||||||
|
|
||||||
# Apply the function |
|
||||||
avg_score <- calculate_average(data$score) |
|
||||||
print(paste("Average score:", avg_score)) |
|
||||||
|
|
||||||
# Data manipulation with dplyr |
|
||||||
filtered_data <- data %>% |
|
||||||
filter(age > 30) %>% |
|
||||||
select(name, score) %>% |
|
||||||
arrange(desc(score)) |
|
||||||
|
|
||||||
# Control structures |
|
||||||
if (nrow(filtered_data) > 0) { |
|
||||||
print("Found records with age > 30") |
|
||||||
} else { |
|
||||||
print("No records with age > 30") |
|
||||||
} |
|
||||||
|
|
||||||
# For loop example |
|
||||||
for (i in 1:nrow(data)) { |
|
||||||
if (data$age[i] < 30) { |
|
||||||
data$category[i] <- "Young" |
|
||||||
} else if (data$age[i] < 40) { |
|
||||||
data$category[i] <- "Middle" |
|
||||||
} else { |
|
||||||
data$category[i] <- "Senior" |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
# Create vectors |
|
||||||
ages <- c(25, 30, 35, 40) |
|
||||||
names <- c("Alice", "Bob", "Charlie", "David") |
|
||||||
|
|
||||||
# Create a list |
|
||||||
person <- list( |
|
||||||
name = "Alice", |
|
||||||
age = 25, |
|
||||||
scores = c(85, 90, 92) |
|
||||||
) |
|
||||||
|
|
||||||
# Access list elements |
|
||||||
person$name |
|
||||||
person$scores[2] |
|
||||||
|
|
||||||
# Create factors |
|
||||||
gender <- factor(c("Male", "Female", "Female", "Male")) |
|
||||||
levels(gender) |
|
||||||
|
|
||||||
# Basic plotting |
|
||||||
plot(data$age, data$score, |
|
||||||
main = "Age vs. Score", |
|
||||||
xlab = "Age", |
|
||||||
ylab = "Score", |
|
||||||
col = "blue", |
|
||||||
pch = 19) |
|
||||||
|
|
||||||
# ggplot visualization |
|
||||||
ggplot(data, aes(x = age, y = score)) + |
|
||||||
geom_point(color = "blue", size = 3) + |
|
||||||
geom_smooth(method = "lm", se = FALSE) + |
|
||||||
labs(title = "Age vs. Score", x = "Age", y = "Score") + |
|
||||||
theme_minimal() |
|
||||||
|
|
||||||
# Statistical analysis |
|
||||||
model <- lm(score ~ age, data = data) |
|
||||||
summary(model) |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_r(r_code) == True |
|
||||||
assert detector.detect_language(r_code) == "R" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(r_code, "R") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_r_detection() |
|
||||||
print("All R detection tests passed!") |
|
@ -1,57 +0,0 @@ |
|||||||
"""Test module for Ruby language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_ruby_detection(): |
|
||||||
"""Test the Ruby language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample Ruby code |
|
||||||
ruby_code = """ |
|
||||||
# A simple Ruby class |
|
||||||
class Person |
|
||||||
attr_accessor :name, :age |
|
||||||
|
|
||||||
def initialize(name, age) |
|
||||||
@name = name |
|
||||||
@age = age |
|
||||||
end |
|
||||||
|
|
||||||
def greet |
|
||||||
puts "Hello, my name is #{@name} and I am #{@age} years old." |
|
||||||
end |
|
||||||
end |
|
||||||
|
|
||||||
# Create a new Person |
|
||||||
person = Person.new("John", 30) |
|
||||||
person.greet |
|
||||||
|
|
||||||
# Hash examples |
|
||||||
old_syntax = { :name => "Ruby", :created_by => "Yukihiro Matsumoto" } |
|
||||||
new_syntax = { name: "Ruby", created_by: "Yukihiro Matsumoto" } |
|
||||||
|
|
||||||
# Block with parameters |
|
||||||
[1, 2, 3].each do |num| |
|
||||||
puts num * 2 |
|
||||||
end |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_ruby(ruby_code) == True |
|
||||||
assert detector.detect_language(ruby_code) == "Ruby" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(ruby_code, "Ruby") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_ruby_detection() |
|
||||||
print("All Ruby detection tests passed!") |
|
@ -1,89 +0,0 @@ |
|||||||
"""Test module for Rust language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_rust_detection(): |
|
||||||
"""Test the Rust language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample Rust code |
|
||||||
rust_code = """ |
|
||||||
use std::collections::HashMap; |
|
||||||
use std::io::{self, Write}; |
|
||||||
|
|
||||||
// A struct in Rust |
|
||||||
#[derive(Debug, Clone)] |
|
||||||
pub struct Person { |
|
||||||
name: String, |
|
||||||
age: u32, |
|
||||||
} |
|
||||||
|
|
||||||
// Implementation block for Person |
|
||||||
impl Person { |
|
||||||
// Constructor (associated function) |
|
||||||
pub fn new(name: String, age: u32) -> Self { |
|
||||||
Person { name, age } |
|
||||||
} |
|
||||||
|
|
||||||
// Method |
|
||||||
pub fn greet(&self) -> String { |
|
||||||
format!("Hello, my name is {} and I am {} years old.", self.name, self.age) |
|
||||||
} |
|
||||||
|
|
||||||
// Mutable method |
|
||||||
pub fn celebrate_birthday(&mut self) { |
|
||||||
self.age += 1; |
|
||||||
println!("Happy birthday! Now I am {} years old.", self.age); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// A simple function with pattern matching |
|
||||||
fn process_option(opt: Option<i32>) -> i32 { |
|
||||||
match opt { |
|
||||||
Some(value) => value, |
|
||||||
None => -1, |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Main function with vector usage |
|
||||||
fn main() { |
|
||||||
// Create a vector |
|
||||||
let mut numbers: Vec<i32> = vec![1, 2, 3, 4, 5]; |
|
||||||
numbers.push(6); |
|
||||||
|
|
||||||
// Create a Person instance |
|
||||||
let mut person = Person::new(String::from("Alice"), 30); |
|
||||||
println!("{}", person.greet()); |
|
||||||
person.celebrate_birthday(); |
|
||||||
|
|
||||||
// Use a HashMap |
|
||||||
let mut scores = HashMap::new(); |
|
||||||
scores.insert(String::from("Blue"), 10); |
|
||||||
scores.insert(String::from("Red"), 50); |
|
||||||
|
|
||||||
// Pattern matching with if let |
|
||||||
if let Some(score) = scores.get("Blue") { |
|
||||||
println!("Blue team score: {}", score); |
|
||||||
} |
|
||||||
} |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_rust(rust_code) == True |
|
||||||
assert detector.detect_language(rust_code) == "Rust" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(rust_code, "Rust") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_rust_detection() |
|
||||||
print("All Rust detection tests passed!") |
|
@ -1,209 +0,0 @@ |
|||||||
"""Test module for SQL language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_sql_detection(): |
|
||||||
"""Test the SQL language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample SQL code |
|
||||||
sql_code = """ |
|
||||||
-- Create database |
|
||||||
CREATE DATABASE ecommerce; |
|
||||||
|
|
||||||
-- Use the database |
|
||||||
USE ecommerce; |
|
||||||
|
|
||||||
-- Create tables |
|
||||||
CREATE TABLE customers ( |
|
||||||
customer_id INT PRIMARY KEY AUTO_INCREMENT, |
|
||||||
first_name VARCHAR(50) NOT NULL, |
|
||||||
last_name VARCHAR(50) NOT NULL, |
|
||||||
email VARCHAR(100) UNIQUE NOT NULL, |
|
||||||
password VARCHAR(255) NOT NULL, |
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, |
|
||||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
|
||||||
is_active BOOLEAN DEFAULT TRUE |
|
||||||
); |
|
||||||
|
|
||||||
CREATE TABLE categories ( |
|
||||||
category_id INT PRIMARY KEY AUTO_INCREMENT, |
|
||||||
name VARCHAR(100) NOT NULL, |
|
||||||
description TEXT, |
|
||||||
parent_id INT, |
|
||||||
FOREIGN KEY (parent_id) REFERENCES categories(category_id) |
|
||||||
); |
|
||||||
|
|
||||||
CREATE TABLE products ( |
|
||||||
product_id INT PRIMARY KEY AUTO_INCREMENT, |
|
||||||
name VARCHAR(100) NOT NULL, |
|
||||||
description TEXT, |
|
||||||
price DECIMAL(10, 2) NOT NULL, |
|
||||||
stock_quantity INT DEFAULT 0, |
|
||||||
category_id INT, |
|
||||||
created_at DATETIME DEFAULT CURRENT_TIMESTAMP, |
|
||||||
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP, |
|
||||||
FOREIGN KEY (category_id) REFERENCES categories(category_id) |
|
||||||
); |
|
||||||
|
|
||||||
CREATE TABLE orders ( |
|
||||||
order_id INT PRIMARY KEY AUTO_INCREMENT, |
|
||||||
customer_id INT NOT NULL, |
|
||||||
order_date DATETIME DEFAULT CURRENT_TIMESTAMP, |
|
||||||
status ENUM('pending', 'processing', 'shipped', 'delivered', 'cancelled') DEFAULT 'pending', |
|
||||||
total_amount DECIMAL(10, 2) NOT NULL, |
|
||||||
FOREIGN KEY (customer_id) REFERENCES customers(customer_id) |
|
||||||
); |
|
||||||
|
|
||||||
CREATE TABLE order_items ( |
|
||||||
order_item_id INT PRIMARY KEY AUTO_INCREMENT, |
|
||||||
order_id INT NOT NULL, |
|
||||||
product_id INT NOT NULL, |
|
||||||
quantity INT NOT NULL, |
|
||||||
price DECIMAL(10, 2) NOT NULL, |
|
||||||
FOREIGN KEY (order_id) REFERENCES orders(order_id), |
|
||||||
FOREIGN KEY (product_id) REFERENCES products(product_id) |
|
||||||
); |
|
||||||
|
|
||||||
-- Insert sample data |
|
||||||
INSERT INTO categories (name, description) |
|
||||||
VALUES ('Electronics', 'Electronic devices and gadgets'), |
|
||||||
('Clothing', 'Apparel and accessories'), |
|
||||||
('Books', 'Books and publications'); |
|
||||||
|
|
||||||
INSERT INTO products (name, description, price, stock_quantity, category_id) |
|
||||||
VALUES ('Smartphone', 'Latest smartphone with advanced features', 699.99, 100, 1), |
|
||||||
('Laptop', 'High-performance laptop for professionals', 1299.99, 50, 1), |
|
||||||
('T-shirt', 'Cotton t-shirt in various colors', 19.99, 200, 2), |
|
||||||
('Jeans', 'Classic denim jeans', 49.99, 150, 2), |
|
||||||
('Programming Book', 'Learn programming from experts', 39.99, 75, 3); |
|
||||||
|
|
||||||
-- Simple queries |
|
||||||
SELECT * FROM products WHERE price > 50.00; |
|
||||||
|
|
||||||
SELECT p.name, p.price, c.name AS category |
|
||||||
FROM products p |
|
||||||
JOIN categories c ON p.category_id = c.category_id |
|
||||||
WHERE p.stock_quantity > 0 |
|
||||||
ORDER BY p.price DESC; |
|
||||||
|
|
||||||
-- Aggregate functions |
|
||||||
SELECT |
|
||||||
c.name AS category, |
|
||||||
COUNT(p.product_id) AS product_count, |
|
||||||
AVG(p.price) AS average_price, |
|
||||||
MIN(p.price) AS min_price, |
|
||||||
MAX(p.price) AS max_price |
|
||||||
FROM products p |
|
||||||
JOIN categories c ON p.category_id = c.category_id |
|
||||||
GROUP BY c.name |
|
||||||
HAVING COUNT(p.product_id) > 1; |
|
||||||
|
|
||||||
-- Transactions |
|
||||||
BEGIN TRANSACTION; |
|
||||||
|
|
||||||
UPDATE products |
|
||||||
SET stock_quantity = stock_quantity - 1 |
|
||||||
WHERE product_id = 1; |
|
||||||
|
|
||||||
INSERT INTO orders (customer_id, total_amount) |
|
||||||
VALUES (1, 699.99); |
|
||||||
|
|
||||||
INSERT INTO order_items (order_id, product_id, quantity, price) |
|
||||||
VALUES (LAST_INSERT_ID(), 1, 1, 699.99); |
|
||||||
|
|
||||||
COMMIT; |
|
||||||
|
|
||||||
-- Views |
|
||||||
CREATE VIEW product_details AS |
|
||||||
SELECT |
|
||||||
p.product_id, |
|
||||||
p.name, |
|
||||||
p.description, |
|
||||||
p.price, |
|
||||||
p.stock_quantity, |
|
||||||
c.name AS category |
|
||||||
FROM products p |
|
||||||
JOIN categories c ON p.category_id = c.category_id; |
|
||||||
|
|
||||||
-- Stored procedure |
|
||||||
DELIMITER // |
|
||||||
CREATE PROCEDURE get_product_inventory() |
|
||||||
BEGIN |
|
||||||
SELECT |
|
||||||
p.name, |
|
||||||
p.stock_quantity, |
|
||||||
CASE |
|
||||||
WHEN p.stock_quantity = 0 THEN 'Out of Stock' |
|
||||||
WHEN p.stock_quantity < 10 THEN 'Low Stock' |
|
||||||
WHEN p.stock_quantity < 50 THEN 'Medium Stock' |
|
||||||
ELSE 'Well Stocked' |
|
||||||
END AS stock_status |
|
||||||
FROM products p |
|
||||||
ORDER BY p.stock_quantity; |
|
||||||
END // |
|
||||||
DELIMITER ; |
|
||||||
|
|
||||||
-- Triggers |
|
||||||
DELIMITER // |
|
||||||
CREATE TRIGGER after_order_insert |
|
||||||
AFTER INSERT ON orders |
|
||||||
FOR EACH ROW |
|
||||||
BEGIN |
|
||||||
INSERT INTO order_history (order_id, customer_id, status, action) |
|
||||||
VALUES (NEW.order_id, NEW.customer_id, NEW.status, 'created'); |
|
||||||
END // |
|
||||||
DELIMITER ; |
|
||||||
|
|
||||||
-- Indexes |
|
||||||
CREATE INDEX idx_product_price ON products(price); |
|
||||||
CREATE INDEX idx_order_customer ON orders(customer_id); |
|
||||||
|
|
||||||
-- Subqueries |
|
||||||
SELECT c.name, c.email |
|
||||||
FROM customers c |
|
||||||
WHERE c.customer_id IN ( |
|
||||||
SELECT DISTINCT o.customer_id |
|
||||||
FROM orders o |
|
||||||
JOIN order_items oi ON o.order_id = oi.order_id |
|
||||||
JOIN products p ON oi.product_id = p.product_id |
|
||||||
WHERE p.category_id = 1 |
|
||||||
); |
|
||||||
|
|
||||||
-- Common Table Expressions (CTE) |
|
||||||
WITH high_value_orders AS ( |
|
||||||
SELECT |
|
||||||
o.order_id, |
|
||||||
o.customer_id, |
|
||||||
o.total_amount |
|
||||||
FROM orders o |
|
||||||
WHERE o.total_amount > 500 |
|
||||||
) |
|
||||||
SELECT |
|
||||||
c.first_name, |
|
||||||
c.last_name, |
|
||||||
COUNT(hvo.order_id) AS high_value_order_count |
|
||||||
FROM customers c |
|
||||||
JOIN high_value_orders hvo ON c.customer_id = hvo.customer_id |
|
||||||
GROUP BY c.customer_id; |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_sql(sql_code) == True |
|
||||||
assert detector.detect_language(sql_code) == "SQL" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(sql_code, "SQL") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_sql_detection() |
|
||||||
print("All SQL detection tests passed!") |
|
@ -1,96 +0,0 @@ |
|||||||
"""Test module for Swift language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_swift_detection(): |
|
||||||
"""Test the Swift language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample Swift code |
|
||||||
swift_code = """ |
|
||||||
import Foundation |
|
||||||
import UIKit |
|
||||||
|
|
||||||
// A simple Swift class |
|
||||||
class Person { |
|
||||||
var name: String |
|
||||||
var age: Int |
|
||||||
|
|
||||||
init(name: String, age: Int) { |
|
||||||
self.name = name |
|
||||||
self.age = age |
|
||||||
} |
|
||||||
|
|
||||||
func greet() -> String { |
|
||||||
return "Hello, my name is \(name) and I am \(age) years old." |
|
||||||
} |
|
||||||
|
|
||||||
func celebrateBirthday() { |
|
||||||
age += 1 |
|
||||||
print("Happy birthday! Now I am \(age) years old.") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Swift structs |
|
||||||
struct Point { |
|
||||||
let x: Double |
|
||||||
let y: Double |
|
||||||
|
|
||||||
func distanceTo(point: Point) -> Double { |
|
||||||
return sqrt(pow(point.x - x, 2) + pow(point.y - y, 2)) |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Swift optional binding |
|
||||||
func processName(name: String?) { |
|
||||||
if let unwrappedName = name { |
|
||||||
print("Hello, \(unwrappedName)!") |
|
||||||
} else { |
|
||||||
print("Hello, anonymous!") |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Guard statement |
|
||||||
func process(value: Int?) { |
|
||||||
guard let value = value else { |
|
||||||
print("Value is nil") |
|
||||||
return |
|
||||||
} |
|
||||||
|
|
||||||
print("Value is \(value)") |
|
||||||
} |
|
||||||
|
|
||||||
// UIKit elements |
|
||||||
class MyViewController: UIViewController { |
|
||||||
@IBOutlet weak var nameLabel: UILabel! |
|
||||||
|
|
||||||
@IBAction func buttonPressed(_ sender: UIButton) { |
|
||||||
nameLabel.text = "Button was pressed!" |
|
||||||
} |
|
||||||
|
|
||||||
override func viewDidLoad() { |
|
||||||
super.viewDidLoad() |
|
||||||
// Do additional setup |
|
||||||
} |
|
||||||
} |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_swift(swift_code) == True |
|
||||||
assert detector.detect_language(swift_code) == "Swift" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(swift_code, "Swift") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_swift_detection() |
|
||||||
print("All Swift detection tests passed!") |
|
@ -1,148 +0,0 @@ |
|||||||
"""Test module for TypeScript language detection.""" |
|
||||||
|
|
||||||
import sys |
|
||||||
import os |
|
||||||
|
|
||||||
# Add the src directory to the Python path |
|
||||||
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), '../src'))) |
|
||||||
|
|
||||||
from ai_code_converter.core.language_detection import LanguageDetector |
|
||||||
|
|
||||||
|
|
||||||
def test_typescript_detection(): |
|
||||||
"""Test the TypeScript language detection functionality.""" |
|
||||||
detector = LanguageDetector() |
|
||||||
|
|
||||||
# Sample TypeScript code |
|
||||||
typescript_code = """ |
|
||||||
import { Component, OnInit } from '@angular/core'; |
|
||||||
import axios from 'axios'; |
|
||||||
|
|
||||||
// Interface definition |
|
||||||
interface User { |
|
||||||
id: number; |
|
||||||
name: string; |
|
||||||
email: string; |
|
||||||
isActive: boolean; |
|
||||||
} |
|
||||||
|
|
||||||
// Type alias |
|
||||||
type UserResponse = User[] | null; |
|
||||||
|
|
||||||
// Enum |
|
||||||
enum UserRole { |
|
||||||
Admin = 'ADMIN', |
|
||||||
User = 'USER', |
|
||||||
Guest = 'GUEST' |
|
||||||
} |
|
||||||
|
|
||||||
// Class with type annotations |
|
||||||
export class UserService { |
|
||||||
private apiUrl: string; |
|
||||||
private users: User[] = []; |
|
||||||
|
|
||||||
constructor(baseUrl: string) { |
|
||||||
this.apiUrl = `${baseUrl}/users`; |
|
||||||
} |
|
||||||
|
|
||||||
// Async method with return type |
|
||||||
public async getUsers(): Promise<User[]> { |
|
||||||
try { |
|
||||||
const response = await axios.get<UserResponse>(this.apiUrl); |
|
||||||
if (response.data) { |
|
||||||
this.users = response.data; |
|
||||||
return this.users; |
|
||||||
} |
|
||||||
return []; |
|
||||||
} catch (error) { |
|
||||||
console.error('Error fetching users:', error); |
|
||||||
return []; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Method with typed parameters |
|
||||||
public getUserById(id: number): User | undefined { |
|
||||||
return this.users.find(user => user.id === id); |
|
||||||
} |
|
||||||
|
|
||||||
// Method with union type parameters |
|
||||||
public filterUsers(status: boolean | null): User[] { |
|
||||||
if (status === null) return this.users; |
|
||||||
return this.users.filter(user => user.isActive === status); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Generic class |
|
||||||
class DataStore<T> { |
|
||||||
private items: T[] = []; |
|
||||||
|
|
||||||
public add(item: T): void { |
|
||||||
this.items.push(item); |
|
||||||
} |
|
||||||
|
|
||||||
public getAll(): T[] { |
|
||||||
return this.items; |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Decorator example |
|
||||||
@Component({ |
|
||||||
selector: 'app-user-list', |
|
||||||
template: '<div>User List Component</div>' |
|
||||||
}) |
|
||||||
class UserListComponent implements OnInit { |
|
||||||
users: User[] = []; |
|
||||||
userService: UserService; |
|
||||||
|
|
||||||
constructor() { |
|
||||||
this.userService = new UserService('https://api.example.com'); |
|
||||||
} |
|
||||||
|
|
||||||
async ngOnInit(): Promise<void> { |
|
||||||
this.users = await this.userService.getUsers(); |
|
||||||
console.log('Users loaded:', this.users.length); |
|
||||||
} |
|
||||||
} |
|
||||||
|
|
||||||
// Function with default parameters |
|
||||||
function createUser(name: string, email: string, isActive: boolean = true): User { |
|
||||||
const id = Math.floor(Math.random() * 1000); |
|
||||||
return { id, name, email, isActive }; |
|
||||||
} |
|
||||||
|
|
||||||
// Main code |
|
||||||
const userStore = new DataStore<User>(); |
|
||||||
const newUser = createUser('John Doe', 'john@example.com'); |
|
||||||
userStore.add(newUser); |
|
||||||
|
|
||||||
console.log('Users in store:', userStore.getAll().length); |
|
||||||
""" |
|
||||||
|
|
||||||
# Test the detection |
|
||||||
assert detector.detect_typescript(typescript_code) == True |
|
||||||
assert detector.detect_language(typescript_code) == "TypeScript" |
|
||||||
|
|
||||||
# Check that it's distinguishable from JavaScript |
|
||||||
js_code = """ |
|
||||||
function greet(name) { |
|
||||||
console.log(`Hello, ${name}!`); |
|
||||||
} |
|
||||||
|
|
||||||
const user = { |
|
||||||
name: 'John', |
|
||||||
age: 30 |
|
||||||
}; |
|
||||||
|
|
||||||
greet(user.name); |
|
||||||
""" |
|
||||||
assert detector.detect_typescript(js_code) == False |
|
||||||
assert detector.detect_language(js_code) == "JavaScript" |
|
||||||
|
|
||||||
# Check validation |
|
||||||
valid, _ = detector.validate_language(typescript_code, "TypeScript") |
|
||||||
assert valid == True |
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
test_typescript_detection() |
|
||||||
print("All TypeScript detection tests passed!") |
|
@ -1,332 +0,0 @@ |
|||||||
import gradio as gr |
|
||||||
|
|
||||||
# Define custom CSS with dark theme fixes, updated to use html.dark |
|
||||||
custom_css = """ |
|
||||||
/* Root variables for light theme */ |
|
||||||
:root { |
|
||||||
--background: #ffffff; |
|
||||||
--secondary-background: #f7f7f7; |
|
||||||
--tertiary-background: #f0f0f0; |
|
||||||
--text: #000000; |
|
||||||
--secondary-text: #5d5d5d; |
|
||||||
--border: #e0e0e0; |
|
||||||
--accent: #ff7b2c; |
|
||||||
--accent-hover: #ff6a14; |
|
||||||
--button-text: #ffffff; |
|
||||||
--code-bg: #f7f7f7; |
|
||||||
--code-text: #000000; |
|
||||||
--dropdown-bg: #ffffff; |
|
||||||
--slider-track: #e0e0e0; |
|
||||||
--slider-thumb: #ff7b2c; |
|
||||||
--collapsible-header: #f0f0f0; |
|
||||||
--primary-button-bg: #4a6ee0; /* Blue */ |
|
||||||
--primary-button-hover: #3a5ec8; |
|
||||||
--secondary-button-bg: #444444; |
|
||||||
--secondary-button-hover: #555555; |
|
||||||
--danger-button-bg: #e74c3c; /* Red */ |
|
||||||
--danger-button-hover: #c0392b; |
|
||||||
--success-button-bg: #e67e22; /* Orange */ |
|
||||||
--success-button-hover: #d35400; |
|
||||||
} |
|
||||||
|
|
||||||
/* Dark theme variables using html.dark */ |
|
||||||
html.dark { |
|
||||||
--background: #1a1a1a; |
|
||||||
--secondary-background: #252525; |
|
||||||
--tertiary-background: #2a2a2a; |
|
||||||
--text: #ffffff; |
|
||||||
--secondary-text: #cccccc; |
|
||||||
--border: #444444; |
|
||||||
--accent: #ff7b2c; |
|
||||||
--accent-hover: #ff6a14; |
|
||||||
--button-text: #ffffff; |
|
||||||
--code-bg: #252525; |
|
||||||
--code-text: #ffffff; |
|
||||||
--dropdown-bg: #2a2a2a; |
|
||||||
--slider-track: #444444; |
|
||||||
--slider-thumb: #ff7b2c; |
|
||||||
--collapsible-header: #333333; |
|
||||||
--primary-button-bg: #4a6ee0; |
|
||||||
--primary-button-hover: #3a5ec8; |
|
||||||
--secondary-button-bg: #444444; |
|
||||||
--secondary-button-hover: #555555; |
|
||||||
--danger-button-bg: #e74c3c; |
|
||||||
--danger-button-hover: #c0392b; |
|
||||||
--success-button-bg: #e67e22; |
|
||||||
--success-button-hover: #d35400; |
|
||||||
} |
|
||||||
|
|
||||||
/* Base styles */ |
|
||||||
body { |
|
||||||
background-color: var(--background) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
transition: all 0.3s ease; |
|
||||||
} |
|
||||||
|
|
||||||
.gradio-container { |
|
||||||
background-color: var(--background) !important; |
|
||||||
max-width: 100% !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Headers */ |
|
||||||
h1, h2, h3, h4, h5, h6, .gr-header { |
|
||||||
color: var(--text) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Panels and blocks */ |
|
||||||
.gr-panel, .gr-form, .gr-box, .gr-block { |
|
||||||
background-color: var(--secondary-background) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
border-color: var(--border) !important; |
|
||||||
border-radius: 6px !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Validation messages section */ |
|
||||||
.gr-accordion .gr-panel { |
|
||||||
background-color: var(--secondary-background) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
border-color: #e74c3c !important; /* Red border */ |
|
||||||
} |
|
||||||
|
|
||||||
.gr-accordion-header { |
|
||||||
background-color: var(--collapsible-header) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Code editors */ |
|
||||||
.codebox, .code-editor, .cm-editor { |
|
||||||
background-color: var(--code-bg) !important; |
|
||||||
color: var(--code-text) !important; |
|
||||||
border: 1px solid var(--border) !important; |
|
||||||
border-radius: 4px !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Syntax highlighting */ |
|
||||||
.cm-editor .cm-content, .cm-editor .cm-line { |
|
||||||
color: var(--code-text) !important; |
|
||||||
} |
|
||||||
.cm-editor .cm-keyword { color: #ff79c6 !important; } /* Pink */ |
|
||||||
.cm-editor .cm-number { color: #bd93f9 !important; } /* Purple */ |
|
||||||
.cm-editor .cm-string { color: #f1fa8c !important; } /* Yellow */ |
|
||||||
.cm-editor .cm-comment { color: #6272a4 !important; } /* Gray */ |
|
||||||
|
|
||||||
/* Buttons */ |
|
||||||
.gr-button { |
|
||||||
background-color: var(--tertiary-background) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
border-color: var(--border) !important; |
|
||||||
border-radius: 4px !important; |
|
||||||
} |
|
||||||
.gr-button.success { |
|
||||||
background-color: var(--success-button-bg) !important; |
|
||||||
color: var(--button-text) !important; |
|
||||||
} |
|
||||||
.gr-button.success:hover { |
|
||||||
background-color: var(--success-button-hover) !important; |
|
||||||
} |
|
||||||
.gr-button.danger { |
|
||||||
background-color: var(--danger-button-bg) !important; |
|
||||||
color: var(--button-text) !important; |
|
||||||
} |
|
||||||
.gr-button.danger:hover { |
|
||||||
background-color: var(--danger-button-hover) !important; |
|
||||||
} |
|
||||||
.gr-button.secondary { |
|
||||||
background-color: var(--secondary-button-bg) !important; |
|
||||||
color: var(--button-text) !important; |
|
||||||
} |
|
||||||
.gr-button.secondary:hover { |
|
||||||
background-color: var(--secondary-button-hover) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* File upload */ |
|
||||||
.gr-file, .gr-file-upload { |
|
||||||
background-color: var(--secondary-background) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
border-color: var(--border) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Dropdowns */ |
|
||||||
.gr-dropdown, .gr-dropdown-container, .gr-dropdown select, .gr-dropdown option { |
|
||||||
background-color: var(--dropdown-bg) !important; |
|
||||||
color: var(--text) !important; |
|
||||||
border-color: var(--border) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Slider */ |
|
||||||
.gr-slider { |
|
||||||
background-color: var(--background) !important; |
|
||||||
} |
|
||||||
.gr-slider-track { |
|
||||||
background-color: var(--slider-track) !important; |
|
||||||
} |
|
||||||
.gr-slider-handle { |
|
||||||
background-color: var(--slider-thumb) !important; |
|
||||||
} |
|
||||||
.gr-slider-value { |
|
||||||
color: var(--text) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Code output */ |
|
||||||
.gr-code { |
|
||||||
background-color: var(--code-bg) !important; |
|
||||||
color: var(--code-text) !important; |
|
||||||
border-color: var(--border) !important; |
|
||||||
} |
|
||||||
|
|
||||||
/* Footer */ |
|
||||||
.footer { |
|
||||||
color: var(--secondary-text) !important; |
|
||||||
} |
|
||||||
.footer a { |
|
||||||
color: var(--accent) !important; |
|
||||||
} |
|
||||||
""" |
|
||||||
|
|
||||||
# JavaScript for theme toggling and initialization |
|
||||||
js_code = """ |
|
||||||
<script> |
|
||||||
function toggleTheme(theme) { |
|
||||||
var url = new URL(window.location.href); |
|
||||||
if (theme === "dark") { |
|
||||||
url.searchParams.set('__theme', 'dark'); |
|
||||||
} else { |
|
||||||
url.searchParams.delete('__theme'); |
|
||||||
} |
|
||||||
window.location.href = url.href; |
|
||||||
} |
|
||||||
|
|
||||||
// Set the radio button based on current theme |
|
||||||
document.addEventListener('DOMContentLoaded', function() { |
|
||||||
var urlParams = new URLSearchParams(window.location.search); |
|
||||||
var currentTheme = urlParams.get('__theme'); |
|
||||||
if (currentTheme === 'dark') { |
|
||||||
document.querySelector('#theme_radio_container input[value="dark"]').checked = true; |
|
||||||
} else { |
|
||||||
document.querySelector('#theme_radio_container input[value="light"]').checked = true; |
|
||||||
} |
|
||||||
}); |
|
||||||
</script> |
|
||||||
""" |
|
||||||
|
|
||||||
# Language and model options |
|
||||||
INPUT_LANGUAGES = ["Python", "JavaScript", "Java", "TypeScript", "Swift", "C#", "Ruby", "Go", "Rust", "PHP"] |
|
||||||
OUTPUT_LANGUAGES = ["Python", "JavaScript", "Java", "TypeScript", "Swift", "C#", "Ruby", "Go", "Rust", "PHP", "Julia"] |
|
||||||
MODELS = ["GPT", "Claude", "CodeLlama", "Llama", "Gemini"] |
|
||||||
DOC_STYLES = ["standard", "detailed", "minimal"] |
|
||||||
|
|
||||||
# Build the interface |
|
||||||
with gr.Blocks(css=custom_css, theme=gr.themes.Base()) as demo: |
|
||||||
# Inject the JavaScript code |
|
||||||
gr.HTML(js_code) |
|
||||||
|
|
||||||
# States for dynamic button text |
|
||||||
input_lang_state = gr.State("Python") |
|
||||||
output_lang_state = gr.State("JavaScript") |
|
||||||
|
|
||||||
# Header |
|
||||||
with gr.Row(elem_classes="header-container"): |
|
||||||
gr.HTML("<h1 class='header-title'>AI CodeXchange</h1>") |
|
||||||
# Theme selection radio and apply button |
|
||||||
theme_radio = gr.Radio(["light", "dark"], label="Theme", elem_id="theme_radio_container", value="dark") |
|
||||||
theme_button = gr.Button("Apply Theme") |
|
||||||
|
|
||||||
# Validation Messages |
|
||||||
with gr.Accordion("Validation Messages", open=True): |
|
||||||
with gr.Row(): |
|
||||||
with gr.Column(): |
|
||||||
input_code = gr.Code(language="python", label="Code In", lines=15, elem_classes="code-container") |
|
||||||
with gr.Column(): |
|
||||||
output_code = gr.Code(language="javascript", label="Converted Code", lines=15, elem_classes="code-container") |
|
||||||
|
|
||||||
# Configuration Options |
|
||||||
with gr.Row(): |
|
||||||
input_lang = gr.Dropdown(INPUT_LANGUAGES, label="Code In", value="Python") |
|
||||||
output_lang = gr.Dropdown(OUTPUT_LANGUAGES, label="Code Out", value="JavaScript") |
|
||||||
model = gr.Dropdown(MODELS, label="Model", value="GPT") |
|
||||||
temperature = gr.Slider(minimum=0, maximum=1, step=0.1, value=0.7, label="Temperature") |
|
||||||
|
|
||||||
# Document Options |
|
||||||
with gr.Row(): |
|
||||||
document_check = gr.Checkbox(label="Document", value=True) |
|
||||||
doc_style = gr.Dropdown(DOC_STYLES, label="Document Style", value="standard") |
|
||||||
|
|
||||||
# File Upload |
|
||||||
with gr.Accordion("Upload", open=True): |
|
||||||
file_upload = gr.File(label="Drop File Here - or - Click to Upload") |
|
||||||
|
|
||||||
# Action Buttons |
|
||||||
with gr.Row(elem_classes="button-row"): |
|
||||||
convert_btn = gr.Button("Convert", elem_classes="success") |
|
||||||
clear_btn = gr.Button("Clear All", elem_classes="danger") |
|
||||||
|
|
||||||
# Run Buttons |
|
||||||
with gr.Row(elem_classes="button-row"): |
|
||||||
run_source = gr.Button("Run Source Code", elem_classes="secondary") |
|
||||||
run_target = gr.Button("Run Target Code", elem_classes="secondary") |
|
||||||
|
|
||||||
# Results |
|
||||||
with gr.Row(): |
|
||||||
source_result = gr.Code(label="Source Code Result", language="python", lines=10, elem_classes="code-container") |
|
||||||
target_result = gr.Code(label="Converted Code Result", language="javascript", lines=10, elem_classes="code-container") |
|
||||||
|
|
||||||
# Download |
|
||||||
with gr.Accordion("Download", open=True): |
|
||||||
with gr.Row(): |
|
||||||
dl_source = gr.Button("Download Source Code") |
|
||||||
dl_target = gr.Button("Download Converted Code") |
|
||||||
|
|
||||||
# Footer |
|
||||||
with gr.Row(elem_classes="footer"): |
|
||||||
gr.HTML("<div>Use via API</div><div>•</div><div>Built with Gradio</div><div>•</div><div>Settings</div>") |
|
||||||
|
|
||||||
# Theme toggle event |
|
||||||
theme_button.click( |
|
||||||
fn=None, |
|
||||||
inputs=None, |
|
||||||
outputs=[], |
|
||||||
js=""" |
|
||||||
var theme = document.querySelector('#theme_radio_container input:checked').value; |
|
||||||
toggleTheme(theme); |
|
||||||
""" |
|
||||||
) |
|
||||||
|
|
||||||
# Existing event handlers |
|
||||||
def convert_code(input_code, in_lang, out_lang, model, temp, doc, doc_style): |
|
||||||
return f"// Converted from {in_lang} to {out_lang} using {model}\n// Temperature: {temp}\n// Documentation: {doc} ({doc_style if doc else 'N/A'})" |
|
||||||
|
|
||||||
convert_btn.click(fn=convert_code, inputs=[input_code, input_lang_state, output_lang_state, model, temperature, document_check, doc_style], outputs=[output_code]) |
|
||||||
|
|
||||||
def update_convert_btn_text(in_lang, out_lang): |
|
||||||
return f"Convert {in_lang} to {out_lang}", in_lang, out_lang |
|
||||||
|
|
||||||
input_lang.change(fn=update_convert_btn_text, inputs=[input_lang, output_lang], outputs=[convert_btn, input_lang_state, output_lang_state]) |
|
||||||
output_lang.change(fn=update_convert_btn_text, inputs=[input_lang, output_lang], outputs=[convert_btn, input_lang_state, output_lang_state]) |
|
||||||
|
|
||||||
def update_run_btn_text(in_lang, out_lang): |
|
||||||
return f"Run {in_lang}", f"Run {out_lang}" |
|
||||||
|
|
||||||
input_lang.change(fn=update_run_btn_text, inputs=[input_lang, output_lang], outputs=[run_source, run_target]) |
|
||||||
output_lang.change(fn=update_run_btn_text, inputs=[input_lang, output_lang], outputs=[run_source, run_target]) |
|
||||||
|
|
||||||
def clear_all(): |
|
||||||
return "", "", "", "" |
|
||||||
|
|
||||||
clear_btn.click(fn=clear_all, inputs=[], outputs=[input_code, output_code, source_result, target_result]) |
|
||||||
|
|
||||||
def run_code(code, lang): |
|
||||||
return f"// Running {lang} code...\n// Results would appear here" |
|
||||||
|
|
||||||
run_source.click(fn=run_code, inputs=[input_code, input_lang_state], outputs=[source_result]) |
|
||||||
run_target.click(fn=run_code, inputs=[output_code, output_lang_state], outputs=[target_result]) |
|
||||||
|
|
||||||
def handle_file_upload(file): |
|
||||||
if file is None: |
|
||||||
return "" |
|
||||||
with open(file.name, "r") as f: |
|
||||||
return f.read() |
|
||||||
|
|
||||||
file_upload.change(fn=handle_file_upload, inputs=[file_upload], outputs=[input_code]) |
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
demo.launch() |
|
@ -1,35 +0,0 @@ |
|||||||
import gradio as gr |
|
||||||
|
|
||||||
# JavaScript function to toggle theme |
|
||||||
js_code = """ |
|
||||||
function toggleTheme(theme) { |
|
||||||
var url = new URL(window.location.href); |
|
||||||
if (theme === "dark") { |
|
||||||
url.searchParams.set('__theme', 'dark'); |
|
||||||
} else { |
|
||||||
url.searchParams.delete('__theme'); |
|
||||||
} |
|
||||||
window.location.href = url.href; |
|
||||||
} |
|
||||||
""" |
|
||||||
|
|
||||||
def create_app(): |
|
||||||
with gr.Blocks(js=js_code) as demo: |
|
||||||
theme_radio = gr.Radio(["light", "dark"], label="Theme") |
|
||||||
|
|
||||||
# Button to trigger the theme change |
|
||||||
theme_button = gr.Button("Toggle Theme") |
|
||||||
|
|
||||||
# Use JavaScript to toggle the theme when the button is clicked |
|
||||||
theme_button.click( |
|
||||||
None, |
|
||||||
inputs=[theme_radio], |
|
||||||
js=f"(theme) => {{ toggleTheme(theme); return []; }}", |
|
||||||
queue=False, |
|
||||||
) |
|
||||||
|
|
||||||
return demo |
|
||||||
|
|
||||||
if __name__ == "__main__": |
|
||||||
app = create_app() |
|
||||||
app.launch() |
|
Loading…
Reference in new issue