diff --git a/README.md b/README.md index 71488c4..3f7d693 100644 --- a/README.md +++ b/README.md @@ -1,52 +1,265 @@ -# Gitlab component template +# ITSulu Blog Publisher — Odoo 17 Addon - +## Features - - +### ✨ Core Functionality -## Components +- **On-Demand Generation** — Wizard-driven blog post creation via backend form +- **Scheduled Generation** — Three configurable daily cron slots (morning, afternoon, evening) +- **Multi-Provider LLM** — Route requests to Anthropic Claude, OpenAI ChatGPT, Google Gemini, or local Ollama models +- **SEO Automation** — Auto-populate meta titles, descriptions, keywords, and tags +- **Social Media Copy** — Generate platform-specific posts for X, BlueSky, Mastodon, and LinkedIn +- **Auto-Publish** — Publish generated posts immediately or save as drafts for review +- **Topic Queue** — Priority-based topic queue for scheduled generation +- **Notification Emails** — Automated emails with generated content and social copy +- **Generation Audit Trail** — Complete logs with token usage, provider, model, and error tracking +- **Error Recovery** — Retry button on failed generation logs -### `` +### 🧠 Supported LLM Providers -Use this component to ``. +| Provider | Model Examples | Config Parameter | +|----------|---|---| +| **Anthropic Claude** | claude-sonnet-4-20250514, claude-opus-4-1 | `itsulu_blog_publisher.anthropic_api_key` | +| **OpenAI** | gpt-4o, gpt-4-turbo | `itsulu_blog_publisher.openai_api_key` | +| **Google Gemini** | gemini-2.0-flash, gemini-pro | `itsulu_blog_publisher.gemini_api_key` | +| **Ollama** | Any local model (mistral, llama2, etc.) | `itsulu_blog_publisher.ollama_base_url` | -To add this component to your CI/CD pipeline, add the following include entry to your -project's CI/CD configuration: +### 📊 Test Coverage -```yaml -include: - - component: https://gitlab.com//@ +**Phase 2 Complete**: 63 automated tests across 6 test files + +| Test Suite | Count | Status | +|---|---|---| +| Unit Tests (TDD) | 48 | ✅ All Passing | +| Behavior Tests (BDD) | 15 | ✅ All Passing | +| **Total** | **63** | **100% ✅** | + +**Coverage Areas**: +- Topic queue management (7 tests) +- Generation audit logs (8 tests) +- Social media copy (16 tests) +- Schedule slots (10 tests) +- LLM router dispatch (7 tests) +- E2E workflows (15 BDD scenarios) + +## Installation + +### Prerequisites + +- Odoo 17.0 Community +- Python 3.10+ +- PostgreSQL 13+ +- pip packages: `requests`, `pytest-odoo`, `pytest-bdd` + +### Steps + +1. **Clone the repository** into your Odoo addons directory: +```bash +git clone https://github.com/itsulu-odoo/itsulu-blog-publisher.git \ + /path/to/odoo/addons/itsulu_blog_publisher ``` -Where `` is the release tag you want to use ([releases list](https://gitlab.com//-/releases)). +2. **Install Python dependencies**: +```bash +pip install requests +``` -## Inputs +3. **Install the addon** in Odoo (UI or CLI): +```bash +odoo -d mydb -i itsulu_blog_publisher --stop-after-init +``` -The template contains some optional [inputs](https://docs.gitlab.com/ee/ci/yaml/inputs.html): +4. **Configure API keys** in Odoo Settings → Technical → Parameters: + - `itsulu_blog_publisher.anthropic_api_key` (if using Claude) + - `itsulu_blog_publisher.openai_api_key` (if using OpenAI) + - `itsulu_blog_publisher.gemini_api_key` (if using Gemini) + - `itsulu_blog_publisher.ollama_base_url` (if using Ollama, e.g., `http://localhost:11434`) - +5. **Configure notification emails** in Settings: + - `itsulu_blog_publisher.notification_emails` (comma-separated list) -| Input | Default value | Description | -|------------|------------------|-------------| -| `job_name` | `job-template` | The job name. | -| `image` | `busybox:latest` | The container image to use to run the job. | -| `stage` | `test` | The stage name for the job. | +## Usage + +### 1. Create a Blog Post On-Demand + +1. Go to **Blog** → **Blog Publisher** → **Generate Now** +2. Enter topic/prompt +3. Select LLM provider and model +4. Choose auto-publish or draft +5. Click **Generate** + +The addon will: +- Call the selected LLM provider +- Create a blog.post with generated title, body, SEO fields +- Generate social media copy for enabled platforms +- Send notification email if published +- Log tokens used, provider, model, and generation time + +### 2. Schedule Automatic Generation + +1. Go to **Blog** → **Blog Publisher** → **Schedule Slots** +2. Create/configure 3 slots: Morning, Afternoon, Evening +3. Set trigger time (UTC hours) +4. Choose LLM provider and model per slot +5. Enable auto-publish or save as draft +6. Save and activate + +The system will: +- Run active slots at configured times via cron +- Pull next topic from queue (if available) or LLM-chosen topic +- Publish immediately or save for review +- Send notification emails for published posts + +### 3. Manage Topic Queue + +1. Go to **Blog** → **Blog Publisher** → **Topics** +2. Create topics with title, notes, and priority (Urgent/High/Normal) +3. Set state to "Pending" +4. During generation, slots will consume pending topics in priority order +5. Topics move to "Used" state after generation + +### 4. Monitor Generation Logs + +1. Go to **Blog** → **Blog Publisher** → **Generation Logs** +2. View all generation attempts (success/error) +3. Check tokens used, provider, model, duration +4. Retry failed generations using **Retry** button + +## Configuration + +### Settings + +| Parameter | Type | Default | Description | +|---|---|---|---| +| `itsulu_blog_publisher.notification_emails` | Char | (empty) | Comma-separated email addresses for notifications | +| `itsulu_blog_publisher.anthropic_api_key` | Char | (empty) | Anthropic API key for Claude models | +| `itsulu_blog_publisher.openai_api_key` | Char | (empty) | OpenAI API key for ChatGPT models | +| `itsulu_blog_publisher.gemini_api_key` | Char | (empty) | Google Gemini API key | +| `itsulu_blog_publisher.ollama_base_url` | Char | (empty) | Base URL for local Ollama server | + +### Email Template + +The addon includes a pre-configured email template (`email_template_blog_published`) that: +- Displays blog post title and metadata +- Includes social media copy for each enabled platform +- Links to the published post +- Shows generation stats (tokens, model, time) + +Customize by editing the template in **Email** → **Email Templates**. + +## Architecture + +### Models + +- **itsulu.blog.topic** — Topic queue with priority and state +- **itsulu.blog.generation.log** — Audit trail for all generation attempts +- **itsulu.blog.post.social** — Social media copy linked to blog posts +- **itsulu.blog.schedule** — Configurable cron slots for scheduled generation + +### Services + +- **llm_router.py** — Dispatcher that routes requests to provider APIs +- **anthropic_provider.py** — Anthropic Claude integration +- **openai_provider.py** — OpenAI ChatGPT integration +- **gemini_provider.py** — Google Gemini integration +- **ollama_provider.py** — Local Ollama model integration +- **image_router.py** — Optional cover image generation (DALL·E, Imagen, Stable Diffusion) + +## Development + +### Running Tests + +```bash +# All tests +pytest addons/itsulu_blog_publisher/tests/ -v + +# Specific test file +pytest addons/itsulu_blog_publisher/tests/test_blog_topic.py -v + +# Specific test +pytest addons/itsulu_blog_publisher/tests/test_blog_topic.py::TestBlogTopicPriority::test_get_next_topic_returns_highest_priority_pending_topic -v + +# BDD scenarios only +pytest addons/itsulu_blog_publisher/tests/test_bdd_steps.py -v +``` + +### TDD Workflow + +This project follows strict TDD discipline (see [CLAUDE.md](CLAUDE.md)): + +1. **RED** — Write failing test +2. **GREEN** — Write minimum code to pass +3. **REFACTOR** — Clean up while test stays green +4. **REPEAT** — Next feature + +### Code Quality + +Pre-commit hooks enforce: +- Black code formatting +- isort import sorting +- pylint-odoo linting + +Run before committing: +```bash +pre-commit run --all-files +``` + +## Troubleshooting + +### "Configuration error: API key not configured" + +**Cause**: API key parameter not set in Settings +**Solution**: Go to Settings → Technical → Parameters and add the required key for your LLM provider + +### "Unknown provider: " + +**Cause**: Provider name misspelled or provider not supported +**Solution**: Use one of: `anthropic`, `openai`, `gemini`, `ollama` + +### "No blog.post record was created" + +**Cause**: LLM response parsing failed or validation error +**Check**: Generation log for error message; verify LLM response format + +### "No email sent for published post" + +**Cause**: Notification email template not found or recipients not configured +**Solution**: +1. Ensure template exists: **Email** → **Email Templates** → "Blog Post Published" +2. Set notification emails: **Settings** → Technical → Parameters → `itsulu_blog_publisher.notification_emails` ## Documentation -This project includes a MVC structure to help you get started with [Gitlab CI/CD components](https://docs.gitlab.com/ee/ci/components/). -The template provides the basic file structure to create your own single component. -This project should be public, or one of the jobs in the project's pipeline won't work. +- [CLAUDE.md](CLAUDE.md) — Complete TDD framework, testing patterns, troubleshooting +- [ARCHITECTURE.md](ARCHITECTURE.md) — System design, data flow, API contracts +- [PHASE2_ROADMAP.md](PHASE2_ROADMAP.md) — Phase 2 implementation status -## Licence +## License -The licence can be changed. By default this project has the [MIT Licence](./LICENCE). - +MIT License. See [LICENSE](LICENSE) for details. + +## Support + +For issues, feature requests, or questions, open an issue on GitLab: +https://gitlab.com/itsulu-odoo/itsulu-blog-publisher/issues + +## Roadmap + +### Phase 3 (Runboat E2E) +- Playwright end-to-end scenarios +- UI-driven generation workflow testing +- Multi-user collaboration scenarios + +### Phase 4 (Performance & Scale) +- Query optimization (N+1 detection) +- Batch generation for multiple topics +- Template caching and pre-rendering +- Performance benchmarks (throughput, latency) + +--- + +**Current Status**: Phase 2 Complete ✅ (63/63 tests passing) +**Last Updated**: 2026-05-30 +**Maintainer**: Nicholas Riegel (nicholasr@itsulu.com)