feat(v3.12.0): media pipeline, AI image generation, capability probe, companion v2.9.0
Some checks failed
Release / Test before release (push) Has been cancelled
Release / Publish to PyPI (push) Has been cancelled
Release / Publish to Docker Hub (push) Has been cancelled
Release / Create GitHub Release (push) Has been cancelled

Three-month batch sync from internal repo (~80 commits) covering Tracks F.5a, F.7e, F.8, F.17, F.18, F.X.

WordPress media pipeline
- Pillow-based optimization, AI image generation (OpenAI / Stability / Replicate / Google Nano Banana / OpenRouter), chunked + resumable uploads, bulk delete/reassign, idempotent retries.

Capability discovery (F.7e)
- Per-site credential probe + adapters for WordPress / WooCommerce / Gitea, tier-fit unions granted ∪ roles, capability badge UI with HTMX partial re-check, install hint in every companion-unreachable error.

Companion plugin overhaul
- Renamed wordpress-plugin/airano-mcp-seo-bridge → wordpress-plugin/airano-mcp-bridge.
- Eight new endpoints: /capabilities, /bulk-meta, /export, /cache-purge, /transient-flush, /site-health, /audit-hook, /upload-and-attach.
- wp.org Plugin Check pass: i18n, WP_Filesystem, scheme allowlist on audit-hook URL.

Other
- Gitea ergonomics (F.17): batch files, tree, search, compare, releases, fork.
- Opportunistic bcrypt upgrade for legacy SHA-256 admin keys (F.8).
- n8n refactor: structured errors, capability probe, missing tools backfilled.
- Idempotency-Key dedup for AI media upload retries; WP client fast-fails on unreachable sites.

Docs
- README + CLAUDE.md drop the fixed "633 tools" claim. The total grows with each release; per-plugin approximations + dashboard-surfaced counts replace it.
- Tools/Tests badges removed in favour of "Plugins: 10".

Deployment
- PyPI mirror chain, optional BUILD_HTTP_PROXY, Alpine→Yandex apk mirror, Debian-slim Plan-B Dockerfile, mirror.gcr.io variant.

CI
- Black + Ruff clean on Python 3.12; pytest tests/ green.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-04-25 16:25:58 +02:00
parent 788439e377
commit f203ca88de
140 changed files with 23802 additions and 2253 deletions

View File

@@ -57,6 +57,7 @@ from core import (
get_tool_registry,
set_api_key_context,
)
from core.capability_probe import api_site_capabilities, api_site_capabilities_badge
from core.dashboard.routes import (
# F.7b: Per-site tool visibility
api_bulk_toggle_site_tools,
@@ -74,6 +75,11 @@ from core.dashboard.routes import (
api_save_setting,
api_scope_presets,
api_set_site_tool_scope,
# F.18.8: Provider Keys Dashboard UI
api_site_provider_default_model,
api_site_provider_keys_delete,
api_site_provider_keys_list,
api_site_provider_keys_set,
api_test_site,
api_update_site,
# E.2: OAuth Social Login routes
@@ -130,6 +136,7 @@ from core.i18n import detect_language, get_all_translations
# OAuth and CSRF (Phase E)
from core.oauth import get_csrf_manager
from plugins.ai_image.providers.openrouter import api_openrouter_models
# Configure logging
LOG_LEVEL = os.getenv("LOG_LEVEL", "INFO").upper()
@@ -4743,9 +4750,17 @@ def create_multi_endpoint_app(transport: str = "streamable-http"):
if hm:
await hm.start_background_checks(interval_seconds=60)
# F.5a.5: reap expired chunked-upload sessions
from core.upload_sessions import CleanupTask as _UploadCleanupTask
upload_cleanup = _UploadCleanupTask()
await upload_cleanup.start()
logger.info("Upload-session cleanup task started")
try:
yield
finally:
await upload_cleanup.stop()
# Stop health monitor background checks
if hm:
await hm.stop_background_checks()
@@ -4772,9 +4787,17 @@ def create_multi_endpoint_app(transport: str = "streamable-http"):
# Build routes
# Note: Order matters! More specific routes first
from core.companion_audit import handle_companion_audit_request
routes = [
# Health check
Route("/health", health_check, methods=["GET"]),
# F.18.7: Companion plugin audit webhook receiver.
Route(
"/api/companion-audit",
handle_companion_audit_request,
methods=["POST"],
),
# Root redirect
Route("/", root_redirect, methods=["GET"]),
# Auth routes (E.2: OAuth Social Login)
@@ -4787,6 +4810,9 @@ def create_multi_endpoint_app(transport: str = "streamable-http"):
Route("/dashboard/login", dashboard_login_submit, methods=["POST"]),
Route("/dashboard/logout", dashboard_logout, methods=["GET", "POST"]),
Route("/dashboard/profile", dashboard_profile_page, methods=["GET"]),
# F.18.8 /dashboard/provider-keys removed in F.5a.9.x — replaced by
# per-site AI keys in /dashboard/sites/{id}. See per-site routes
# registered below under "Site Management API".
Route("/dashboard/sites/add", dashboard_sites_add, methods=["GET"]),
Route("/dashboard/sites/{id}/edit", dashboard_sites_edit, methods=["GET"]),
Route("/dashboard/sites/{id}", dashboard_sites_view, methods=["GET"]),
@@ -4874,6 +4900,46 @@ def create_multi_endpoint_app(transport: str = "streamable-http"):
Route("/api/sites/{id}/test", api_test_site, methods=["POST"]),
Route("/api/sites/{id}", api_delete_site, methods=["DELETE"]),
Route("/api/sites/{id}", api_update_site, methods=["PATCH"]),
# F.5a.9.x: per-site AI provider keys
Route(
"/api/sites/{id}/provider-keys",
api_site_provider_keys_list,
methods=["GET"],
),
# F.7e: credential capability probe
Route(
"/api/sites/{id}/capabilities",
api_site_capabilities,
methods=["GET"],
),
# F.X.fix #9: HTMX partial for the capability badge
Route(
"/api/sites/{id}/capabilities/badge",
api_site_capabilities_badge,
methods=["GET"],
),
# F.X.fix #12: OpenRouter image-model discovery
Route(
"/api/providers/openrouter/models",
api_openrouter_models,
methods=["GET"],
),
Route(
"/api/sites/{id}/provider-keys/{provider}",
api_site_provider_keys_set,
methods=["POST"],
),
Route(
"/api/sites/{id}/provider-keys/{provider}",
api_site_provider_keys_delete,
methods=["DELETE"],
),
# F.X.fix-pass3: per-site default image model
Route(
"/api/sites/{id}/provider-keys/{provider}/default-model",
api_site_provider_default_model,
methods=["PATCH"],
),
# User API Key routes (E.3)
Route("/api/keys", api_list_keys, methods=["GET"]),
Route("/api/keys", api_create_key, methods=["POST"]),