Commit graph

2 commits

Author SHA1 Message Date
Anuragp22
24e4bb40e5 feat: background worker, prompt template, section switcher, home hub
Bundles three changes that were originally landed as stacked PRs into
peer branches and never reached main. Combined here as a single PR
targeting main.

worker/index.js (new)
---------------------
Long-lived Node process that:
- Polls Postgres every 2s for batches in status='running'.
- Claims queued jobs with SELECT ... FOR UPDATE SKIP LOCKED (single
  worker today, ready for N-worker scale tomorrow with no further
  code change).
- Re-uploads local-only trainer images (/api/uploads/...) to MuAPI's
  /upload_file once and caches the resulting CDN URL on the trainer
  row so future jobs reuse it.
- Submits POST /api/v1/<batch.model> with prompt, images_list,
  aspect_ratio, duration, quality.
- Polls /api/v1/predictions/:id/result, extracts videoUrl from
  outputs[0]/url/output.url/video_url on success.
- Backoff: min(10 * 3^retries, 300)s. After retries >= 3, status=
  'failed', waiting for manual Retry from the UI.
- Recovery on boot: re-queues anything left in 'submitting' from a
  crashed run; 'polling' jobs keep their muapiRequestId.

Configuration: MUAPI_API_KEY (required to do work), MUAPI_BASE_URL
(default https://api.muapi.ai), WORKER_TICK_MS (default 2000),
UPLOAD_DIR (default /data/uploads).

worker/package.json: { "type": "module" } so plain Node 20 runs the
ESM imports.

Dockerfile: copy /app/worker into the runner stage.

docker-compose.override.yml: replace placeholder with the real
'npx prisma generate && node worker/index.js'.

lib/promptTemplate.js (new) + worker integration
------------------------------------------------
renderPrompt({trainer, studio, job}) wraps each row's raw practice
description in a fixed narrative template that pins identity,
biomechanics, environment, lighting, clothing, expression, video
style, and a list of forbidden behaviours (no camera movement, no
cuts, no limb warping, no pose distortion, etc).

duration, aspect_ratio, and quality remain SEPARATE fields in the
MuAPI request body; they are never injected into the prompt text.

lib/csvParser.js: stops appending 'Start position: ... Camera: ...'
into the stored prompt. Just stores the raw practice description;
startPosition + cameraAngle remain available as their own columns
for the renderer to consume.

components/SectionSwitcher.jsx (new)
------------------------------------
Two-pill switcher (Studio · Batch) rendered in the top-left of every
shell. Active pill is yellow on black. Click writes the choice to
localStorage so the home hub can highlight 'Last used'.

StandaloneShell, BatchShell, BatchDetail headers all updated to host
the switcher next to the logo. The redundant '← Studio' link in
BatchShell's right-side actions is removed since the switcher
replaces it.

app/page.js + components/HomeHub.jsx
------------------------------------
/ used to redirect to /studio. Now serves a hub with two cards:
Batch (CSV-driven automation) and Studio (one-off generations).
The card the user last opened gets a yellow accent + 'Last used'
tag from localStorage.

Stub-package copy
-----------------
packages/ai-agent and packages/workflow-ui description strings and
runtime 'feature unavailable' notices: removed organization-specific
phrasing in favour of generic 'this fork' wording.
2026-04-23 09:41:55 +05:30
Anuragp22
694c7075e2 feat(batch): New Batch wizard, CSV parser, and batch list
Slice 3 of the batch feature. Marketing team can now upload the
Rasika-style CSV, watch each row auto-map to the trainer/studio
they uploaded in slice 2, get a real MuAPI cost estimate, and
persist the batch as a draft.

Backend
-------
- POST /api/batches: creates a batch in status='draft' along with one
  job per CSV row (status='queued', not yet picked up since the
  worker arrives in slice 4).
- GET /api/batches: list view payload.
- GET /api/batches/[id]: detail with jobs joined to trainer/studio
  rows. Used by the slice-5 progress UI.
- POST /api/batches/[id]/estimate-cost: forwards the batch's model +
  payload to MuAPI's /api/v1/app/calculate_dynamic_cost, multiplies
  by row count, returns {perJob, total, currency}.

CSV
---
- lib/csvParser.js: PapaParse-based parser that validates required
  columns, normalises duration ("15 sec" -> 15) snapped to Seedance
  2.0's [5,10,15], maps quality ("1080P" -> "high"), and composes a
  prompt from description + start position + camera angle.

UI
--
- components/batch/NewBatchWizard.jsx: full-screen 3-step wizard.
  - Step 1 — name, CSV upload, model/duration/quality/aspect/
    concurrency settings.
  - Step 2 — review every row in a table. Auto-maps Character ->
    Trainer.csvLabel and Studio -> Studio.csvLabel, shows per-row
    override dropdowns and bulk-assign helpers, hard-blocks Next
    until every active row has both a trainer and studio.
  - Step 3 — saves the batch and triggers the cost estimate. On
    success, surfaces the batch id and points the user to the
    upcoming worker slice.
- components/batch/BatchesTab.jsx: replaces the placeholder with a
  real list view (status pill, progress counts, model, created-at)
  and the "+ New batch" button that opens the wizard.
- components/batch/BatchShell.jsx: pass apiKey to BatchesTab.

Verification
------------
- POST /api/batches with one row -> 201, batch + job persisted in
  Postgres (verified with psql).
- GET /api/batches lists the row.
- Cost estimate endpoint returns 401 without a key, calls MuAPI
  correctly with one (live test pending real credits).
2026-04-23 08:01:15 +05:30