diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6bac06f1..d8863546 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -27,14 +27,23 @@ jobs: with: python-version: 3.11 - - run: pip install uv - - run: uv sync + - name: Install dependencies + run: | + pip install uv + uv sync # Python checks (isort, black, ruff, mypy) - - run: uv run isort --check-only . - - run: uv run black --check . - - run: uv run ruff check --ignore E501,E402 . - - run: uv run mypy . + - name: Python lint & typecheck + run: | + uv run isort --check-only . + uv run black --check . + uv run ruff check --ignore E501,E402,I001,I002 . + uv run mypy . + + # TypeScript type check + - name: TypeScript typecheck + run: node ./scripts/typescript-typecheck.js # JS/TS/Markdown/YAML checks - - run: uv run prettier --check "**/*.{ts,tsx,js,jsx,json,md,yaml,yml}" + - name: Prettier check + run: uv run prettier --check "**/*.{ts,tsx,js,jsx,json,md,yaml,yml}" diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f979589d..ea0c2e5a 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -8,6 +8,13 @@ repos: language: node files: \.(ts|tsx|js|jsx|json|md|yaml|yml)$ + - repo: local + hooks: + - id: tsc + name: TypeScript type check + entry: node ./scripts/typescript-typecheck.js + language: node + - repo: https://github.com/PyCQA/isort rev: 7.0.0 hooks: @@ -31,7 +38,7 @@ repos: - id: ruff name: ruff linter language_version: python3.11 - args: ['--fix', '--ignore', 'E501,E402'] # Ignore line length and module level import not at top of file + args: ['--fix', '--ignore', 'E501,E402,I001,I002'] # Ignore line length, module level import not at top of file, and import sorting issues files: \.(py)$ - repo: https://github.com/pre-commit/mirrors-mypy diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 75980e2a..e38aa3ed 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -36,16 +36,19 @@ We follow strict code formatting guidelines to ensure consistency across the cod ```bash # For Python code uv run black . - uv run ruff check --fix . + uv run isort . + uv run ruff check --ignore E501,E402,I001,I002 --fix . ``` 4. **Validate Your Code**: Ensure your code passes all checks: ```bash uv run mypy . ``` +5. Every time you try to commit code, a pre-commit hook will automatically run the formatting and validation tools. If any issues are found, the commit will be blocked until they are resolved. Please make sure to address any issues reported by the pre-commit hook before attempting to commit again. Once all issues are resolved, you can proceed with your commit. ## Documentation Documentation improvements are always welcome. You can: + - Fix typos or unclear explanations - Add examples and use cases - Improve API documentation @@ -53,4 +56,4 @@ Documentation improvements are always welcome. You can: For detailed instructions on setting up your development environment and submitting code contributions, please see our [Developer-Guide](Development.md). -Feel free to join our [Discord community](https://discord.com/invite/mVnXXpdE85) to discuss ideas or get help with your contributions. \ No newline at end of file +Feel free to join our [Discord community](https://discord.com/invite/mVnXXpdE85) to discuss ideas or get help with your contributions. diff --git a/Development.md b/Development.md index 2b061aea..3fdbc5f0 100644 --- a/Development.md +++ b/Development.md @@ -17,36 +17,38 @@ These packages are part of a uv workspace which manages a shared virtual environ 1. Install Lume CLI: - ```bash - /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/lume/scripts/install.sh)" - ``` + ```bash + /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/trycua/cua/main/libs/lume/scripts/install.sh)" + ``` 2. Clone the repository: - ```bash - git clone https://github.com/trycua/cua.git - cd cua - ``` + ```bash + git clone https://github.com/trycua/cua.git + cd cua + ``` 3. Create a `.env.local` file in the root directory with your API keys: - ```bash - # Required for Anthropic provider - ANTHROPIC_API_KEY=your_anthropic_key_here + ```bash + # Required for Anthropic provider + ANTHROPIC_API_KEY=your_anthropic_key_here - # Required for OpenAI provider - OPENAI_API_KEY=your_openai_key_here - ``` + # Required for OpenAI provider + OPENAI_API_KEY=your_openai_key_here + ``` 4. Open the workspace in VSCode or Cursor: - ```bash - # For Cua Python development - code .vscode/py.code-workspace + ```bash + # For Cua Python development + code .vscode/py.code-workspace - # For Lume (Swift) development - code .vscode/lume.code-workspace - ``` + # For Lume (Swift) development + code .vscode/lume.code-workspace + ``` + +5. Install Pre-commit hooks ([see below](#pre-commit-hook)): Using the workspace file is strongly recommended as it: @@ -55,6 +57,19 @@ Using the workspace file is strongly recommended as it: - Enables debugging configurations - Maintains consistent settings across packages +### Pre-commit Hook Installation + +Pre-commit hooks are scripts that run automatically before each commit to ensure code quality and consistency. +To install the hooks: + +```bash +# First, ensure dependencies are installed (only needed once) +uv sync + +# Then install the pre-commit hooks +uv run pre-commit install +``` + ## Lume Development Refer to the [Lume README](./libs/lume/Development.md) for instructions on how to develop the Lume CLI. @@ -118,10 +133,11 @@ The Cua project follows strict code formatting standards to ensure consistency a The project uses the following tools for code formatting and linting: - **[Black](https://black.readthedocs.io/)**: Code formatter +- **[isort](https://pycqa.github.io/isort/)**: Import sorter - **[Ruff](https://beta.ruff.rs/docs/)**: Fast linter and formatter - **[MyPy](https://mypy.readthedocs.io/)**: Static type checker -These tools are automatically installed when you set up the development environment using the `./scripts/build.sh` script. +These tools are automatically installed when you set up the development environment. #### Configuration @@ -163,23 +179,48 @@ warn_unused_ignores = false The repository includes VSCode workspace configurations that enable automatic formatting. When you open the workspace files (as recommended in the setup instructions), the correct formatting settings are automatically applied. -Python-specific settings in the workspace files: +##### Python-specific settings + +These are configured in `.vscode/settings.json`: ```json -"[python]": { - "editor.formatOnSave": true, - "editor.defaultFormatter": "ms-python.black-formatter", - "editor.codeActionsOnSave": { - "source.organizeImports": "explicit" - } +{ + "python.defaultInterpreterPath": "${workspaceFolder}/.venv/bin/python", + "editor.formatOnSave": true, + "editor.codeActionsOnSave": { + "source.organizeImports": "explicit", + "source.fixAll": "explicit" + }, + "[python]": { + "editor.defaultFormatter": "ms-python.black-formatter" + }, + "python.formatting.provider": "black", + "ruff.configuration": "${workspaceFolder}/pyproject.toml", + "mypy-type-checker.args": ["--config-file", "${workspaceFolder}/pyproject.toml"], + "mypy-type-checker.path": ["${workspaceFolder}"] } ``` -Recommended VS Code extensions: +##### **JS/TS-specific settings** -- Black Formatter (ms-python.black-formatter) -- Ruff (charliermarsh.ruff) -- Pylance (ms-python.vscode-pylance) +```json +"[javascript][typescript][typescriptreact][javascriptreact]": { + "editor.defaultFormatter": "esbenp.prettier-vscode" +} +``` + +- Ensures Prettier is used for all JS/TS files for consistent formatting. + +Recommended VS Code Extensions + +- **Black Formatter** – `ms-python.black-formatter` +- **Ruff** – `charliermarsh.ruff` +- **Pylance** – `ms-python.vscode-pylance` +- **isort** – `ms-python.isort` +- **Prettier** – `esbenp.prettier-vscode` +- **Mypy Type Checker** – `ms-python.mypy-type-checker` + +> VSCode will automatically suggest installing the recommended extensions when you open the workspace. #### Manual Formatting @@ -189,8 +230,11 @@ To manually format code: # Format all Python files using Black uv run black . +# Sort imports using isort +uv run isort . + # Run Ruff linter with auto-fix -uv run ruff check --fix . +uv run ruff check --ignore E501,E402,I001,I002 . # Run type checking with MyPy uv run mypy . @@ -200,11 +244,29 @@ uv run mypy . Before submitting a pull request, ensure your code passes all formatting checks: +**Option 1: Run all hooks via pre-commit (all in a single command)** + ```bash -# Run all checks +# Run hooks on staged files (recommended for quick checks) +uv run pre-commit run +``` + +- Automatically runs Black, Ruff, isort, Mypy, Prettier, and any other configured hooks. + +**Option 2: Run individual tools manually** + +```bash +# Python checks uv run black --check . -uv run ruff check . +uv run isort --check . +uv run ruff check --ignore E501,E402,I001,I002 . uv run mypy . + +# JavaScript/TypeScript checks +uv run prettier --check "**/*.{ts,tsx,js,jsx,json,md,yaml,yml}" + +# TypeScript typecheck +node ./scripts/typescript-typecheck.js ``` ### Swift Code (Lume) diff --git a/scripts/typescript-typecheck.js b/scripts/typescript-typecheck.js new file mode 100644 index 00000000..29e12345 --- /dev/null +++ b/scripts/typescript-typecheck.js @@ -0,0 +1,8 @@ +#!/usr/bin/env node +const { execSync } = require('child_process'); + +try { + execSync('pnpm -C libs/typescript -r run typecheck', { stdio: 'inherit' }); +} catch (err) { + process.exit(1); +} diff --git a/uv.lock b/uv.lock index 776161aa..d33f2821 100644 --- a/uv.lock +++ b/uv.lock @@ -1160,6 +1160,7 @@ dev = [ { name = "cua-som" }, { name = "hud-python", extra = ["agent"] }, { name = "ipykernel" }, + { name = "isort" }, { name = "jedi" }, { name = "jupyter" }, { name = "mypy" }, @@ -1197,6 +1198,7 @@ dev = [ { name = "cua-som", editable = "libs/python/som" }, { name = "hud-python", extras = ["agent"], specifier = "==0.4.52" }, { name = "ipykernel", specifier = ">=6.29.5" }, + { name = "isort", specifier = ">=7.0.0" }, { name = "jedi", specifier = ">=0.19.2" }, { name = "jupyter", specifier = ">=1.0.0" }, { name = "mypy", specifier = ">=1.10.0" }, @@ -2252,6 +2254,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/7b/55/e5326141505c5d5e34c5e0935d2908a74e4561eca44108fbfb9c13d2911a/isoduration-20.11.0-py3-none-any.whl", hash = "sha256:b2904c2a4228c3d44f409c8ae8e2370eb21a26f7ac2ec5446df141dde3452042", size = 11321, upload-time = "2020-11-01T10:59:58.02Z" }, ] +[[package]] +name = "isort" +version = "7.0.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/63/53/4f3c058e3bace40282876f9b553343376ee687f3c35a525dc79dbd450f88/isort-7.0.0.tar.gz", hash = "sha256:5513527951aadb3ac4292a41a16cbc50dd1642432f5e8c20057d414bdafb4187", size = 805049, upload-time = "2025-10-11T13:30:59.107Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/7f/ed/e3705d6d02b4f7aea715a353c8ce193efd0b5db13e204df895d38734c244/isort-7.0.0-py3-none-any.whl", hash = "sha256:1bcabac8bc3c36c7fb7b98a76c8abb18e0f841a3ba81decac7691008592499c1", size = 94672, upload-time = "2025-10-11T13:30:57.665Z" }, +] + [[package]] name = "jedi" version = "0.19.2"