diff --git a/ARCHITECTURE.md b/ARCHITECTURE.md index 6666d8b..822c62e 100755 --- a/ARCHITECTURE.md +++ b/ARCHITECTURE.md @@ -152,8 +152,8 @@ prautoblogger/ │ │ │ ├── services/ │ │ ├── interface-model-registry.php # Contract for provider-specific model registries -│ │ ├── class-openrouter-model-registry.php # Fetches, caches, queries the OpenRouter model list -│ │ ├── class-openrouter-model-normalizer.php # Maps raw OpenRouter data → standardized record shape +│ │ ├── class-open-router-model-registry.php # Fetches, caches, queries the OpenRouter model list +│ │ ├── class-open-router-model-normalizer.php # Maps raw OpenRouter data → standardized record shape │ │ └── (Phase 3: class-cloudflare-workers-ai-model-registry.php) │ │ │ ├── frontend/ @@ -446,7 +446,7 @@ Reddit rejected our OAuth API application (April 2026). We initially switched to ### #18: OpenRouter model registry — daily refresh, WP option + transient cache, zero-coupling -The admin model picker (v1) needs to list OpenRouter models with pricing and capabilities. We fetch `https://openrouter.ai/api/v1/models` (free, unauthenticated) once daily and store the normalized payload in a WP option fronted by a 24h transient. On stale-and-fetch-fails, we serve last-good + surface a warning. The registry class (`class-openrouter-model-registry.php`) takes all config via constructor (option name, transient name, endpoint URL) — no PRAUTOBLOGGER_* constants inside the class body. Phase 2 lifts it into a shared Composer package with zero internal edits. Phase 3 adds a parallel `Cloudflare_WorkersAI_Model_Registry` behind the same interface. Capability vocabulary: `text→text`, `text+image→text`, `text+audio→text`, `text→image`, `text→audio`, `text→video`, `text→embedding`. Cost: $0/month. +The admin model picker (v1) needs to list OpenRouter models with pricing and capabilities. We fetch `https://openrouter.ai/api/v1/models` (free, unauthenticated) once daily and store the normalized payload in a WP option fronted by a 24h transient. On stale-and-fetch-fails, we serve last-good + surface a warning. The registry class (`class-open-router-model-registry.php`) takes all config via constructor (option name, transient name, endpoint URL) — no PRAUTOBLOGGER_* constants inside the class body. Phase 2 lifts it into a shared Composer package with zero internal edits. Phase 3 adds a parallel `Cloudflare_WorkersAI_Model_Registry` behind the same interface. Capability vocabulary: `text→text`, `text+image→text`, `text+audio→text`, `text→image`, `text→audio`, `text→video`, `text→embedding`. Cost: $0/month. ### #16: Image generation via Cloudflare Workers AI (FLUX.1), direct (not via AI Gateway) The image-generation layer (started 2026-04-15, tracked in `convo/prautoblogger/threads/2026-04-image-pipeline/`) uses FLUX.1 [schnell] on Cloudflare Workers AI as its default model, chosen for its ~$0.0011/MP cost and 2–3 sec latency. FLUX.1 [dev] is a ~4× cost upgrade exposed as a dropdown for specific posts that warrant it. Calls go directly to `https://api.cloudflare.com/client/v4/accounts/{id}/ai/run/@cf/black-forest-labs/...`, *not* through the Cloudflare AI Gateway that we use for OpenRouter — the gateway route to Workers AI currently 403s (pre-existing open issue). The provider lives behind `PRAutoBlogger_Image_Provider_Interface`, so the decision is trivially reversible: switching to a different image API (DALL-E, Replicate, a future AI Gateway route) is a new class implementation plus a one-line swap in the pipeline wiring. Trade-off: we run two different Cloudflare integration paths (gateway for OpenRouter LLMs, direct for Workers AI images) until the gateway route stabilizes — minor cognitive overhead, zero functional downside. diff --git a/CHANGELOG.md b/CHANGELOG.md index 98a16bb..349e733 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -40,8 +40,8 @@ and this project uses [Semantic Versioning](https://semver.org/). list (`/api/v1/models` — free, unauthenticated). Daily refresh via the existing `prautoblogger_daily_generation` cron hook with 12h idempotency. - `includes/services/interface-model-registry.php` — Phase 3-aware contract. - - `includes/services/class-openrouter-model-registry.php` — fetch + cache + query. - - `includes/services/class-openrouter-model-normalizer.php` — raw → standardized shape. + - `includes/services/class-open-router-model-registry.php` — fetch + cache + query. + - `includes/services/class-open-router-model-normalizer.php` — raw → standardized shape. - Capability vocabulary: `text→text`, `text+image→text`, `text→embedding`, etc. - Zero-coupling: no PRAUTOBLOGGER_* constants inside the class — Phase 2 lift into a shared Composer package requires only a namespace rename. diff --git a/includes/services/class-openrouter-model-normalizer.php b/includes/services/class-open-router-model-normalizer.php similarity index 98% rename from includes/services/class-openrouter-model-normalizer.php rename to includes/services/class-open-router-model-normalizer.php index db5bf9b..1086867 100644 --- a/includes/services/class-openrouter-model-normalizer.php +++ b/includes/services/class-open-router-model-normalizer.php @@ -11,7 +11,7 @@ declare(strict_types=1); * Triggered by: PRAutoBlogger_OpenRouter_Model_Registry::refresh(). * Dependencies: None — pure data transformation, no I/O. * - * @see services/class-openrouter-model-registry.php — Sole consumer. + * @see services/class-open-router-model-registry.php — Sole consumer. * @see interface-model-registry.php — Defines the normalized record shape. * @see ARCHITECTURE.md — Capability vocabulary. */ diff --git a/includes/services/class-openrouter-model-registry.php b/includes/services/class-open-router-model-registry.php similarity index 98% rename from includes/services/class-openrouter-model-registry.php rename to includes/services/class-open-router-model-registry.php index 8dcb62a..15611a0 100644 --- a/includes/services/class-openrouter-model-registry.php +++ b/includes/services/class-open-router-model-registry.php @@ -17,7 +17,7 @@ declare(strict_types=1); * PRAutoBlogger_OpenRouter_Model_Normalizer. * * @see interface-model-registry.php — Interface. - * @see class-openrouter-model-normalizer.php — Normalization logic. + * @see class-open-router-model-normalizer.php — Normalization logic. * @see class-prautoblogger.php — Hooks the refresh action. * @see ARCHITECTURE.md — AI Model Registries section. */ diff --git a/includes/services/interface-model-registry.php b/includes/services/interface-model-registry.php index 634f32b..a527bd4 100644 --- a/includes/services/interface-model-registry.php +++ b/includes/services/interface-model-registry.php @@ -4,7 +4,7 @@ declare(strict_types=1); /** * Contract for a provider-specific AI model registry. * - * Phase 1 (v1): single implementation for OpenRouter (`class-openrouter-model-registry.php`). + * Phase 1 (v1): single implementation for OpenRouter (`class-open-router-model-registry.php`). * Phase 3: a second implementation wraps Cloudflare Workers AI FLUX model data. A * higher-level dispatcher iterates registered registries, calls each with the same * capability, and unions the results — the per-registry interface stays unchanged. @@ -19,7 +19,7 @@ declare(strict_types=1); * (commit 3), daily cron via the main plugin loader. * Dependencies: None at interface level — implementations wrap an HTTP API. * - * @see services/class-openrouter-model-registry.php — Default implementation. + * @see services/class-open-router-model-registry.php — Default implementation. * @see admin/fields/class-openrouter-model-field.php — Field renderer that queries this interface. * @see ARCHITECTURE.md — AI Model Registries section. */