# Alur API Express → Engine learning-lab Express tidak punya backend sendiri. Semua logika AI (perencanaan, pembuatan materi, video, riset) ada di engine **learning-lab** (FastAPI, `/api/v1`). Express hanya membuat *agent* (jadwal) beserta konfigurasinya, lalu membaca dan meninjau hasilnya. ## Jalur request | Lingkungan | Jalur | |---|---| | Production | `express.bawana.com/api/*` → redirect Netlify ([netlify.toml](../netlify.toml)) → `https://learningstudio.bawana.com/api/*` | | Dev | Proxy Vite `/api` → `ENGINE_URL` (default `http://localhost:8000`, [vite.config.ts](../vite.config.ts)) | - Prefix `/api/v1` ditambahkan di [src/api/client.ts](../src/api/client.ts). Setiap request membawa `Authorization: Bearer `. - Request baca dan aksi diatur lajunya oleh `pace` di `client.ts`, supaya tidak terkena rate limit proxy (503/429). - Endpoint agent ada di `learning-lab/backend/app/api/v1/endpoints/agents.py` (semua di bawah `/organizations/current/agents`). Endpoint produksi konten ada di `agent_content.py` (`/organizations/current/agents/{id}/content`). Di bawah ini, `AGENTS` = `/organizations/current/agents`. ## Jadwal = agent Setiap jadwal Express adalah satu agent engine. Namanya diawali prefix Express, lalu dibaca lewat `expressAgents()` di [schedules.ts](../src/express/schedules.ts). ### Membuat jadwal (`createSchedule`) | Langkah | Endpoint | |---|---| | (khusus video) Ambil harga satu video sebagai budget run | `GET AGENTS/video-quote?scenes=…&duration_seconds=…` | | Buat agent dengan konfigurasi dari `configFor()` | `POST AGENTS` | | Pasang dokumen Brain (semua dokumen yang siap, atau hanya yang dipilih) | `PUT AGENTS/{id}/knowledge-sources` | | Aktifkan (menyetujui aturan produksi; sebelum aktif tidak ada yang berjalan) | `POST AGENTS/{id}/activate` | ### Mengelola jadwal | Aksi | Endpoint | |---|---| | Ubah brief (engine mengembalikan agent ke draft, jadi langsung diaktifkan ulang atau dipause) | `PATCH AGENTS/{id}`, lalu `POST AGENTS/{id}/activate` atau `/pause` | | Pause / resume | `POST AGENTS/{id}/pause`, `POST AGENTS/{id}/activate` | | Arsipkan | `POST AGENTS/{id}/archive` | | Riwayat run | `GET AGENTS/{id}/runs` | | Kesiapan knowledge | `GET AGENTS/{id}/knowledge-readiness` | ## 1. Konten materi (summary, quiz, flashcard, slide, audio, SCORM, …) **Konfigurasi agent** (`configFor`): ```ts enabled_tools: ['knowledge.retrieve', 'compose.graph.retrieve', 'compose.create_material'] material_outputs: outputsFor(kind) content_goal: { enabled: true, weekly_target, execution_mode: 'automatic' } ``` Audio dan SCORM adalah jenis buatan Express sendiri, disusun dari output Compose. Audio adalah summary narasi; SCORM adalah pasangan summary dan quiz dari satu item rencana. **Produksi** (`AGENTS/{id}/content`): | Langkah | Endpoint | |---|---| | "Produce now", atau tick otomatis jam 09:00 WIB | `POST …/content/planning-quotes` `{ target }` | | Konfirmasi rencana | `POST …/content/plans/{plan}/confirm-planning` `{ revision }` | | Approve dan start | Dijalankan otomatis oleh tick engine (mode `automatic`) | | Retry satu item (maksimal 3 percobaan) | `POST …/plans/{plan}/items/{item}/retry-quote`, lalu `POST …/plans/{plan}/start` | | Status rencana dan periode minggu ini | `GET …/content` (di-cache 30 detik oleh `productionStatus`) | **Di sisi engine** (`backend/app/services/`): - `agent_content_planning.py`: model mengusulkan topik beserta bukti dari isi Brain. - `agent_content_execution.py`: membuat quote dan memesan kredit untuk setiap item. - `agent_materials.py`: menjalankan Compose (`compose_creation`) untuk membuat materinya. **Hasil**: `material-drafts`. ## 2. Video **Konfigurasi agent**: ```ts enabled_tools: ['knowledge.retrieve', 'compose.graph.retrieve', 'studio.create_video'] video_options: { max_scenes, max_duration_seconds, art_style: 'realistic', language } run_schedule: { cadence: 'weekly' | 'daily', hour: 9, minute: 0, weekday: 0 } ``` **Memicu run**: tick jadwal di engine, atau `runNow`, yaitu `POST AGENTS/{id}/runs` dengan header `Idempotency-Key`. **Di sisi engine**, `agent_worker.py` menjalankan: `agent_video_drafts.py` (membuat project Video Studio dan memesan kredit) → `agent_video_script.py` → `agent_video_storyboard.py` → `agent_video_clips.py` → `agent_video_render.py` **Hasil**: `video-drafts`. Satu draft tidak bisa di-retry sendiri; yang dilakukan adalah run baru dari jadwalnya, dan tombol retry hanya muncul di draft terbaru. ## 3. Riset sumber web **Konfigurasi agent**: ```ts enabled_tools: ['knowledge.retrieve', 'compose.graph.retrieve', 'browse.search', 'library.add_url'] research_options: { max_results: 5 } auto_approve_sources ``` **Memicu run**: jam 07:00 WIB, atau `POST AGENTS/{id}/runs`. **Hasil**: `source-drafts`. ## Membaca dan meninjau hasil ([results.ts](../src/express/results.ts)) | Jenis | Daftar | Detail | Aksi | |---|---|---|---| | Materi | `GET AGENTS/{id}/material-drafts` | `GET AGENTS/{id}/material-drafts/{draft}` | `POST …/material-drafts/{draft}/decision` `{ expected_revision, decision }` | | Video | `GET AGENTS/{id}/video-drafts` | (judul diambil dari daftar) | `POST …/video-drafts/{draft}/review` `{ decision }`, `POST …/video-drafts/{draft}/cancel` | | Sumber | `GET AGENTS/{id}/source-drafts` | — | `POST …/source-drafts/{draft}/review` `{ expected_revision, decision }` | Ekspor slide deck ke PPTX memakai `POST /slide-deck/{deckId}/export`. ### Pola polling `listResults()` dipakai oleh halaman Results dan Production (query key `['results']`, `RESULTS_POLL` = setiap 30 detik): - Setiap poll membaca `GET AGENTS/status?archived=true` satu kali, dengan `If-None-Match` (opsi `revalidate` di `client.ts`). Kalau tidak ada perubahan, engine menjawab 304. - Dari respons itu dibuat tanda per agent. Endpoint per jadwal (`material-drafts`, `video-drafts`, `source-drafts`) hanya dibaca ulang untuk agent yang tandanya berubah. - Pembacaan ulang tetap dipaksa untuk jadwal konten dengan plan aktif (topik plan belum punya draft), setelah 30 menit (URL video bertanda tangan berlaku 1 jam), dan setelah setiap mutation (`forgetReads`, [main.tsx](../src/main.tsx)). - Kalau `/status` sibuk, tanda terakhir dipakai. Kalau endpoint tidak tersedia, semua jadwal dibaca seperti dulu; jadwal arsip tetap cukup dibaca sekali. - Paling banyak 4 request per jadwal berjalan bersamaan (`PER_SCHEDULE_LIMIT`). Konten dibaca dulu, baru riset. - Kalau engine membalas 503/429, request dicoba sekali lagi setelah 3 detik. Kalau tetap gagal, hasil poll sebelumnya yang dipakai. - Di engine, `_video_draft_out` menjalankan sekitar 5 query untuk setiap draft (project, run step, dokumen, scene, kredit), dengan batas 100 draft per agent. ## Brain dan kredit ([src/api/engine.ts](../src/api/engine.ts)) | Aksi | Endpoint | |---|---| | Daftar / status / hapus / unduh dokumen | `GET /upload/list`, `GET /upload/{id}`, `DELETE /upload/{id}`, `GET /upload/{id}/file` | | Upload | `POST /upload/` | | Format yang didukung | `GET /upload/supported-formats` | | Knowledge graph dokumen | `GET /upload/{id}/knowledge`, `POST /upload/{id}/knowledge/build` | | Proses ulang | `POST /upload/{id}/reprocess` | | Versi baru atau bukan | `POST /upload/{id}/versions/link` atau `/decline` | | Saldo kredit | `GET /organizations/me` | | Pemilik jadwal | `GET /auth/me`, `GET /organizations/current/dashboard/members` | ## Kode lama yang tidak dipakai Fungsi berikut di `src/api/engine.ts` tidak dipanggil di mana pun di `src/`. Ini sisa alur versi awal, yang memakai satu agent tunggal bernama `Learning Lab Express` dan memanggil Compose langsung: - `generateText`, `generateQuiz`: `POST /compose/sets`, `/generate/summary`, `/generate/quiz` - `ensureAgent`, `attachSources`, `setSchedule`, `research` `resetAgentCache` masih dipakai oleh `AuthGate.tsx`.