Skip to content

Add media generation endpoints and local asset storage - #98

Merged
maiphucgiang merged 8 commits into
mainfrom
feature/media-generation
Oct 27, 2026
Merged

maiphucgiang merged 8 commits into
mainfrom
feature/media-generation

Conversation

@maiphucgiang

@maiphucgiang maiphucgiang commented Oct 26, 2026 •

Copy link
Copy Markdown
Owner

Summary

  • Add OpenAI-compatible image generation, image editing and asynchronous video endpoints backed by the verified WorkBuddy media routes.
  • Add account/catalog-aware media routing, bounded media failover, request/session headers, model guards and media-specific business-code handling.
  • Persist generated assets and video task metadata in a dedicated local media store with MIME sniffing, TTL/quota cleanup, immutable asset serving and admin/WebUI management.
  • Add preview simulation, English/Chinese client and WebUI documentation, media model catalogs and end-to-end/unit coverage.
  • Keep bound video tasks on their submitting account; a real upstream polling error now terminates the task and later polls return the stored failure without another upstream call.
  • Route-specific model errors can fail over to another eligible media account, while invalid enable_audio types are rejected instead of coerced.

… page

- /v1/images/generations, /v1/images/edits (JSON), /v1/videos submit/query/content
  backed by upstream /v2/images/* and /v2/videos/*; chat endpoints reject media
  models with a pointer to the media API
- Media routing: cn-cli whitelist, catalog membership with static fallback,
  positive balance; replay only on 401/403/429 or unsent bodies, 5xx/timeout
  never replayed; 401 alone cools accounts; video tasks stay account-bound
- media.sqlite3 + media/ store: header-sniffed file whitelist, atomic commits,
  TTL and capacity eviction, CSP-sandboxed public serving at /v1/media/*
- media_public_base_url / media_max_total_mb / media_ttl_hours settings with
  WebUI media page (library, tasks, models, settings drawer), admin /admin/media
  API, logs protocol badges, preview simulation and seeds, tests and docs
- Contract layer mirrors the CLI ImageService body: three-family branches,
  default 1024x1024 size, exact catalog tags, multiline prompts (32000-char
  shared bound), business-error envelope checks (MediaUpstreamError → 502
  with upstream code, never replayed)
- Media catalog scope reads the account root table (serves); CatalogIndex
  builds media_kinds for O(1) chat-guard and model-table lookups; preview
  moves media models to the root list with real tags
- Store: payload staged in media/.incoming outside the lock, TTL derived
  from created + current setting (expires column dropped, schema v1),
  explicit task-error clearing; admin media routes answer 503 when the
  store is missing and serialize created_at/expires_at/updated_at
- Gateway flow: image validation 400s, per-task refresh locks (one
  download), retryable vs deterministic download failures, concurrent
  multi-image downloads with partial-failure results and no orphans,
  store pre-check before billed upstream rounds, expired reads 404
- WebUI: created_at/expires_at/updated_at fields, catalog source labels,
  picture-style icon, i18n copy-failure text, warn hint on in-flight
  tasks with download retries; docs updated in pairs
- Image references get their own 20 MiB bound so data: URIs fit; prompts
  keep the 32000-char bound and blank prompts are rejected again
- Video downloads fail permanently only on 403/404/410, refused types or
  over-quota payloads; other statuses and local store errors stay retryable
- Store: best-effort unlink without shard rmdir, stale .incoming sweep,
  TTL-filtered listing and usage; control chars checked with one regex
- Multi-image replies count every failed item, including unexpected
  exceptions, against the processed items only
- Admin media routes keep the generic error envelope; TTL and quota come
  from the gateway helpers; tasks swept mid-refresh answer 404
- WebUI flags deferred downloads and localizes remaining-time labels
- Media replies carrying an account-restriction code, as an HTTP error or
  a non-zero business envelope, disable the account through
  note_restriction; codes in NO_FAILOVER_UPSTREAM_CODES are never replayed
- Other media refusals keep their health isolation: only 401 reaches the
  cooldown path
- Extract _apply_session_headers from _cred_for and use it for media
  leases, so media requests carry the same conversation and trace headers
@sourcery-ai

sourcery-ai Bot commented Oct 26, 2026

Copy link
Copy Markdown

Sorry @maiphucgiang, your pull request is larger than the review limit of 150,000 diff characters

@maiphucgiang
maiphucgiang merged commit 9ec1c67 into main Oct 27, 2026
6 checks passed
@maiphucgiang
maiphucgiang deleted the feature/media-generation branch October 27, 2026 04:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant