commit c42c2e411ffb9f081af311138a19a5710b432b6d Author: Mortdecai Date: Sun Jun 28 09:56:45 2026 -0400 JELLAI — public showcase (README + screenshots) diff --git a/README.md b/README.md new file mode 100644 index 0000000..3317ad9 --- /dev/null +++ b/README.md @@ -0,0 +1,66 @@ +# JELLAI + +An AI-native TV experience layered over an **existing Emby media server**. Not a library you browse — +a channel that's already on, plus a concierge you talk to. A single tool-calling model runs the whole +loop: it drives the gateway tools (search, schedule, playback handoff) and talks to you from a +personality prompt. Always-on chat, TV-style time-block scheduling, mood awareness, and preference +learning seeded from your real watch history. + +**Status:** v1 — working prototype. TV-first, single user. Built on the Emby you already have (one +server, one source of truth — your watch history is the personalization seed). + +## What it feels like + +You don't open JELLAI. It's already there — your media server, just with the lights turned down and +a concierge in the corner. A **TONIGHT strip** runs along the bottom, and a 💬 door waits bottom-right. +Nothing covers what you're watching. + +![Home with the TONIGHT strip and concierge door](docs/screenshots/01-home-strip.png) + +Tap the door and the **concierge panel** slides in from the right — video keeps playing. Tell it how +you feel, not what to search for: *"build me a chill TV night — something funny and easygoing."* It +talks back in its own voice, then **builds a real lineup** into the strip: time blocks, in order, drawn +from your actual library. Don't like it? `[yes] [swap] [keep]` — one word steers the whole night. +Click any block to start playing from there, in Emby's own player. + +![Concierge panel building a lineup, strip filled with time blocks](docs/screenshots/02-concierge-lineup.png) + +> The strip is the spine. Ask once, and the rest of the night schedules itself — then re-schedules +> live every time you change your mind. That's the whole product: a channel that's already on, tuned +> to you, that you can talk to. + +These are real screenshots — a live themed Emby client driving the running gateway and a **local** +language model. No cloud LLM in the loop. + +## How it works + +``` +Emby web UI ──CSS/JS inject──▶ concierge panel ──WebSocket──▶ gateway ──▶ local LLM (Ollama) +(your server) (overlay theme) (tool loop) tool-calling + ▲ │ + └──────────────── Emby REST API (/Items, schedule, playback)─┘ +``` + +- **Frontend (v1):** a concierge panel + schedule strip injected into the Emby web client via CSS/JS. + It couples to almost nothing in Emby's DOM — it only appends its own fixed-position nodes — so it + survives Emby updates. Playback always delegates to Emby's own player. The eventual target is a + custom SPA over the Emby REST API. +- **Gateway:** a small Python WebSocket server mediating between the UI and a local model. It runs a + tool-calling loop against one stock instruct model — no fine-tune unless a measured gap demands it. +- **Tools:** search, TV-style scheduling, and watch-state queries against the Emby API. The model sees + JSON tool schemas and composes them (e.g. "movie night" → a movies-only lineup). + +## Why build on Emby instead of a new frontend + +The original plan was a dedicated themed media app. We reversed it and built on the existing Emby: + +- **Single source of truth** — no duplicate library scan, no second metadata DB. +- **Watch history is the personalization seed** — per-user learning is the whole premise, and that + history already lives in Emby. A fresh install starts cold. +- **Emby is enough** — a full documented REST API, plus community CSS/JS injection for the overlay. + +## Status & scope + +Working today: the concierge loop, live TV-style scheduling into the strip, mood-aware search with +type/year/rating/sort filters, and one-word lineup steering. Deliberately out of v1: content +acquisition, multi-user profiles, and model fine-tuning — added only against a measured need. diff --git a/docs/screenshots/01-home-strip.png b/docs/screenshots/01-home-strip.png new file mode 100644 index 0000000..4edf346 Binary files /dev/null and b/docs/screenshots/01-home-strip.png differ diff --git a/docs/screenshots/02-concierge-lineup.png b/docs/screenshots/02-concierge-lineup.png new file mode 100644 index 0000000..e2a7ed7 Binary files /dev/null and b/docs/screenshots/02-concierge-lineup.png differ