Features
- Video export (MP4) — Export a lesson as a rendered video: a
VideoTimelineIR with a pure compile pipeline #913, an L1 Hyperframes emitter with in-browser frame collection and ZIP export #931, and a service-backed MP4 render with in-app one-click export #937 (by @cosarah) — built on a shared orchestration spec inlib/choreography#890 (by @cosarah) and persisted TTS audio durations #862 (by @cosarah) - Server-backed runtime storage — A pluggable storage seam for classroom runtime state:
@openmaic/storageKV + asset primitives #858, a normalized DocumentStore #860, RuntimeStore sessions with append-only records #880, a DSL runtime envelope #870, device-anonymous learner identity #885, a runtime-event outbox with dual-write #893, cutovers for PBL learner state #902 #922 and chat sessions #926, and an HTTP backend contract with a Postgres backend and reference server #946 - Editor: direct manipulation — Select and drag slide elements #859, 8-point resize + rotate handles #881, marquee multi-select with multi-element drag #888, and a draggable insert toolbar #912, scaffolded as the
@openmaic/rendererv2 editing surface behind a machine-enforced import boundary #853 #855 - Edit with AI upgrades — Natural-language element edits through a typed EditIntent pipeline #896, validated JSON Patch element edits #927, and multi-session conversation history for the AI editor #801
- DSL self-ownership —
@openmaic/dslnow owns the Action playback verbs #787, ships JSON Schema artifacts with pure validators #817, activates the migration registry and runner #825, and owns element-level normalization and defaults wired into the generator #832 and the importer output boundary #845 - Document Parsing expansion — Multi-format course-material upload #741 and document bundles #844 (by @jackefn), audio/video media extraction with an AliDocMind provider #887 (by @yanpgwang), and a renamed Document Parsing surface with visible supported formats and extended MinerU support (by @yanpgwang)
- Add Azure OpenAI as an LLM provider #916 (by @hydraxman), SearXNG as a web-search provider #842 (by @PineSongCN), ComfyUI as an image provider #850 (by @PhillLittlewood), the GPT-5.6 model family #907, and an updated Doubao Seed model catalog #827
- Add one-click token-plan setup and a deployment usage dashboard #784 (by @yanpgwang)
- Add action-level playback navigation #843 (by @danishsshaikh)
- Redesign the narration timeline (action picker + inline insert) and enable it for interactive/PBL scenes #834
- Add in-editor authoring of classroom agents with a Stage-level roster #816
- Parallelize within-scene TTS generation #696 (by @ly-wang19)
- Feed the real HTML element inventory into interactive-action prompts #829 and add a postMessage listener contract to diagram/game/code widgets #872 (by @yanpgwang)
- Add an experimental Pi classroom runtime behind a flag #914
Bug Fixes
- Security: disable redirects in media connectivity probes #930 and harden provider redirect handling with ISATAP address detection #928 against SSRF (by @YizukiAme)
- Generation: strip reasoning blocks before JSON parsing #750 (by @yipwingtim), localize scene-generation errors #894 (by @wsun1), tolerate malformed generated slide data (by @yipwingtim), and honor outline node constraints in diagrams #911
- Editor: keep emptied or zero-action scenes playable, bind the outline by stable id, and surface incomplete content #814; show per-line loading while the batch "regenerate all TTS" runs #830
- Export: fix the unresponsive resource pack for interactive-only decks #933 (by @2046731121CC), compute SVG path bounding boxes via
getBounds()#656, keep sibling attributes when style is empty #683, and convert PPTX shadow offsets from px to pt #679 (by @ly-wang19) - Quiz: render formulas in quiz text #833 (by @dpersek); stop leaking questions on entry and pass results to the chat agent #823 (by @yanpgwang)
- Storage: store image files as array buffers #923 (by @YizukiAme) and accept image storage IDs containing underscores #918
- Chat: preserve message line breaks #908, and cap the roundtable non-presentation input height #917 (by @YizukiAme)
- TTS: respect string context when splitting the Doubao stream #677; web search: match Brave's current result-title markup #688 (by @ly-wang19)
- Stage: centralize the deck completion predicate #883 (by @dpersek)
- AI: close PROVIDERS/THINKING_CAPABILITIES metadata drift with a guard #809 (by @mvanhorn)
- Home: clarify the Interactive Mode selected state #901; lecture notes: render interactive-webpage widget actions #810
- Docker: fix the postinstall script failure in Docker builds #835 (by @Lee-Flier)
- mathml2omml: call
includes()instead of indexing it #681 (by @ly-wang19)
Other Changes
- Performance: dedupe editor alignment snap-lines in O(n) #692, diff code lines in O(n) via a prev-line map #706, and index assigned images by id in
fixElementDefaults#701 (by @ly-wang19) - Tests: cover
splitLongSpeechText/splitLongSpeechActions#694 (by @ly-wang19); settle dynamic imports #899 and drain debounced saves #897 before store-test teardown - Media providers: share the submit-poll task driver #900 and the auth probe across matching adapters #903, and remove the dead legacy pipeline chain #905 (by @YizukiAme)
- Packages: add repository metadata #813 and set
@openmaic/*package versions to 0.0.2 #812 (by @xuyuanwei678) - Docs: document the dev-server OOM workaround for large generations #808 (by @mvanhorn)
- Tighten GitHub issue intake #921