Commit Graph

34 Commits

Author SHA1 Message Date
peptiderepo
14f1cf0351 Fix broken View link on idea generation complete
View URL was using adminUrl (wp-admin/?p=123) instead of siteUrl.
Now uses home_url() for the frontend permalink.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 02:11:32 +07:00
peptiderepo
0cde08757b Add generate-from-idea button to Ideas browser (v0.6.0)
Each idea row now has a Generate button that triggers single-article
generation via a background WP-Cron job. Skips the pipeline's collect/
analyze/score steps and goes straight to Article_Worker with the
selected idea. Button shows real-time stage updates via per-idea status
transients, then swaps to Edit/View links with cost on completion.
Respects the generation lock to prevent concurrent runs.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 02:01:25 +07:00
peptiderepo
327cdc08d9 feat: add Ideas browser admin page (v0.5.1)
New submenu page showing all article ideas from the content analyzer.
Displays title, type, relevance score, frequency, key points, and
keywords with type filtering and pagination. Gives live visibility
into the idea pipeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 00:34:31 +07:00
peptiderepo
c03bdfb69c feat: add LLM Deep Research source provider (v0.5.0)
New data source that sends a configurable research prompt to a
reasoning-capable model (Grok 4.1 Fast, DeepSeek-R1, etc.) to identify
trending topics, content gaps, and emerging questions. Findings feed
into the content analyzer alongside Reddit data, combining real-time
community signals with deep knowledge-base research.

New admin settings: Research Model picker, Research Prompt textarea,
and LLM Deep Research toggle in Enabled Sources.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-20 00:05:15 +07:00
peptiderepo
39570e4586 feat: add OpenRouter reasoning mode support (v0.4.9)
Enables reasoning-capable models (Grok 4.1 Fast, DeepSeek-R1, etc.)
via new admin settings: Enable Reasoning toggle and Reasoning Effort
selector. Provider auto-injects reasoning params when enabled; callers
can override per-call via options array. Response parser captures
reasoning_tokens and reasoning_content for visibility.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 23:54:26 +07:00
peptiderepo
36d45fd1ed feat: cost breakdown popover on post list (v0.4.7)
Cost column is now clickable — hovering shows a per-step breakdown
with stage name, model, token count, and cost for every LLM call.
Pure CSS popover, no JS dependency.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 22:41:47 +07:00
peptiderepo
7d61c8c76d feat: add Image B toggle to disable second image generation (v0.4.6)
New toggle in Images settings controls whether the source-data-based
second image is generated. Disabling saves one image gen call + one
LLM prompt rewrite per article. Defaults to enabled.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 22:08:06 +07:00
peptiderepo
ca8fe1bfba feat: add Analysis & Editor Instructions settings (v0.4.5)
Two new textareas in Content settings let admins provide custom
instructions for the analysis and chief editor LLM stages, matching
the Writing Instructions field added in v0.4.4. All three pipeline
stages now have user-controllable system prompt customization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 17:13:49 +07:00
peptiderepo
b0cc93669d feat: add Writing Instructions setting for LLM system prompt (v0.4.4)
New textarea in Content settings lets admins provide custom instructions
appended to the writer's system prompt. Steers style, structure, voice,
and formatting without editing code.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 17:01:54 +07:00
peptiderepo
3e1e5efe09 fix: word-wrap title column and tighten custom column widths (v0.4.2)
Title column was compressed to ~30px making post titles unreadable.
Give title 35% min-width with word-wrap, trim model columns to 100px
with text-overflow ellipsis, cost column to 55px.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 14:27:49 +07:00
peptiderepo
499dcc931d fix: set minimum column widths for model/cost columns
Columns were crushed to 1-char width by WordPress's auto-layout.
Added 120px for model columns and 60px for cost.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 14:23:07 +07:00
peptiderepo
0a15e266cd feat: add Writing Model, Image Model, and Cost columns to posts list
v0.4.1 — Three new columns on the WordPress Posts admin page showing
which LLM wrote each article, which model generated its featured image,
and the total API cost. Model names shortened for compact display with
full ID in tooltip. Cost queries the generation_log table, skipping
the DB hit entirely for non-generated posts.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-19 14:21:02 +07:00
peptiderepo
c8595e05de Fix duplicate image, remove hardcoded model references
Three fixes in one:

1. Duplicate image: prepend_caption_to_post() was embedding the full
   image + caption as a <figure> block, but the theme already displays
   the featured image. Now only the caption text is prepended — no
   second copy of the image.

2. Hardcoded model names: removed all FLUX.1/FLUX.2 references from
   model-agnostic code (pipeline, prompt builder, sideloader, OpenRouter
   provider, interface, admin labels). The Cloudflare provider still
   references FLUX since it specifically wraps that model family.

3. Test alignment: OpenRouterImagePricingTest was asserting against
   removed models (flux-2-pro, seedream). Updated to match current
   COST_PER_IMAGE entries (Gemini Flash, GPT-5 Image).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 16:08:36 +07:00
peptiderepo
862d7e40e6 fix: update image models, handle upstream errors in HTTP 200
Three issues found in activity logs:

1. Image model IDs stale — FLUX and Seedream removed from OpenRouter.
   Updated to current models: Gemini 2.5/3.1 Flash Image, Gemini 3 Pro
   Image, GPT-5 Image/Mini. Default changed to gemini-2.5-flash-image.

2. openrouter/free router wraps upstream 429 errors in HTTP 200 body
   with error object. Both text and image response parsers now detect
   this pattern and surface a proper RuntimeException.

3. Image request used modalities: ["image"] but Gemini needs
   ["image", "text"]. Updated to include both.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 10:47:05 +07:00
peptiderepo
4cc9b39693 fix: model picker shows 0 image models — capability mismatch in field renderer
The field renderer still checked for the old 'cloudflare_image' capability
but the setting was changed to 'image_generation'. Updated to resolve
model name/price from the shared get_image_models() list. Bumped to
v0.2.5 to bust browser JS/CSS cache.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 09:23:39 +07:00
peptiderepo
0a68741945 feat: add OpenRouter image provider for higher-quality image generation
Replaces Cloudflare Workers AI (FLUX.1 schnell) as the default image
provider with OpenRouter, which offers FLUX.2 Pro, Seedream 3.0,
Gemini Flash Image, and GPT Image 1 at comparable or better pricing.

- New provider class (3-file split: provider, pricing, support) reuses
  the existing OpenRouter API key and Cloudflare AI Gateway
- Admin settings: new Image Provider dropdown (openrouter/cloudflare),
  model picker shows all available image models from both providers
- Image pipeline auto-selects the configured provider at construction
- Cost logging now uses actual model name instead of hardcoded flux-1-schnell
- Default model changed to black-forest-labs/flux-2-pro ($0.03/image)
- Unit tests for pricing resolution and provider response parsing

Cost impact: FLUX.2 Pro at $0.03/image vs schnell at $0.0007/image —
~43x more expensive per image, but dramatically better quality. At 2
images/article × 1 article/day = ~$1.80/month. Seedream 3.0 ($0.003)
available as a budget alternative.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 09:19:13 +07:00
peptiderepo
5b5286ca5b fix: remove deprecated flux-1-dev model from Cloudflare image config
FLUX.1 [dev] was removed from Cloudflare Workers AI in April 2026,
returning HTTP 400 "No route for that URI". This removes it from the
static model picker list and pricing calculations. Any saved setting
referencing flux-1-dev gracefully falls through to flux-1-schnell
via the null-coalesce in resolve_model().

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 07:48:18 +07:00
peptiderepo
49aee0b446 fix: add Cloudflare token to encrypted fields list (fixes 401 on image gen)
prautoblogger_cloudflare_ai_token was missing from the $encrypted array
in sanitize_field(), so the token was stored as plaintext. On read,
decrypt() failed on the non-encrypted value and returned empty string,
causing HTTP 401 on every Cloudflare Workers AI call.

Fix: add the field to the encrypted list so future saves encrypt it.
Also add legacy plaintext detection in get_api_token() and the validator
so the existing DB value works immediately and gets auto-encrypted on
first use.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 07:24:01 +07:00
peptiderepo
1c1e861f2e feat: extend model picker to image model (Cloudflare FLUX)
Apply the same interactive model picker UI to the image model field.
Since Cloudflare models don't come from OpenRouter's registry, the
two FLUX models are embedded as static data in the page config and
the JS popup renders cost-per-image instead of token pricing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 03:06:17 +07:00
peptiderepo
31f303a831 feat: interactive model picker with searchable popup and pricing
Replace plain text inputs for analysis/writing/editor model fields
with a rich model picker that fetches the OpenRouter model registry
and displays a searchable popup with model name, provider, input/output
pricing per 1M tokens, and context window. Also extracts source status
and model field renderers into dedicated field classes to keep
class-admin-page.php under the 300-line cap.

New files:
- assets/js/model-picker.js — popup UI with search, filtering, caching
- assets/css/model-picker.css — popup styles matching admin design system
- includes/admin/fields/class-open-router-model-field.php — server render
- includes/admin/fields/class-source-status-field.php — extracted field

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 02:53:40 +07:00
peptiderepo
0e44c52ad8 feat: add AJAX endpoint for retroactive image generation
Adds wp_ajax_prautoblogger_generate_image so images can be generated
for existing posts that were published before image gen was enabled
or fixed. Uses set_time_limit(120) to handle the Cloudflare API
latency that caused fatals when run via Code Snippets init hook.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-18 00:39:10 +07:00
peptiderepo
6cf8ff62fc fix: sanitize JSON-encoded array fields without mangling
The sanitize_field() fallthrough for JSON fields starting with '['
called sanitize_text_field() which escaped quotes and brackets,
breaking json_decode() on read. This caused subreddits, topic
exclusions, and enabled sources to always read back as empty arrays.

Now properly decodes, sanitizes each item, and re-encodes as clean
JSON for all three input paths: PHP array, JSON string, or CSV.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 23:20:52 +07:00
peptiderepo
b6363d8474 fix: add Cloudflare AI token to encryption list in sanitize_field
The $encrypted array was missing prautoblogger_cloudflare_ai_token,
so saving through the admin UI stored plaintext while the read path
called decrypt() — which would fail on non-encrypted data.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 22:44:53 +07:00
peptiderepo
8de7b7f68a refactor: split settings-fields into core + extended (264/157 lines)
Extract schedule, publishing, analytics, and images field definitions
into PRAutoBlogger_Settings_Fields_Extended. Core class retains sections
and API/Models/Content/Sources fields, merging extended fields via
get_fields(). Both files well under 300-line limit.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-17 02:53:01 +07:00
peptiderepo
49d094b4f8 Refactor: Split cost reporting into separate class
Extract read-only reporting methods from PRAutoBlogger_Cost_Tracker into a new
PRAutoBlogger_Cost_Reporter class. This reduces Cost_Tracker from 313 to 206
lines and Reporter to 141 lines, both under the 300-line cap.

Changed files:
- Create includes/core/class-cost-reporter.php with reporting methods:
  * get_monthly_spend(): float
  * get_daily_spend(int $days = 30): array
  * get_spend_by_stage(string $start_date, string $end_date): array
  * get_budget_utilization(): float

- Update includes/core/class-cost-tracker.php:
  * Remove reporting methods
  * Update is_budget_exceeded() and would_exceed_budget() to use Cost_Reporter
  * Keep get_current_run_cost() (tracks current pipeline run only)
  * Add @see cross-reference to Cost_Reporter

- Update templates and admin classes to instantiate Cost_Reporter:
  * templates/admin/metrics-page.php
  * templates/admin/settings-page.php
  * includes/admin/class-admin-notices.php
  * includes/admin/class-dashboard-widget.php

- Split tests/unit/Core/CostTrackerTest.php:
  * Create tests/unit/Core/CostReporterTest.php for reporter methods
  * Keep run ID and budget enforcement tests in CostTrackerTest

Autoloader automatically discovers PRAutoBlogger_Cost_Reporter class.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 20:27:57 +07:00
peptiderepo
2e41c3f2f6 feat(images): wire image pipeline into article flow (commit 1b) (#14)
Completes the image + A/B experiment workstream by integrating
image generation into the post publishing pipeline.

New classes:
- class-image-pipeline.php: Orchestrates A/B generation (article-driven
  Image A → featured; source-driven Image B → post meta). Each image
  independently fallible; article publishes even if both fail.
- class-image-prompt-builder.php: Synthesizes visual prompts from article
  title+content and Reddit source data. Appends CEO-locked 90s infomercial
  style suffix. Keeps prompts concise for FLUX.1 quality.
- class-image-media-sideloader.php: Downloads image bytes, creates temp
  file, sideloads via media_handle_sideload(), sets alt text and metadata,
  cleans up temp files.

Changes to existing files:
- Publisher.attach_generated_images(): Runs image pipeline post-creation,
  sets _thumbnail_id (Image A) and _prautoblogger_image_b_id (Image B).
  Errors logged but don't block post publication.
- Settings: prautoblogger_image_enabled (toggle, default off).

Tests:
- ImagePipelineTest.php: Orchestration, cost tracking, graceful failures.
- ImagePromptBuilderTest.php: Prompt generation, length limits.

Docs:
- ARCHITECTURE.md: New step 6b in data flow, new files in file tree.
- CHANGELOG.md: Commit 1a/1b breakdown.

Co-authored-by: peptiderepo <peptiderepo@users.noreply.github.com>
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-16 16:51:22 +07:00
peptiderepo
8e6b2d528f Commit 1a: Cloudflare Workers AI image provider + pricing + validator (#9)
Implements image-provider interface + Cloudflare Workers AI adapter with pricing and validator. Independent QA verdict: APPROVE on 52fd11e (qa-reviews/prautoblogger/2026-04-15-52fd11e2ce97dd9e659df5cc87ec1382a668bec1.md). All 4 CTO blockers resolved (PHPUnit retry mocks, XSS hardening on error strings, PHPCS on new files, 300-line cap via support-class extraction). PHPCS backlog (586 errors across 38 pre-existing files) remains on continue-on-error; Workstream C material.
2026-04-15 18:25:46 +07:00
peptiderepo
428a3d5861 feat: optional Cloudflare AI Gateway proxy for OpenRouter calls
Adds two WP options: prautoblogger_ai_gateway_base_url (routes OpenRouter calls through a Cloudflare AI Gateway when set to an https:// URL; empty = direct, the default) and prautoblogger_ai_gateway_cache_ttl (seconds for cf-aig-cache-ttl response caching; 0 = off).

The gateway is a transparent OpenRouter-compatible proxy, so no consuming class, no provider abstraction, and no response-parsing path changes. The http_api_curl belt-and-suspenders Authorization filter is rescoped to the configured upstream host so it still runs under gateway.ai.cloudflare.com.

Rationale: leverages existing Cloudflare infrastructure to satisfy the CTO cost-control rules (caching, cost tracking, rate limiting, fallback) without building equivalent middleware in-plugin. Fully opt-in and reversible from the admin UI.

Docs: ARCHITECTURE.md options + integrations tables updated; key decision #15 added. Uninstall is unaffected (wildcard prautoblogger_% delete).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-04-15 01:41:30 +07:00
peptiderepo
b21d102afb feat: v0.2.2 — CI hardening, remove dead stubs, strengthen tests
Address CTO audit findings for PRAutoBlogger:
- CI pipeline now runs PHPCS (WordPress standards) and PHPUnit before deploy
- Removed TikTok/Instagram/YouTube stub providers (dead code, not registered)
- Rewrote PublisherTest with real behavioral assertions (post_status, metadata,
  taxonomy, log linking, hooks) instead of method-existence checks
- Added cross-system LLM budget coordination docs to ARCHITECTURE.md
- Bumped version to 0.2.2

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 22:41:10 +07:00
peptiderepo
d9985f6dc2 refactor: remove PullPush.io, use Reddit RSS as primary data source
PullPush.io index was frequently stale/unavailable. Reddit RSS/Atom feeds
work reliably from datacenter IPs (Hostinger) where .json gets 403.

- RSS is now the primary source for post fetching
- .json endpoints kept as fallback for posts and sole source for comments
- Deleted class-pull-push-client.php
- Updated admin UI, test connection handler, docs, and ARCHITECTURE.md

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 14:00:55 +07:00
peptiderepo
b5cbbef804 feat: v0.2.1 — fix encryption, diverse multi-topic generation, UX fixes
- Rewrite encryption with "enc:" prefix to permanently eliminate
  the double-encryption bug on settings save
- Add one-time migration to clear legacy non-prefixed encrypted values
- Rewrite content analyzer prompts to request N distinct diverse topics
  across 5 categories (question, complaint, comparison, news, guide)
- Pass target_count*2 from pipeline to analyzer for headroom
- Add skip_dedup flag so manual Generate Now always produces content
- Generate Now button now sends force=1 to clear stale locks
- Rename OpenRouter provider files to PSR-4 convention (hyphenated)
- Switch default models to google/gemini-2.5-flash-lite
- Clean up reddit_debug log channel to standard 'reddit'
- Bump version to 0.2.1

Cost: ~$0.003/article with Gemini 2.0 Flash, ~34s pipeline.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 13:36:36 +07:00
peptiderepo
726b378a52 feat: v0.2.0 — PullPush.io admin UI, version bump, deploy fix
- Remove Reddit OAuth fields (Client ID/Secret) from admin settings
- Add source status indicator showing PullPush.io + .json fallback health
- Add configurable cache TTL, time window, and posts-per-subreddit settings
- Update Test Connections to report which Reddit source is active
- Bump version 0.1.0 → 0.2.0 across plugin header, constant, and readme
- Switch deploy pipeline from zip/REST API to SSH rsync with --delete
- Add LiteSpeed cache purge step to prevent stale OPcache after deploy
- Update CHANGELOG.md and readme.txt for 0.2.0 release

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-12 10:59:35 +07:00
Terence Ong
88d674d679 Initial commit: PRAutoBlogger v0.1.0 with frontend posts widget 2026-04-10 23:33:42 +07:00
Terence Ong
68c6f67bcf Initial commit: AutoBlogger v0.1.0
WordPress plugin that auto-researches topics from Reddit, generates
SEO-optimized articles via OpenRouter LLMs, runs them through a chief
editor agent, and publishes on a daily schedule.

Includes:
- Full generation pipeline (collect → analyze → score → generate → review → publish)
- Cost tracking and budget enforcement
- Admin UI: settings, review queue, metrics, activity log
- CI/CD pipeline (GitHub Actions → WordPress REST deploy)
- Unit test suite (PHPUnit + Brain Monkey)
- Structured logging with configurable verbosity

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-04-10 16:10:27 +07:00