diff --git a/.justfile b/.justfile new file mode 100644 index 0000000..c6a1e42 --- /dev/null +++ b/.justfile @@ -0,0 +1,44 @@ +# .justfile for project management + +pr_prep_patch: + git fetch origin + git checkout main + git pull origin main + git checkout - + git merge main + uv run ruff format + uv run ruff check --fix + uv lock -U + uv version --bump patch + uv build + git add . + git commit -m 'automated commit from just pr_prep_patch' + +pr_prep_minor: + git fetch origin + git checkout main + git pull origin main + git checkout - + git merge main + uv run ruff format + uv run ruff check --fix + uv lock -U + uv version --bump minor + uv build + git add . + git commit -m 'automated commit from just pr_prep_minor' + + +pr_prep_major: + git fetch origin + git checkout main + git pull origin main + git checkout - + git merge main + uv run ruff format + uv run ruff check --fix + uv lock -U + uv version --bump major + uv build + git add . + git commit -m 'automated commit from just pr_prep_major' diff --git a/.vscode/tasks.json b/.vscode/tasks.json new file mode 100644 index 0000000..deb1f5f --- /dev/null +++ b/.vscode/tasks.json @@ -0,0 +1,145 @@ +{ + "version": "2.0.0", + "tasks": [ + { + "label": "PR Prep: Patch", + "type": "shell", + "command": "just", + "args": ["pr_prep_patch"], + "group": { + "kind": "build", + "isDefault": false + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "shared", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": [], + "detail": "Prepare PR with patch version bump", + "icon": { + "id": "git-pull-request", + "color": "terminal.ansiGreen" + } + }, + { + "label": "PR Prep: Minor", + "type": "shell", + "command": "just", + "args": ["pr_prep_minor"], + "group": { + "kind": "build", + "isDefault": false + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "shared", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": [], + "detail": "Prepare PR with minor version bump", + "icon": { + "id": "git-pull-request", + "color": "terminal.ansiBlue" + } + }, + { + "label": "PR Prep: Major", + "type": "shell", + "command": "just", + "args": ["pr_prep_major"], + "group": { + "kind": "build", + "isDefault": false + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "shared", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": [], + "detail": "Prepare PR with major version bump", + "icon": { + "id": "git-pull-request", + "color": "terminal.ansiRed" + } + }, + { + "label": "Code Quality: Format & Lint", + "type": "shell", + "command": "uv", + "args": ["run", "ruff", "format"], + "group": { + "kind": "build", + "isDefault": true + }, + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "shared", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": [], + "detail": "Format code with ruff", + "icon": { + "id": "code", + "color": "terminal.ansiYellow" + }, + "dependsOrder": "sequence", + "dependsOn": ["Code Quality: Lint Fix"] + }, + { + "label": "Code Quality: Lint Fix", + "type": "shell", + "command": "uv", + "args": ["run", "ruff", "check", "--fix"], + "group": "build", + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "shared", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": [], + "detail": "Fix linting issues with ruff", + "icon": { + "id": "tools", + "color": "terminal.ansiYellow" + } + }, + { + "label": "Dependencies: Update Lock", + "type": "shell", + "command": "uv", + "args": ["lock", "-U"], + "group": "build", + "presentation": { + "echo": true, + "reveal": "always", + "focus": true, + "panel": "shared", + "showReuseMessage": true, + "clear": false + }, + "problemMatcher": [], + "detail": "Update dependency lock file", + "icon": { + "id": "package", + "color": "terminal.ansiCyan" + } + } + ] +} \ No newline at end of file diff --git a/README.md b/README.md index 876a699..5cbecc4 100644 --- a/README.md +++ b/README.md @@ -80,6 +80,91 @@ If you prefer not to use the entry point, you can run directly: uv run src/main.py ``` +## Development Workflow + +Merlin includes automated development workflows using [Just](https://just.systems/) - a command runner that simplifies common tasks. + +### Installing Just + +**Option 1: Quick Install (Recommended)** +```bash +curl --proto '=https' --tlsv1.2 -sSf https://just.systems/install.sh | bash -s -- --to ~/.local/bin +``` + +**Option 2: Package Manager** +```bash +# On macOS with Homebrew +brew install just + +# On Ubuntu/Debian +wget -qO - 'https://proget.makedeb.org/debian-feeds/prebuilt-mpr.pub' | gpg --dearmor | sudo tee /usr/share/keyrings/prebuilt-mpr-archive-keyring.gpg 1> /dev/null +echo "deb [arch=all,amd64,arm64,armhf signed-by=/usr/share/keyrings/prebuilt-mpr-archive-keyring.gpg] https://proget.makedeb.org prebuilt-mpr $(lsb_release -cs)" | sudo tee /etc/apt/sources.list.d/prebuilt-mpr.list +sudo apt update +sudo apt install just + +# On Windows with Chocolatey +choco install just + +# On Windows with Scoop +scoop install just +``` + +### Available Commands + +Run `just --list` to see all available commands: + +- **`just pr_prep_patch`** - Prepare PR with patch version bump (bug fixes, small changes) +- **`just pr_prep_minor`** - Prepare PR with minor version bump (new features, backward compatible) +- **`just pr_prep_major`** - Prepare PR with major version bump (breaking changes) + +### What Each Command Does + +Each PR preparation command performs a complete automated workflow: + +1. **Git Sync**: Fetch, checkout main, pull latest, merge to current branch +2. **Code Quality**: Format code with `ruff format` and fix issues with `ruff check --fix` +3. **Dependencies**: Update lock file with `uv lock -U` +4. **Versioning**: Bump version (patch/minor/major) and build project +5. **Commit**: Stage all changes and commit with automated message + +### Usage Examples + +**Terminal Usage:** +```bash +# For bug fixes and documentation updates +just pr_prep_patch + +# For new features that don't break existing functionality +just pr_prep_minor + +# For breaking changes or major rewrites +just pr_prep_major +``` + +**VS Code Integration:** + +The project includes VS Code tasks for easy access to Just commands: + +1. **Command Palette** (`Ctrl+Shift+P` or `Cmd+Shift+P`): + - Type "Tasks: Run Task" + - Select from available tasks: + - `PR Prep: Patch` (🟢 Green icon) + - `PR Prep: Minor` (🔵 Blue icon) + - `PR Prep: Major` (🔴 Red icon) + - `Code Quality: Format & Lint` + - `Dependencies: Update Lock` + +2. **Quick Access** (`Ctrl+Shift+P`): + - Type "Tasks: Run Build Task" for default formatting task + +3. **Terminal Menu**: Go to **Terminal** → **Run Task...** + +**Task Features:** +- 🎯 **Auto-focus**: Tasks automatically switch to terminal when running +- 🎨 **Color-coded**: Green for patch, blue for minor, red for major changes +- 📝 **Descriptive**: Each task shows what it does in the picker +- 🔗 **Integrated**: Seamless workflow between VS Code and terminal + ### Configuration Merlin uses a two-tier configuration system to separate application settings from personal user settings. diff --git a/pyproject.toml b/pyproject.toml index e08259a..2bf4cbb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "Merlin" -version = "1.2.2" +version = "1.2.3" description = "Merlin - Your AI Assistant with multi-agent architecture" readme = "README.md" requires-python = ">=3.14" @@ -18,6 +18,7 @@ dependencies = [ "urllib3>=2.0.0", "retry-requests>=2.0.0", "python-dotenv>=1.1.1", + "python-dateutil>=2.9.0.post0", ] [project.scripts] diff --git a/uv.lock b/uv.lock index 2b38599..ba05d87 100644 --- a/uv.lock +++ b/uv.lock @@ -724,11 +724,12 @@ wheels = [ [[package]] name = "merlin" -version = "1.2.2" +version = "1.2.3" source = { editable = "." } dependencies = [ { name = "dspy" }, { name = "openmeteo-requests" }, + { name = "python-dateutil" }, { name = "python-dotenv" }, { name = "requests" }, { name = "requests-cache" }, @@ -742,6 +743,7 @@ dependencies = [ requires-dist = [ { name = "dspy", specifier = ">=3.0.3" }, { name = "openmeteo-requests", specifier = ">=1.1.0" }, + { name = "python-dateutil", specifier = ">=2.9.0.post0" }, { name = "python-dotenv", specifier = ">=1.1.1" }, { name = "requests", specifier = ">=2.31.0" }, { name = "requests-cache", specifier = ">=1.1.0" }, @@ -1036,6 +1038,18 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" }, ] +[[package]] +name = "python-dateutil" +version = "2.9.0.post0" +source = { registry = "https://pypi.org/simple" } +dependencies = [ + { name = "six" }, +] +sdist = { url = "https://files.pythonhosted.org/packages/66/c0/0c8b6ad9f17a802ee498c46e004a0eb49bc148f2fd230864601a86dcf6db/python-dateutil-2.9.0.post0.tar.gz", hash = "sha256:37dd54208da7e1cd875388217d5e00ebd4179249f90fb72437e91a35459a0ad3", size = 342432, upload-time = "2024-03-01T18:36:20.211Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/ec/57/56b9bcc3c9c6a792fcbaf139543cee77261f3651ca9da0c93f5c1221264b/python_dateutil-2.9.0.post0-py2.py3-none-any.whl", hash = "sha256:a8b2bc7bffae282281c8140a97d3aa9c14da0b136dfe83f850eea9a5f7470427", size = 229892, upload-time = "2024-03-01T18:36:18.57Z" }, +] + [[package]] name = "python-dotenv" version = "1.2.1" @@ -1279,6 +1293,15 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/2e/5d/aa883766f8ef9ffbe6aa24f7192fb71632f31a30e77eb39aa2b0dc4290ac/ruff-0.14.2-py3-none-win_arm64.whl", hash = "sha256:ea9d635e83ba21569fbacda7e78afbfeb94911c9434aff06192d9bc23fd5495a", size = 12554956, upload-time = "2025-10-23T19:36:58.714Z" }, ] +[[package]] +name = "six" +version = "1.17.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/94/e7/b2c673351809dca68a0e064b6af791aa332cf192da575fd474ed7d6f16a2/six-1.17.0.tar.gz", hash = "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81", size = 34031, upload-time = "2024-12-04T17:35:28.174Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b7/ce/149a00dd41f10bc29e5921b496af8b574d8413afcd5e30dfa0ed46c2cc5e/six-1.17.0-py2.py3-none-any.whl", hash = "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", size = 11050, upload-time = "2024-12-04T17:35:26.475Z" }, +] + [[package]] name = "sniffio" version = "1.3.1"