Bump the application version to 1.0.3 and record the changelog. This is a security release closing three advisories — access-code token expiry and verification throttling, a render-service network policy on untrusted HTML, and audio provider redirect and DNS-rebinding validation — and upgrading Next.js to patch a critical RCE, plus the fixes and features merged since 1.0.2. Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
73 KiB
Changelog
All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog.
[1.0.3] - 2026-09-15
A security release: access-code tokens now expire and verification is throttled behind a trusted proxy, the render service applies a network policy to the untrusted HTML it renders, audio provider requests validate redirects and pin their connections, and Next.js is upgraded to patch a critical RCE. It also carries the fixes and features merged since 1.0.2.
Security
- Access-code verification tokens (
timestamp.HMAC) never expired because neither verifier checked the timestamp, andPOST /api/access-code/verifyhad no throttling. Both verifiers now enforce a 7-day server-side lifetime and reject non-canonical signatures, and verification is rate-limited per client whenTRUST_PROXY_HEADERS=true(with a warning to use a long randomACCESS_CODEwhen it is short) GHSA-qpmr-534w-hhpg (reported by @CaptBoykin) #1513 - The render service ran caller-supplied HTML in headless Chromium without the packager's Content-Security-Policy on the
/previewand/renderpaths, so inline script could reach loopback and internal addresses and, on/render, paint the response into the returned MP4. Both paths now inject a first-parsed CSP, the preview frame is additionally guarded by request interception, and framed same-origin.svg/.xhtmldocuments are sanitized GHSA-vqq3-22q7-289w (reported by @CaptBoykin) #1512 - Audio provider requests (TTS, ASR, voice registration and voice cloning) validated a client-supplied base URL once and then followed redirects and re-resolved DNS unvalidated, so a redirect or a rebinding answer could reach an internal address. These requests now validate every redirect hop and connect only to the addresses the guard validated, on every hop GHSA-9p8q-rcmg-pmjw (reported by @CaptBoykin) #1514
- Upgrade Next.js from 16.2.11 to 16.3.3, which patches an unauthenticated remote code execution on Windows-hosted servers (GHSA-p293-qw3h-jr36 / CVE-2026-75604) #1503
Features
- Storage: the server owns the asset entry lifecycle and releases assets on course deletion (the #1007 amendment) #1472 #1473
- Skills: add an inquiry-based exercise-class teaching skill grounded in the zone of proximal development #1382
Bug Fixes
- Importer: resolve embedded PPTX videos when the legacy link points at NULL, and upload video posters through the configured callback (
@openmaic/importer0.2.1) #1507 - Storage: keep jsonb writes valid when model output contains NUL or lone surrogates #1499; allow one owner material to be bound to multiple sessions #1500
- Classroom: render a transient server error as a retryable state instead of the terminal "course does not exist" card, on both the pane and the standalone route #1485
- Upload: resolve the generic Office MIME (
application/vnd.ms-office) via the filename extension #1498 - Settings: maintain the ASR language state invariant on provider selection #1443
- TTS: treat a custom provider's Add-dialog default base URL as a configured credential path so generation narration is not skipped #1482
- Export: tolerate malformed authored CSS in classroom exports instead of dropping later assets #1422
- Render service: preserve plan audio during chunk assembly #1358
- Docker: enable the Pro workbench flag in Docker builds and allow a non-TLS localhost cookie #1484
Other Changes
- Docs: document the deployment assumptions and pre-report checks in the security policy #1511
- Tests: isolate the image URL-guard test environment so it no longer inherits the generic OpenAI fallback #1476
[1.0.2] - 2026-09-14
A security release that closes a cloud-metadata SSRF gap, a DNS-rebinding bypass on media proxying, and a classroom overwrite, and tightens two request paths — read the Breaking Changes section first.
Security
/api/proxy-mediaand the outbound URL guard accepted the Alibaba Cloud instance-metadata address100.100.100.200because the metadata denylist was not applied before an IP literal was accepted. The guard now checks metadata hostnames and addresses — including mapped and transition encodings — before the literal and local-network branches, in every environment and regardless ofALLOW_LOCAL_NETWORKSGHSA-6xff-rgjg-v33f (reported by @lihua666a-cell)/api/proxy-mediavalidated a hostname and then letfetch()resolve it again at connect time, so a name whose answer changed between the two lookups could reach an internal address (DNS rebinding). The proxy now connects only to the addresses the guard validated, on every redirect hop, through a shared pinned dispatcher GHSA-23xq-m3mm-3j49 (reported by @ry2811)POST /api/classroomaccepted a caller-chosen classroom id and renamed a temporary file over an existing classroom, replacing its content. Ids are now server-generated and classroom files are created exclusively, with a bounded retry and a 409 on collision GHSA-87m4-6c66-pc68 (reported by @ry2811)POST /api/generate/ttsnow inspects a 200 response before storing or billing it: HTML, JSON and other non-audio bodies are rejected, and a URL embedded in a JSON envelope is never followed #1405
Breaking Changes
POST /api/classroomno longer honours a client-suppliedstage.id; theidin the response is the classroom's id #1489- The outbound URL guard now refuses IANA reserved, documentation, multicast and broadcast ranges (
240.0.0.0/4,198.18.0.0/15,192.0.2.0/24,2001:db8::/32, …) at both the URL and the connection layer, regardless ofALLOW_LOCAL_NETWORKS. CGNAT100.64.0.0/10(Tailscale and similar overlays) is blocked by default and allowed withALLOW_LOCAL_NETWORKS=true, like private ranges #1488
Features
- Playback: the global Reference courseware entry now grounds HTML-backed GenUI and Interactive scenes on one source-authored component — resolved again on the host against the request-start scene snapshot, sanitized and bounded, and shared with the Director and both child runtimes — behind the default-off
NEXT_PUBLIC_COURSEWARE_REFERENCE_ENABLEDbuild-time gate #1281 - Export: the export dialog checks render queue availability before compiling; a service that reports itself busy disables MP4 with a localized hint and a manual recheck, while ZIP and subtitle downloads stay available #1455
- Media: under server-backed persistence, generated media is written through the asset pool first and the allocated id is persisted into the document, so a reload regenerates nothing and other browsers resolve the same bytes #1392
- Providers: add GLM-5.3 and GLM-5.3-Flash, and make the GLM thinking adapter degrade a disabled request to the lightest effort for always-thinking models #1401
- Render service: emit one JSON lifecycle event per render and preview transition — submission, start with
queueWaitMs, finish with its outcome and duration, admission rejection, and preview request — carrying only bounded, low-cardinality fields #1397
Bug Fixes
- TTS: prepare the next discussion segment while the current clip plays, so synthesis latency overlaps playback while audio stays strictly ordered #1435
- Export: keep one in-memory compiled ZIP so an unchanged retry after a 429 submits the same result instead of recompiling #1456
- AI runtime: let non-streaming LLM calls outlive undici's 300 s headers timeout through a shared dispatcher with a 15-minute limit #1404; share one process-local thinking context across Next.js bundle evaluations #1378
- Importer: convert Equation 3.0 and MathType OLE formulas to LaTeX through MTEF v3 with degrade telemetry, and fix the non-transparent formula placeholder #1411; stop PPTX import from hanging in non-browser environments by bounding image loading and EMF/PDF rasterization #1424
- Quiz: resolve AI answer keys to option values before grading, failing closed when a key matches no option or several #1328
- Renderer: lazy-load the optional ECharts runtime, share one loading promise and wait for chart readiness during slide PNG export #1420
- Render service: keep preview browser evaluation self-contained so
tsx's__namehelper never reaches Chromium #1421; enforce the chunk worker cap and report the worker count actually observed #1359 - Materials: sanitize the owner id in the byte-store key so uploads work on Windows #1426
- Settings: read
data.errorfor image and video provider test results instead of renderingfailed: undefined#1459 - Classroom: adapt the completion page to short viewports instead of clipping its content above the scroll origin #1461
- Build: include the libvips native libraries in standalone tracing so sharp loads at boot #1407
Other Changes
- CI: add an opt-in issue triage agent that analyzes read-only by default and publishes only on an explicit run #1439
- Docs: state the advisory severity and CVE process in the security policy #1417
- Tests: cover preview callbacks across the
tsx/browser boundary #1454; make the material search budget test deterministic through an injectable clock #1453
[1.0.1] - 2026-09-06
A security and stability release. Everyone running 1.0.0 should upgrade; read the Breaking Changes section first, as this release tightens two defaults.
Security
- Classroom persistence rejected a stage id that escaped the classrooms directory
only on the read path. The write path now applies the same allowlist, and the
storage layer asserts a resolved classroom file stays inside
CLASSROOMS_DIRGHSA-p2wh-m28m-c5xw (reported by @skeletonsec) - Stored slide HTML is now restricted to the formatting vocabulary the renderer produces, sanitized at the classroom persistence boundary on both write and read, with a separate policy for KaTeX snapshots so formulas are not flattened GHSA-7rhf-2798-mvcj (reported by @skeletonsec)
- The outbound URL guard ran only under
NODE_ENV=production; it now runs at every call site in every environment, and a repository-scanning test fails if a gated call site reappears GHSA-9m7h-vh2h-rc3w (reported by @uziii2208) - Provider requests now re-validate every redirect hop through a shared transport and drop credential headers on a cross-origin hop, the way the platform fetch does GHSA-725p-44hx-v52c (reported by @skeletonsec)
- The development persistence authenticator is refused under
NODE_ENV=productionunless an explicit opt-in is set; it provides no user isolation and was never meant to serve production traffic - Bump next, js-yaml, undici, nanoid, lodash and sharp for disclosed advisories #1357
- Bound skill zip inflation instead of trusting the declared uncompressed size #1374, and bound
import_pptxparsing with a size cap and timeout #1269
Breaking Changes
- Node: the minimum supported runtime is now 22.19.0, up from 20.9.0 #1337
- The outbound URL guard now runs in every environment, not only production builds. A client-supplied provider base URL pointing at a loopback or private address — a local Ollama or Lemonade endpoint entered in Settings, for example — is rejected unless
ALLOW_LOCAL_NETWORKS=trueis set. Production deployments already behaved this way; development builds did not - Redirect hops are re-validated for every provider, including server-managed ones. An internal gateway that answers a redirect to a private address needs
ALLOW_LOCAL_NETWORKS=true - The development persistence authenticator no longer serves traffic under
NODE_ENV=production. A deployment that intentionally runs it on a trusted network must setPERSISTENCE_ALLOW_INSECURE_DEV_AUTH=true POST /api/classroomnow rejects a payload whose scenes do not satisfy the slide DSL, and a stage id outside[A-Za-z0-9_-]
Features
- Agent: add a fact-check skill #1274; let
generate_scenepasswidgetTypeandwidgetOutlinefor interactive pages #1259; makegenerate_videoasynchronous with a placeholder reference #1267 - Pro workbench: reference single PPT elements from chat #1224; generate concise conversation titles #1275
- Render service: add a
POST /previewendpoint #1285; report admission state machine-readably, with 429 reasons and an accepting flag on health #1351 - Providers: add Exa as a web-search provider #1342; register
deepseek-v4-flash-vision-expwith vision capability #1329 - Canvas: insert text by double-click #1310
Bug Fixes
- Classroom: speed up loading through media hydration, sidebar thumbnails and media range requests #1276; keep bottom table rows visible during playback #1366; keep videos playing inline on mobile #1321
- Agent runtime: preserve
generate_scenefailure causes #1316; boundgenerate_sceneretries per page #1370; normalize skill paths to POSIX before the loader #1297 - Workbench: handle stale workspace resume memory #1271; persist Pro conversation titles #1273; render LaTeX in assistant messages #1309
- Generation: assign unique IDs per media request #1368; load micropip before generated imports #1282; keep diagram node position off the hover transform #1339; normalize GPT Image 2 generation sizes #1346
- Providers and media: apply server-pinned models for image and video providers #1298; bypass the AI SDK for custom ASR providers so extra response fields survive #1283; turn TTS and media generation on from the Settings page #1311
- Storage: prune redundant intermediate
message_updateframes #1279 - DSL: migrate away legacy rotate/height fields on line elements #1261
- Export: recheck script readiness on download #1159
- Importer: fix
pnpm installfailing on Windows #1372 - Docs site: isolate the standalone build from product middleware #1307
Other Changes
- Build and tooling: enforce the direct dependency engine floor #1337; enforce LF line endings for text files #1296; replace
rm -rfwith a cross-platformfs.rmSyncin package scripts #1338 - CI: migrate GitHub Actions off the deprecated Node 20 runtime #1343
- Docs: sync the README with current code, multi-workbench skill support and the 1.0 videos #1334; swap the English and Chinese user-guide links in the README badges #1290
- Tests: isolate the media force-off test from the OpenAI fallback #1303
[1.0.0] - 2026-08-27
Features
- Agent workbench (Pro mode) — chat-first course building from the home page: the collapsible workspace shell #1206, the agent chat surface #1205, and the client data layer #1204, with Pro entry points that preserve mode-transition semantics #1208; owner-scoped folder routes, stage-metadata viewer surfaces, and the material upload contract #1215, plus stage and material HTTP routes #1203; the Pro workbench flag now implies the MAIC Editor gate #1223
- Durable agent runtime — server-backed course-building sessions: the driver model contract and stage route dialect #1165, the runtime foundations on the agent-session store #1167, a background session runner #1169, agent session and owner event streams #1170, and session lifecycle routes #1171 — sessions survive restarts, accept follow-up steering and cancellation, and stream a replayable event transcript; the runtime configuration surface is documented #1176
- Agent tools and skills — validated, provider-neutral course tools: neutral tool foundation libraries #1184, a
web_searchtool on the session runner #1185, session materials with afetch_urltool behind the URL trust gate #1190, material read/search #1192, stage read/patch #1194, page generation and deck editing #1198, roster and voice registration #1201, folder organisation #1202, image/video/PPTX import #1211, and the material extraction lifecycle #1212; a skills system #1189 with Feynman and spiral curriculum methods #1240, reference tools and skills ported in a parity audit #1241, and real skill management in Settings — list, download, delete, and upload #1244 - Provider-neutral server capabilities — image, video, and ASR models resolved from server config #1175, uniform capability force-off with a consistent missing-key contract #1181, startup validation of model routing config #1182, silent-behavior fixes from the provider audit #1196, and provider force-off enforced in agent tools with vendor identity scrubbed from tool results #1231
- Pluggable persistence — an agent-session store with a PostgreSQL backend over layered contracts #1163, an ownership scope on stage documents #1191, a per-session URL trust gate #1186, per-scene monotonic revisions via database triggers #1214, owner materials migrated to
oss_keywith the legacyasset_iddropped #1250, and per-owner quota reservations serialized with crashed uploads reclaimable #1232 - Materials and the asset byte model — uploaded sources ingested into the asset pool and extracted by id #1154, derived assets with lineage and an extraction cache #1164, a material library manifest with id-addressed generation images #1168, inline base64 images converted to pool assets on load #1172, legacy references converted to allocated asset ids #1101, media and materials moved onto the reference byte model with the asset-registry wiring retired #1242, a standardized asset manifest with converged export paths #1117 over one shared stored-bytes resolver #1116, opt-in indirect asset byte egress #1100, and an optional local ffmpeg/ffprobe media extractor #1213
- Editor: float the insert toolbar in the outer frame with collapse #1246; port the timeline TTS preview single-flight and voice-all state latching #1235
- Whiteboard and Pi Native Child: destructive whiteboard runtime operations #1173; Native Child whiteboard tools #1152 and additive whiteboard tools #1156, web search #1133, and a native child runtime with scoped Spotlight #1111
- Qwen TTS voice cloning #1160
- Download the narration script as Markdown or DOCX on export #1144
- A document lexical retrieval foundation for RAG #1078
- Video export: a bounded local chunk executor #1115
- German (de-DE) localization #1128
- OpenClaw skill: a secondary-development flow #1119
Bug Fixes
- Workbench: restore editor chrome, mode transition, streaming, materials, mentions, and folders #1229; restore the attach entry and add the rail settings entry, pinning all three entry points #1221; list PG-mode home courses via owner stages while keeping the interrupted terminal course card #1218; send the opening session message exactly once with references intact #1234; show newly created folders in the sidebar without a reload #1254; single-source the chat gutter so the timeline and composer share a left edge #1255 #1247; lock the pane-embedded classroom to edit mode #1256; label the extraction lifecycle tools on the timeline
- Agent runtime: control-plane routes answer 404, not 500, without a database, and the runtime reports itself unusable without one #1207; abort in-flight TTS on cancel and bound every provider request with a timeout #1217; bound every tool call with a timeout and never resurrect a cancelled session #1226; fence durable tool writes and consume cancel requests atomically #1230; fence session claims while an ask_user question is outstanding #1248; settle-time rescue tracks real delivery instead of a count offset #1249; repair orphaned and late tool results across interruption boundaries #1180; wake SSE tails and the runner on durable deltas for streaming fidelity #1222; carry reasoning through the completions dialect so the thinking strip renders #1239; revoke deleted-session URL authority and reject private ISATAP endpoints #1199
- Editor: complete element referencing with the renderer DOM contract and GenUI picking aligned to the reference #1238; resolve dock-bar i18n keys, remove the dock height drag, and wire element referencing #1233; allow dragging selected lines #1166; allow multi-tab edit mode by dropping the cross-tab edit lock #1161; align editable shape labels with text #1137; keep class roster cards from shrinking #1135
- Media: restore the reference classic media chain #1236; persist origin-independent classroom-media references from the agent runtime #1245
- Storage: asset writes no longer self-deadlock against pooled PostgreSQL #1225 #1227
- Importer: adapt the imported PPTX canvas size so decks render without overflow #1237
- Classroom: center adapted canvases in the stage and send navigation home during generation #1243
- Renderer: preserve literal text line breaks #1132
- Whiteboard: correct the inverted viewportRatio so boards render 16:9 landscape #1257
- Video export: make Cyrillic and Arabic Quiz fonts deterministic #1114; constrain GenUI iframe visibility #1125
- i18n: fix the Traditional Chinese translations in the importer #1127
Other Changes
- Docs: add the release version prefix to the README and drop the opt-in framing, surface the 1.0.0 user-guide badges at the top #1253, and a takeaway-style 1.0.0 announcement with bilingual guide links; announce 1.0.0 and refresh the feature overview #1216; document the agent runtime configuration surface #1176
- Tests: reconcile vendor-token debt counts with the integration line and after the main merge, mock both runtime gate exports in the control-plane route suites, and give material fixtures the extraction lifecycle fields; keep the PG contract suite order-independent #1200; cover indirect-egress CORS in Chromium #1138; wait for project cleanup instead of racing it in the render suite #1193; stop loading
.env.localinto unit tests by default #1162; guard the provider-neutral layers against vendor leakage #1197 - CI and build: cut wall-clock time and bound Playwright browser installs #1146; scope the Next typecheck to production sources #1179; add optional Docker mirrors and a pnpm cache #1139
- Workbench cleanup: retire the bookmark concept and the saved-courses drawer #1219; remove the in-editor agent panel #1210
- Storage: drop the unused active-stage API from the agent-session contract #1174
- Pi: simplify agent tool ownership and completion #1148
[0.3.2] - 2026-08-14
Features
- Video export hardening — fidelity polish for spotlight geometry, video clips, formulas, and subtitles #952, deterministic Quiz/PBL cover cards #995, self-contained static interactive HTML capture #1086, deterministic Quiz question-list scrolling #1102, a stable RenderExecutor seam #1104, explicit CPU resource profiles #1105, and effective parallel capture in the render service #1042
- Server-backed persistence completion — learner-data cutover: quiz + playback onto RuntimeStore #955; document-persistence cutover: stage/scene/outline onto DocumentStore #965; server-backed documents over an HTTP contract with a Postgres backend and one reference server #979; a one-command server-backed stack (compose profile + embedded API + docs) #982; dirty-set incremental saves with operation-level flush #983; settings/user-profile persistence through KVStore #1001; the KV HTTP contract and clients promoted to main #1020; learner whiteboard RuntimeStore foundation #1075
- Asset registry — allocated asset ids over the content-addressed blob layer #1024, unified media asset reference types #1038, generated assets allocated through the registry #1039, a server asset registry over a pluggable byte layer #1077, and the asset backend wired into the app #1089
@openmaic/generationpackage — scaffolding with pipeline types and packaged prompt assets #1063; outline generation #1065 and scene generation + PBL single-call planning #1087 moved into the package; the app consumes the package everywhere andlib/generationis deleted #1090- SDK contract ownership — interactive and PBL content kinds promoted into
@openmaic/dsl#1070, app consumes the contract's interactive/widget types #1073 and PBL project types #1079, and the renderer decouples its editing UI from the app #1072 - Course folder grouping #1005 (by @CXuPercy)
- Local FunASR ASR provider #1044
- Claude (
claude search) as a web-search provider #393 (by @joseph-mpo-yeti) - Per-stage routing for
generate-classroominstead of one model #1048; evidence-aware Pi Director context runtime #971; optional playback canvas renderer #958 - Amazon Bedrock LLM provider #538 (by @littlebullGit), Atlas Cloud LLM provider #948 (by @binyangzhu000-sudo), latest Claude/Gemini/Kimi/Grok models #993, and Grok 4.6 #1113
- French (fr-FR) locale #1068 (by @momo2lajoie), Spanish (Mexico) locale #942 (by @davidmedel), Vietnamese (vi-VN) locale #1025 (by @niitbeo), and 432 reviewed zh-TW translations #526 (by @alvinets)
Bug Fixes
- Persistence: stop corrupting binary response bodies in the route adapter #1088; omit undefined object fields at persistence boundaries #992; bind default fetch to globalThis in both HTTP store clients #984
- Chat: harden runtime sync, legacy migration, and record validation #1050; add opt-in streaming chat compatibility #990
- Access code: refetch server providers after the code is accepted #1081
- Render service: make parallel capture effective #1042; keep the entrypoint LF so the image starts on Windows #1027
- i18n: load every Inter subset so non-Latin text keeps the UI font #1026; translate ASR provider names in the generation toolbar #1028; localize Pro mode right rail labels #1023
- Render whiteboard math via KaTeX instead of raw LaTeX text #938; keep arrowheads visible when toggling thumbnails #1045
- AI: omit zero SiliconFlow thinking budget #1035; harden shared Pi transport contracts #1108
- Importer: handle custom shapes without paths #1015
- Vocational mode: keep the toggle thumb within the track #1032
- Editor packages: add npm provenance metadata #1098
- Release: dedupe the published dsl and close two release-path blind spots #1019; hand published versions to the marker job #1076
Other Changes
- PBL: retire the v1 write path and dead UI, converge on v2 #1060; split the planner core from the loop with an injectable LLM call path #1069; pin single-call prompt goldens #1071; route runtime agents through the shared LLM entry point #1006
- Document transform pipeline foundation #920; choreography overlays driven from descriptors #947; single-source the generated agent roster on the stage document #994
- Publish validated package tarballs #1040; publish storage and enforce version bumps #998; publish the OpenMAIC skill to ClawHub #1056
- Docs refresh and synchronization #996; align the environment variable template #1107; stabilize the Hyperframes lint command #1097
[0.3.1] - 2026-07-21
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
[0.3.0] - 2026-06-28
License
- Relicense the project from AGPL-3.0 to MIT
Breaking Changes
- Remove
allow-same-originfrom the interactivesrcDociframe sandbox for tighter isolation; interactive widgets that relied on same-origin access may need updates #726 (by @sebastiondev) - Restructure the slide DSL and renderer into standalone
@openmaic/*packages consumed by the app; the inline DSL shim is removed #707 #738
Features
- Project-Based Learning (PBL) v2 — Add the PBL v2 core schema and generation path #795 (by @cosarah), runtime APIs with classroom UI #799 (by @cosarah), in-timeline discussion authoring #798, auto-retry for transient scene-generation failures #788 (by @YizukiAme), and a planner eval harness #803 #805 (by @cosarah)
- Edit with AI — Add a Pro-mode editor agent that edits generated slides from a chat prompt #777
@openmaic/*SDK on npm — Publish the DSL, renderer, and importer SDK family to npm #778 #780, introduce themaic-import/maic-rendererworkspace packages #668 (by @xuyuanwei678), and promote the Stage/Scene lesson skeleton into@maic/dsl#740- Add optional per-stage LLM model routing #745
- Add GLM-5.2 and Kimi K2.7 Code #774, and Qwen3.7 Plus and Qwen3.7 Max #753, to the model registry
- Add a vocational-learning task engine with procedural skill widgets #685 (by @jackefn)
- Add Korean (ko-KR) translation #733 (by @moduvoice)
- Improve TTS with per-agent auto-voice quality and stable timbre registration #670, and unify the provider-enablement model with browser-native TTS off by default #665
- Add opt-in parallel scene-content generation #660 (by @ly-wang19)
- Add a document extractor provider foundation #704 (by @jackefn)
- Infer concise course titles from outlines for more readable course names #756
- Refactor widget actions into the unified scene action pipeline #796
Bug Fixes
- Importer: port PPTX shape-restoration hotfixes #789 (by @xuyuanwei678), fix hanging-indent bullet rendering #727 (by @xuyuanwei678), and guard SVG export against arc-first paths #638 (by @ly-wang19)
- Generation: make outline type changes take effect so interactive/PBL outlines are no longer downgraded to slides #772, stop regenerating deleted slides on finished decks #769, show full key-point text in the outline editor #782, and linearize outline streaming and interactive post-processing for better performance #732
- Agent: respond to the user's turn before lecturing #699, and constrain action narration to a single teacher voice #671
- Editor: stop dumping the raw tool-failure blob in AI edit tool cards #785, persist AgentBar voice and mode selections across reloads #723, and keep the edit runtime alive across read-only scenes #802 (by @cosarah)
- Audio: gate the speech button on ASR availability #711, revoke blob URLs when playback is rejected #652 (by @ly-wang19), and surface TTS provider rate limits as HTTP 429 #644 (by @ly-wang19)
- Renderer: make the code entrance animation play line by line #724 (by @tongshu2023)
- Security: point the SSRF local-network rejection at the
ALLOW_LOCAL_NETWORKSescape hatch #667 (by @mvanhorn) - Networking: bypass the proxy for loopback hosts and honor
NO_PROXY#718 (by @tongshu2023) - Fix overlay layout shift on the home and classroom pages #690 (by @cosarah)
Other Changes
- Drop the dead
ThumbnailSlidepath and fix@maic/dslNode ESM resolution #736 - Docs: correct the stale i18n location and supported-language list #640 (by @ly-wang19)
[0.2.2] - 2026-06-02
Features
- MAIC Editor (v0) — slide editing surface — A new Pro Mode toggle turns any generated slide into an editable canvas: select and edit text, insert text boxes and images, navigate and reorder slides from a thumbnail rail, with history-aware undo/redo. This is the first surface of the broader MAIC Editor framework (gated behind
NEXT_PUBLIC_MAIC_EDITOR_ENABLED) #615 - Editable outline before generation — The streaming course outline now morphs into an inline editor: review, edit, reorder, and add or delete scenes and bullet points, then confirm to generate the full course — so you catch structure problems before spending a full generation #558
- Offline-ready classroom export — Exported teaching resource packs and classroom ZIPs now inline external assets so interactive pages open fully offline, even when copied to another machine #613
- Add Claude Opus 4.8 and MiniMax M3 to the default model registry #635
- Add Gemini 3.5 Flash #584
- Add Xiaomi MiMo Token Plan support #578 (by @xuruiray)
- Add web search providers: Brave and Baidu #42 (by @YizukiAme), Bocha #524, and MiniMax #634
- Add Azure STT (Fast Transcription) as a speech-to-text provider #175 (by @ismailariyan)
- Add HappyHorse video adapter #509 (by @xuruiray) and Lemonade as an LLM provider #508
- Add OpenAI image generation environment-variable fallback #510 (by @xuruiray)
- Add generated-video manifest references so produced videos survive export/import #540
- Add Traditional Chinese (zh-TW) #517 (by @alvinets) and Brazilian Portuguese (pt-BR) #602 (by @hemanz) interface languages
Bug Fixes
- Server-configured providers are now admin-managed — providers set via server environment can no longer be overridden by client settings, preventing base-URL/key tampering on shared deployments #624; fixes server API-key fallback when the client echoes the provider base URL #533 (by @LooThao); auto-selects the server LLM model #577 (by @xuruiray); and enforces a "usable provider ⇒ concrete model" invariant #581
- Keep interactive scenes alive across remounts with an iframe keep-alive pool, so interactive content no longer reloads when navigating #629
- Restore the orchestration director's ability to answer the user's question and stop runaway turns (removed
maxTurns) #599; restore agent attribution in the director summary #554 (by @ashutoshrana) - Skip shapes with malformed SVG paths instead of aborting the whole PPTX export #505; prevent memory leaks and silent export failures #552 (by @arnow117)
- Add defensive checks in ChartElement to prevent crashes on malformed chart data #588 (by @tongshu2023)
- Let whiteboard code elements capture internal scroll/drag instead of the canvas #544 (by @cosarah)
- Preserve discussion triggers when importing classroom ZIPs #557 (by @cosarah)
- Fix generated video thumbnails #546
- Gate media snippets in the interactive-outlines prompt template #628
- Hide the unsupported MiniMax Hailuo fast text-to-video model #632; remove weak Lemonade recommended models #567 (by @cosarah)
- Fix Haiku 4.5 thinking controls #501
- Use an ESM import for TypeScript in the pptxgenjs rollup config #616
- Align zh-TW provider names with the rest of the locale set
Other Changes
- Add a Fumadocs-based documentation site #622
- Add a VoxCPM2 setup guide and tighten the README section #500 #502
- Fix the commercial licensing contact email #604 (by @DHQ1204)
[0.2.1] - 2026-04-26
Features
- VoxCPM2 TTS provider with voice cloning — OpenMAIC adapts to user-managed VoxCPM backends (vLLM-Omni, Nano-VLLM, official Python API). Clone any voice from a reference audio clip you upload or record in the browser, or let Auto Voice generate a fitting voice from each agent's persona at synthesis time. Voice profiles are stored locally to keep the serverless setup model. The Agent Bar exposes a searchable, previewable voice picker that draws from the global VoxCPM voice pool #496
- Per-model thinking configuration — First-class metadata for each model's reasoning capability (effort levels, on/off toggle, adjustable budget, or fixed thinking) flows through chat and all generation paths and is mapped to the right provider-specific request fields (Anthropic
thinking, OpenAIreasoning, etc.). The model selector becomes a unified provider/model/thinking popover with compact search and a much smaller toolbar footprint #494 - End-of-course completion page with persistent quiz state — When the outline is fully materialized, students see a course-complete view with quiz score card, scene-type stat cards, and a (motion-respecting) confetti celebration. Quiz answers persist on submit and grading results persist on completion, so navigating away and back restores the reviewing state with AI feedback intact instead of resetting #484
- Add latest released models including GPT-5.5, DeepSeek-V4 (
-pro,-flash), Xiaomi MiMo (mimo-v2.5-pro,mimo-v2.5), Tencent Hy3, and OpenRouter as a multi-provider gateway #481 #487 - Add OpenAI image generation (GPT-Image-2) as a media provider #481
- Refresh built-in model registries across Anthropic, DeepSeek, Kimi, Qwen, MiniMax, Grok, OpenAI, GLM, SiliconFlow, and Ollama; persisted local settings now rehydrate in registry order so newly curated lists appear consistent without clearing state #481
- Add inline search for recent classrooms on the home page with deferred filtering by name and description, keyboard-driven open/clear/collapse #476
- Add Deep-Interactive badge on classroom thumbnails for sessions generated with Interactive Mode #478
- Replace always-included media instruction blocks in generation prompts with conditional snippet includes gated on
imageEnabled/videoEnabled— disabled capabilities are removed from the prompt entirely instead of relying on negative-override directives the model often ignored #490 (by @YizukiAme)
Bug Fixes
- Fix language drift between outline and scene generation by unifying the languageDirective across the pipeline so the same target language flows from outline planning through every per-scene call #474
Other Changes
- Refactor whiteboard role prompts to file-based markdown templates and add a geometry-conflict detector (overlap, line-through-bbox, canvas clipping) that surfaces problems back to the model. Eval (flash, repeat 3, gemini-3.1-pro scorer) shows overall quality 5.4 → 6.1 and overlap 6.3 → 8.1 from prompt + detector alone #485
- Migrate orchestration prompt builders (
buildStructuredPrompt,buildDirectorPrompt,buildPBLSystemPrompt) from inline TS template literals to file-based markdown templates underlib/prompts/, sharing the loader infrastructure with the generation pipeline.prompt-builder.ts890 → 314 lines; future content tweaks land as markdown edits #459
[0.2.0] - 2026-04-20
Features
- Deep Interactive Mode — Generate hands-on interactive scenes (3D visualization, simulation, game, mind map/diagram, online programming) with an AI teacher who operates the UI to guide students. Fully responsive across desktop, tablet, and mobile #461
- Add code element support on the whiteboard — AI agents can write, display, and reference runnable code during lessons #385 (by @cosarah)
- Add Arabic (ar-SA) interface language #431 (by @YizukiAme)
- Add MinerU Cloud API as a PDF parsing provider, with a dedicated settings UI #438
- Add latest OpenAI models to the default config #416 (by @donghch)
- Add GLM-5.1 and GLM-5V-Turbo to GLM preset models #437
- Add international base URL shortcuts for GLM, Kimi, and MiniMax in provider settings #449
- Add anti-framing security headers (X-Frame-Options + CSP
frame-ancestors) with an optionalALLOWED_FRAME_ANCESTORSoverride #430 (by @YizukiAme) - Add i18n key alignment check to CI so missing or extra translation keys fail the build #447 (by @KanameMadoka520)
- Add whiteboard layout quality eval harness and unify it with the outline-language harness #425 #453
Bug Fixes
- Fix classroom ZIP export to use the latest classroom name from IndexedDB #435
- Fix spotlight cutout for text elements and add element-content variant for image/video #457
Other Changes
- Renew the README with Deep Interactive Mode showcase and visual assets #463 (by @Shirokumaaaa)
- Update Discord invite links across README, CONTRIBUTING, and issue templates
[0.1.1] - 2026-04-14
Features
- Add inline language inference for outline and PBL generation, replacing manual language selector #412 (by @cosarah)
- Add ACCESS_CODE site-level authentication for shared deployments #411
- Add classroom export and import as ZIP #418
- Add custom OpenAI-compatible TTS/ASR provider support #409
- Add Ollama as built-in provider with keyless activation #94 (by @f1rep0wr)
- Add Japanese (ja-JP) locale #365 (by @YizukiAme)
- Add Russian (ru-RU) locale #261 (by @maximvalerevich)
- Migrate i18n infrastructure to i18next framework #331 (by @cosarah)
- Add MiniMax provider support #182 (by @Hi-Jiajun)
- Add Doubao TTS 2.0 (Volcengine) provider #283
- Add configurable model selection for TTS and ASR #108 (by @ShaojieLiu)
- Add context-aware Tavily web search when PDF is uploaded #258 (by @nkmohit)
- Add course rename #58 (by @YizukiAme)
- Add end-to-end generation happy path test #405
Bug Fixes
- Fix DNS rebinding bypass in SSRF validation #386 (by @YizukiAme)
- Add ALLOW_LOCAL_NETWORKS env var for self-hosted deployments #366
- Fix custom provider baseUrl not persisting on creation #417 (by @YizukiAme)
- Hide Ollama from model selector when not configured #420 (by @cosarah)
- Fix agent configs not persisting in server-generated classrooms #336 (by @YizukiAme)
- Fix action filtering logic and add safety improvements #163 (by @zky001)
- Fix modifier-key combos triggering single-key shortcuts #359 (by @YizukiAme)
- Fix agent mode selection for conditionally set generatedAgentConfigs #373 (by @YizukiAme)
- Unify TTS model selection to per-provider and fix ElevenLabs model_id #326
- Allow model-level test connection without client-side API key #309 (by @cosarah)
- Add structured request context to all API error logs #337 (by @YizukiAme)
- Fix breathing bar background color in roundtable #307
Other Changes
- Add missing Ollama and Doubao provider names for ru-RU #389 (by @cosarah)
- Update Ollama logo to official version #400 (by @cosarah)
- Remove deprecated Gemini 3 Pro Preview model #142 (by @Orinameh)
- Update expired Discord invite link
- Create SECURITY.md #281 (by @fai1424)
New Contributors
@f1rep0wr, @maximvalerevich, @Hi-Jiajun, @cosarah, @zky001, @Orinameh, @fai1424
[0.1.0] - 2026-03-26
The first tagged release of OpenMAIC, including all improvements since the initial open-source launch.
Highlights
- Discussion TTS — Voice playback during discussion phase with per-agent voice assignment, supporting all TTS providers including browser-native #211
- Immersive Mode — Full-screen view with speech bubbles, auto-hide controls, and keyboard navigation #195 (by @YizukiAme)
- Discussion buffer-level pause — Freeze text reveal without aborting the AI stream #129 (by @YizukiAme)
- Keyboard shortcuts — Comprehensive roundtable controls: T/V/Esc/Space/M/S/C #256 (by @YizukiAme)
- Whiteboard enhancements — Pan, zoom, auto-fit #31, history and auto-save #40 (by @YizukiAme)
- New providers — ElevenLabs TTS #134 (by @nkmohit), Grok/xAI for LLM, image, and video #113 (by @KanameMadoka520)
- Server-side generation — Media and TTS generation on the server #75 (by @cosarah)
- 1.25x playback speed #131 (by @YizukiAme)
- OpenClaw integration — Generate classrooms from Feishu, Slack, Telegram, and 20+ messaging apps #4 (by @cosarah)
- Vercel one-click deploy #2 (by @cosarah)
Security
- Fix SSRF and credential forwarding via client-supplied baseUrl #30 (by @Wing900)
- Use resolved API key in chat route instead of client-sent key #221
Testing
New Contributors
@YizukiAme, @nkmohit, @KanameMadoka520, @Wing900, @Bortlesboat, @JokerQianwei, @humingfeng, @tsinglua, @mehulmpt, @ShaojieLiu, @Rowtion