feat: Live Runware model catalog sync — v0.15.0

Implements daily WP-Cron sync from Runware's /v1/models endpoint with 24h TTL caching,
on-demand AJAX refresh button in PRAdmin (Images settings), smart fallback logic, and
pricing merge from the authoritative cost table.

## Key additions:
- class-runware-model-catalog.php: ~300 lines, fetches/normalizes/caches models,
  exposes sync()/get_models()/get_last_synced_at()/is_stale() public API
- AJAX handler: prautoblogger_sync_runware_models_now with nonce + manage_options check
- Daily cron registered on activation, unscheduled on deactivation
- Caching strategy: <24h fresh → use cache; stale → sync; sync fails → fallback
- Pricing merge: costs from class-runware-image-pricing.php injected on every sync
- Fallback never returns empty array (hardcoded 15-model list)
- Unit tests: sync success/failure, stale cache, fallback behavior, pricing merge

## File changes:
- class-image-model-registry.php: refactored to delegate Runware to catalog,
  extracted get_runware_fallback_models() and get_openrouter_models()
- class-settings-fields-extended.php: added runware_catalog_sync field type
  for status display + Sync button in Images settings section
- class-prautoblogger.php: registered daily cron + AJAX hook
- class-activator.php: schedule prautoblogger_sync_runware_models on activation
- class-deactivator.php: unschedule on deactivation
- class-ajax-handlers.php: added on_ajax_sync_runware_models_now() handler
- class-runware-image-pricing.php: added @see cross-reference to catalog
- ARCHITECTURE.md: updated Runware row in External API Integrations table
- prautoblogger.php: version bump to 0.15.0
- CHANGELOG.md: detailed entry describing the fix and why it was necessary

Fixes the pattern from v0.13.8 and v0.14.0 where hardcoded Runware model
expansion without pricing class updates led to silent fallback-to-schnell bugs.
This commit is contained in:
peptiderepo
2026-04-26 04:27:17 +00:00
parent 61975d4551
commit def070d15a
12 changed files with 589 additions and 31 deletions

View File

@@ -116,6 +116,8 @@ class PRAutoBlogger {
$registry = $this->executor->get_model_registry();
add_action( 'prautoblogger_refresh_model_registry', array( $registry, 'refresh' ) );
// v0.15.0: daily Runware model catalog sync to keep the live model list fresh.
add_action( 'prautoblogger_sync_runware_models', array( new PRAutoBlogger_Runware_Model_Catalog(), 'sync' ) );
// Opik observability: async trace/span dispatch.
add_action(
@@ -179,6 +181,7 @@ class PRAutoBlogger {
add_action( 'wp_ajax_prautoblogger_test_connection', array( $this->ajax_handlers, 'on_ajax_test_connection' ) );
add_action( 'wp_ajax_prautoblogger_get_models', array( $this->ajax_handlers, 'on_ajax_get_models' ) );
add_action( 'wp_ajax_prautoblogger_refresh_models', array( new PRAutoBlogger_Model_Registry_Refresh( $this->ajax_handlers->get_registry() ), 'handle' ) );
t add_action( 'wp_ajax_prautoblogger_sync_runware_models_now', array( $this->ajax_handlers, 'on_ajax_sync_runware_models_now' ) );
$review_queue = new PRAutoBlogger_Review_Queue();
add_action( 'wp_ajax_prautoblogger_approve_post', array( $review_queue, 'on_ajax_approve_post' ) );