Skip to content

Releases: THU-MAIC/OpenMAIC

OpenMAIC v1.2.1 — Web research: Kimi, DeepSeek and Firecrawl

Choose a tag to compare

@wyuc wyuc released this 18 Oct 13:19
e19d0d4

1.2.1 is a regular patch release. Its main theme is web research: Kimi, DeepSeek and Firecrawl join as web-search providers, and a new webFetch slot lets the agent's fetch_url tool use a hosted reader instead of the built-in one. It also contains one breaking change, the removal of the legacy director-graph classroom chat (#1913), and removes retired models from the built-in catalogs (#1939). Read Breaking Changes before upgrading from 1.2.0.

Breaking Changes

  • The legacy director-graph classroom chat is removed; classroom chat always runs on Pi. #1913
    • Pi needs a Classroom model with tool calling: select one for Classroom in Course Model Config, or set the classroom slot (or the llm slot it inherits from) in openmaic.yml. For Gemini, use the native google preset.
    • Remove NEXT_PUBLIC_PI_CHAT_ENABLED. A production build accepts only unset, an empty string, true or 1 (exact match) and fails with migration guidance on any other value. The Docker build arg and its Compose forwarding remain only to carry the value to that check.
    • POST /api/chat is removed and answers 404. With ACCESS_CODE set, an unauthenticated request still gets 401 first.

Highlights

  • Web research. Every new provider is opt-in or must be assigned; existing search defaults and the keyless builtin reader stay as they are.
    • webFetch slot. The reader behind the agent's fetch_url tool is now a capability slot with its own provider registry. It defaults to builtin (the existing local reader); webFetch: null in openmaic.yml removes the tool. Kimi is the first hosted reader, reusing the kimi or kimi-coding-plan credentials. Choose the reader in Course Model Config → Web Fetch and enter keys in Settings → Model Services → Web Fetch. URL and private-address checks run before a URL reaches a hosted reader and again on the final URL it reports; each request uses one reader, with no fallback. #1912
    • Kimi web search. Shares the Kimi chat key and base URL; Open Platform keys use Search Pro and Coding Plan keys use the Coding Plan search endpoint. A Kimi chat key alone does not enable search: set WEB_SEARCH_KIMI_ENABLED=true, add web-search.kimi to server-providers.yml, or, with openmaic.yml, assign slots.webSearch to a kimi provider. WEB_SEARCH_KIMI_ENABLED=false turns it off. #1911
    • Token plans can declare web fetch. Connecting Kimi Coding Plan in Settings → Token Plan now assigns web fetch to the plan alongside chat and web search, taking over the implicit builtin default without a conflict prompt; disconnecting returns to the server default. Lock the webFetch slot to keep builtin. #1927
    • DeepSeek web search and fetch. The deepseek preset reuses DEEPSEEK_API_KEY and its API base for both tools. Opt in to search with WEB_SEARCH_DEEPSEEK_ENABLED=true, a web-search.deepseek entry, or an explicit webSearch slot; assign webFetch: deepseek in openmaic.yml for fetch. #1937
    • Firecrawl web search and fetch. One firecrawl provider (preset: firecrawl) serves both webSearch and webFetch with one key. FIRECRAWL_API_KEY / FIRECRAWL_BASE_URL configure it in legacy setups, where it comes last in the search preference order; web fetch stays on builtin until webFetch is assigned to it. A self-hosted Firecrawl base must be declared in openmaic.yml. #1931 #1834 (by @JuampiHernandez)

Features

  • Classroom chat: cue_user can offer 2 to 4 suggested replies, shown as one row of buttons in the roundtable. Choosing one sends it as an ordinary learner message; learners can still type their own reply. #1379 (by @yanpgwang)

Bug Fixes

  • Chat: on plain HTTP at a non-localhost address (a LAN or Tailscale IP, for example), where the browser has no Web Locks, classroom chats failed to load and every save retried in a loop. Chats now save and load there; two tabs on the same chat resolve last-write-wins. The deployment guide recommends HTTPS for phones and tablets. #1929
  • i18n: the server picks the initial language from the locale cookie, then Accept-Language, and sets <html lang> to match, so server and client render the same language: a browser in another language no longer gets Chinese server HTML that switches after load. / and /_not-found now render dynamically. #1874 (by @costajohnt)
  • Generation: a non-numeric or non-finite shape rotate is reported as a model-output error with its element path instead of silently becoming 0; a missing or null angle still means 0 (@openmaic/generation 0.3.21). #1891 (by @Hahaa909)
  • Roundtable: the suggested-reply bubble no longer appears stacked with the outgoing chat bubble and then jumps down; it appears once, in place, after the previous bubble has left. #1943

Packages

  • @openmaic/generation 0.3.21 (was 0.3.20). Other packages are unchanged from 1.2.0.

Known issues

  • Google shuts down the Veo 3.1 previews on October 22, 2026; after that the built-in Veo provider has no working model. #1940
  • Qwen voice cloning still uses a retired model, so registering or synthesizing a cloned voice fails until it moves to CosyVoice; TTS_QWEN_VOICE_CLONE_MODEL can point to another model. #1941
  • Volcengine Ark Agent Plan models report no image input, so reference images are dropped for them. #1942

Other Changes

  • Models: remove retired entries from the built-in catalogs and presets (existing saved IDs remain user-managed): #1939
    • deepseek: deepseek-v4-flash, deepseek-v4-flash-vision-exp. Use deepseek-flash.
    • qwen: qwen3.6-max-preview, qwen3-max. Use qwen3.7-max.
    • kimi: kimi-k2.5, kimi-k2-thinking. Use kimi-k3.
    • siliconflow: deepseek-ai/DeepSeek-R1-Distill-Qwen-7B, Pro/moonshotai/Kimi-K2.5, THUDM/GLM-4.1V-9B-Thinking, THUDM/GLM-Z1-Rumination-32B-0414. Use an available model from the provider catalog.
    • grok: grok-4-1-fast-reasoning, grok-4-1-fast-non-reasoning, grok-code-fast-1. Use grok-4.3 or grok-build-0.1.
    • grok-image: grok-imagine-image-pro. Use grok-imagine-image.
    • tencent-hunyuan: hy3-preview; also remove hunyuan-2.0-thinking-20251109 and hunyuan-2.0-instruct-20251111 from environment examples. Use hy3.
    • xiaomi: mimo-v2-pro, mimo-v2-omni, mimo-v2-flash. Use mimo-v2.6-pro or mimo-v2.6-flash.
    • doubao: doubao-seed-1-8-251228. Use doubao-seed-evolving.
    • seedream: doubao-seedream-3-0-t2i-250415. Use doubao-seedream-5-0-260128.
    • seedance: doubao-seedance-1-5-pro-251215. Use doubao-seedance-2-0-mini-260615. Keep doubao-seedance-1-0-lite-t2v-250428 while its status is Retiring, not Shutdown.
    • qwen-image: qwen-image-max, qwen-image-max-2025-12-30, qwen-image-plus, qwen-image-plus-2026-01-09, qwen-image. Use qwen-image-3.0.
    • nano-banana: gemini-3.1-flash-image-preview, gemini-3-pro-image-preview. Use gemini-nano-banana-2.1 or gemini-3-pro-image.
    • veo: veo-3.0-fast-generate-001, veo-3.0-generate-001, veo-2.0-generate-001. Use veo-3.1-generate-preview (scheduled to retire October 22, 2026).
    • qwen-tts: qwen3-tts-instruct-flash, qwen-tts. Use qwen3-tts-flash.
    • Ark Agent Plan doubao: doubao-seed-2.1-turbo, doubao-seed-2.0-pro, doubao-seed-2.0-code, doubao-seed-2.0-lite, deepseek-v3.2, minimax-m2.7, glm-5.2, glm-5.1, kimi-k2.6. Use doubao-seed-2.1-pro, deepseek-v4-pro or minimax-m3.
    • Ark Agent Plan seedream: doubao-seedream-5.0-lite. Use doubao-seedream-5.0-pro.
    • Ark Agent Plan seedance: doubao-seedance-1.5-pro. Use doubao-seedance-2.0-mini.
    • Removed IDs that vendors route to a catalog successor resolve to it for capability lookups, so saved configurations keep image input, thinking controls and reasoning replay: deepseek-v4-flash and deepseek-v4-flash-vision-exp → deepseek-flash, hy3-preview → hy3, grok-code-fast-1 → grok-build-0.1, Ark Agent Plan glm-5.2 → glm-5.3.
    • grok-4-1-fast* (served as grok-4.3 at a fixed reasoning effort) and SiliconFlow Pro/moonshotai/Kimi-K2.5 remain valid in saved configurations. They lose catalog capability metadata, including image input and thinking controls; reselect a replacement model to restore that metadata.
    • Retain qwen3-tts-vc-2026-01-22 as the non-selectable grouping ID for saved cloned voices. The model has retired: clone registration and synthesis fail until migration to CosyVoice. TTS_QWEN_VOICE_CLONE_MODEL can point to another model.
    • Keep upcoming retirements in the catalog: MiMo V2.5 / V2.5 Pro on October 21, 2026; Veo 3.1 Fast / Standard / Lite previews and Doubao Seed 2.0 Lite / Mini on October 22, 2026; gpt-image-1 on October 23, 2026. Google's recommended Veo replacement, gemini-omni-1.1-flash, is not yet supported by the Veo adapter.
    • Ark Agent Plan: add the officially listed migration targets doubao-seed-2.1-lite, glm-5.3, kimi-k3 and kimi-k2.8-preview (the Small-tier replacement for kimi-k2.7-code).
    • Keep models with future retirement dates and unverified entri...
Read more

OpenMAIC v1.2.0 — Server-first, with classroom export

Choose a tag to compare

@wyuc wyuc released this 16 Oct 04:06
a9da60b

Up to 1.1.x the browser drove course generation one request per step and kept the courses, the provider keys and the model settings itself. Closing the tab stopped a course halfway, every browser had to be set up on its own, a deployment could offer providers but not fix which models its users get, and the headless API ran a separate pipeline that drifted from the web app. 1.2.0 moves all of this to the server: courses and media, identity, model configuration and course generation live there, and the browser is a client. Classrooms can now also leave OpenMAIC: as a PPTX that keeps every scene, or as one offline HTML file that plays the lesson.

The cost is the deployment shape: 1.2.0 needs PostgreSQL and a long-running Node.js server. Serverless hosts, Vercel included, stay on 1.1.x. Read Breaking changes and Before you upgrade first, then follow the deployment guide's Upgrading from 1.1.x.

Design: RFC #1754 (release), #1701 (model configuration) and #1809 (classroom export).

Highlights

  • Generation runs on the server. Classic generation is a server-side run that keeps going when the page is closed, resumes from its last checkpoint after a restart or a crashed worker, streams progress to every open tab, and pauses at a failed step so that Retry re-runs only that step. Images and videos are generated alongside the scenes, and a single failed item can be retried. The web app and the headless API share one pipeline. #1756 #1759 #1761
  • Models are configured on the server. openmaic.yml declares providers and capability slots (llm with course.*, classroom and agent, plus tts, asr, image, video, webSearch and document). slots are defaults users may change, lock fixes slots for everyone, and allowUserKeys: false keeps users from adding their own providers. Settings take the matching shape (set it up yourself, choose a model or configured by the administrator), and keys are stored encrypted on the server and never leave it. #1727 #1733 #1767 #1793
  • Materials are parsed as soon as they are attached. The composer uploads and parses each file in place and shows progress, Ready, or Failed with Retry; Generate waits until every file is ready, and the preview opens without a material-analysis step. #1796
  • Identity and persistence. Three identity modes: single-user for personal installations (the Docker Compose default), anonymous visitors (the cookie now lasts 400 days and is renewed while in use), and accounts through host auth methods. Anonymous work can be claimed into an account with POST /api/identity/claim. Courses, media, custom agents and model settings are stored on the server, the database schema is versioned, and the first load after the upgrade moves each browser's data to the server once. #1757 #1758
  • Classroom export.
    • The PPTX keeps the whole lesson. Interactive, quiz and PBL scenes stay in place as placeholder slides with an Open online button and a QR code that open the scene in the online classroom. Export PPTX and Export Resource Pack offer placeholder slides (recommended) or slides only. #1811 #1819 #1823 #1693
    • Offline HTML. One self-contained file that plays the classroom without a network connection: narration with captions, spotlight and laser, auto-advancing slides, slide video, discussion cards and interactive widget actions; quiz, interactive and PBL scenes hold until the learner moves on. Export with narration and video or without narration. Classrooms over 400 MB are exported as a ZIP of classroom.html and its media folders. #1813 #1842 #1845 #1848 #1850
  • Inline math survives saving. Formulas typed in the slide text editor are stored as LaTeX source and typeset by the clients, render-service previews and the PPTX export follow, and every KaTeX/Temml path disables formula-defined macros. #1829 #1904 #1827

Security

1.2.0 includes every fix of the 1.1.x security releases, and these advisories:

  • GHSA-r2xp-m5r2-g7xj (High): callers could use server-managed provider credentials with arbitrary models. Model authorization is now enforced for server-managed providers across chat, media, speech, model-based web search and workspace assignments. Reported by @13ob0. #1879
  • GHSA-x3gm-gw9m-94h9 (Medium): MP4 render jobs were not bound to the requesting owner. Reported by @Duang777. #1884
  • GHSA-6jrw-cp5x-j8jc (Low): deleted courses did not revoke legacy classroom media URLs. Reported by @Duang777. #1883
  • GHSA-6c52-8h4v-5xvg (High): stored XSS in slides loaded through /api/persistence. Fixed in 1.1.3 and in this line since 1.2.0-rc.1. #1799

Hardening since rc.2: user-authored skill content is fenced with an unforgeable end marker #1816, formula-defined macros are disabled in every math renderer #1827, and CSS escapes are refused in inline styles #1815.

Breaking changes

  • PostgreSQL and a long-running server are required. DATABASE_URL is mandatory. Deploy with Docker (docker compose up now includes PostgreSQL and runs single-user on 127.0.0.1) or with pnpm start. NEXT_PUBLIC_PERSISTENCE and vercel.json are removed.
  • MODEL_ROUTES without openmaic.yml stops the server at startup. Deployments running the Pro agent must write openmaic.yml first; the route-to-slot table is under "Migrating from the legacy configuration" in the configuration docs. Without openmaic.yml, the provider variables, server-providers.yml, DEFAULT_MODEL and MODEL_FALLBACK keep working but are deprecated.
  • Providers with server-managed credentials need an explicit model list (*_MODELS, or models under the provider in openmaic.yml / server-providers.yml). Without one, only default, fallback and slot references are authorized. A startup warning names each provider that has credentials but no list.
  • Upgrade the render-service together with or before the app. Render jobs are owner-bound, and old/new mixes fail closed.
  • The browser no longer sends provider settings. The x-api-key, x-model, x-base-url, x-model-routes, x-image-* and x-video-* headers and the matching body fields are deprecated, honoured only for a slot with nothing assigned and never under allowUserKeys: false.
  • Headless API. POST /api/generate-classroom takes { requirement, materialIds? }; upload documents first with POST /api/materials (pdfContent is refused). Job ids are run ids, so earlier job ids answer 404. Every capability the server configures runs (GET /api/generate-classroom/capabilities reports which). In anonymous-cookie mode, keep one cookie jar for the upload, the submission and the polls.
  • Routes removed: /api/generate/{scene-outlines-stream,agent-profiles,scene-content,scene-actions}, /api/extract-document, /api/web-search, and GET / POST /api/classroom. Use /api/generation-runs.
  • A course is read-only while it is being generated (409 COURSE_GENERATING for other writers).
  • Runtime sessions are keyed by the resolved owner. PERSISTENCE_DEV_TOKEN, NEXT_PUBLIC_PERSISTENCE_TOKEN and PERSISTENCE_ALLOW_INSECURE_DEV_AUTH are removed. If the token was your only access gate, put the deployment behind ACCESS_CODE, a gateway or owner auth methods first.
  • Assets belong to an owner; ASSET_QUOTA_BYTES is a per-owner limit.
  • Pi classroom chat refuses models that cannot call tools (tool_calling_required) and Google's OpenAI-compatible Gemini endpoint (gemini_native_required); use the native google preset for Gemini. #1894 #1897
  • Embedders: @openmaic/storage 0.32–0.37 moves document ownership to the documentOwnership relation, drops the IndexedDB fallback of the browser storage seams, and removes ServerPersistenceProvider.documentStore.

Before you upgrade

  • Back up the database. The fir...
Read more

v1.2.0-rc.2 — Security

Pre-release

Choose a tag to compare

@wyuc wyuc released this 11 Oct 08:01
153d084

Security release candidate for 1.2.0. It fixes three vulnerabilities reported privately; see the advisories below.

Upgrade notes

  • Providers that use server credentials now need an explicit model list (*_MODELS or models); without one only default/fallback models are usable. See the breaking-change section below.
  • Upgrade the render-service together with or before the app.

Thanks to @13ob0 and @Duang777 for the reports and fixes.

Advisories

Security

  • Enforce model authorization for server-managed providers across chat, media, speech, model-based web search and workspace model assignments. Unauthorized and unknown model ids return the same HTTP 403 response before provider access. Users' own credentials continue to work. #1879 (with @13ob0)
  • Render jobs are bound to the requesting owner. The render-service and app must be upgraded together; upgrade every service instance (or drain old instances) together with or before the app. Old/new version mixes fail closed through a dedicated owner-bound job namespace. #1884 (by @Duang777)
  • Deleted courses no longer serve their legacy classroom media: /api/classroom-media/<id>/... checks the course lifecycle before touching the filesystem and answers a tombstoned course with the same 404 as a missing file. Successful responses are private, max-age=300, must-revalidate instead of public, immutable. #1883 (by @Duang777)

Breaking change: server-managed model authorization

  • Set *_MODELS for every provider with server-managed credentials, or set models under each provider in openmaic.yml / server-providers.yml. Without a list, only deployment default/fallback and capability slot references authorize models; preset catalogues and workspace assignments do not. Provider-only media slots authorize a single adapter default. Services without model ids need no list. Providers configured without credentials (local Ollama, Lemonade) are not restricted; a keyless gateway that adds its own upstream credential should be given a key and a model list.
  • Migration: list the model ids users should be able to select (including voice compatibility models), restart the server, then update workspace selections that are no longer authorized. A startup warning names the configuration setting for each provider with credentials but no explicit list.

Bug Fixes

  • S3 asset storage: @openmaic/storage 0.37.3 supports path-style addressing for S3-compatible object stores such as MinIO and Ceph. Set AWS_S3_FORCE_PATH_STYLE=true (or 1) together with AWS_ENDPOINT_URL_S3 so objects are addressed as endpoint/bucket/key; leaving it unset keeps the existing behaviour for Amazon S3 (#1686).
  • Server persistence: @openmaic/storage 0.37.2 bounds HttpDocumentStore requests with a deadline (requestTimeoutMs, default 30s, <= 0 disables) covering the request round trip — sending the body and receiving the response headers — so a persistence endpoint that stops answering fails like any other transport error instead of holding its caller forever. The stage autosave keeps at most one save in flight and starts the next only once that promise settles, so a request that never settled silently stranded every later save for the life of the page while the editor went on rendering the in-memory document; the reload showed what had actually reached the server. A request aborted at the deadline rejects with HTTP_REQUEST_TIMEOUT, which the autosave's existing backoff retries. The budget is the floor plus an allowance proportional to the request body (sized at a fixed 100 KiB/s) and is capped at 10 minutes, so a large document on a slow link is not mistaken for a stall; reading the response body stays outside the bound. This mirrors the budget HttpAssetStore already applies through probeTimeoutMs / startBoundedOperation.
  • Synchronous scene previews and video exports no longer block each other; each uses its own execution lane. #1830
  • Preview concurrency is capped by the render resource profile and reported by /health. Cancelling a preview during Chromium startup retains its execution slot until launch and browser cleanup settle.

OpenMAIC v1.1.4 — Security

Choose a tag to compare

@wyuc wyuc released this 11 Oct 09:40
39d04dd

A security release. Providers that use server credentials only send models the deployment authorizes, render jobs are bound to the requesting owner, and deleted courses stop serving their legacy media. Read Breaking change before upgrading, and upgrade the render-service together with or before the app. The same fixes ship in v1.2.0-rc.2. Thanks to @13ob0 and @Duang777 for the reports.

Advisories

Security

  • Render jobs are bound to the requesting owner. Upgrade every render-service instance (or drain old instances) together with or before the app. Mixed service versions fail closed through a dedicated owner-bound job namespace.
  • Legacy classroom media stops being served when its course is deleted. Media responses use private caching with revalidation, and lifecycle lookup failures fail closed.
  • Providers using server credentials now authorize the selected model before provider access across chat, generation, media, voice, transcription, search and connection tests. Model authorization refusals return the same HTTP 403 PROVIDER_DISABLED response. Users' own credentials and keyless providers are unaffected.

Breaking change: server-managed model authorization

  • Configure *_MODELS or each provider's YAML models list. Without a list, chat authorizes only DEFAULT_MODEL and operator MODEL_ROUTES references; other model-selecting capabilities authorize only their single default. Preset catalogues do not grant access. Services without model selection need no list.
  • With an explicit list, TTS, ASR, image, video and Claude web search use a listed client choice or substitute the first listed model for an unlisted or missing choice. Speech preview, narration and transcription send catalogue defaults on the 1.1.x client: put the desired pinned model first, without needing to list the client default. Unlisted models never reach the provider with server credentials.
  • Qwen clone voices map the built-in clone sentinel to the configured TTS_QWEN_VOICE_CLONE_MODEL before authorization. Include the final clone target in the TTS model list; the override alone does not authorize it.
  • Migration: list all selectable model ids, including voice compatibility models, restart the server, and update saved chat selections and capability selections without explicit lists outside the authorized set. Startup warnings identify credentialed model-selecting providers without a list. Give a gateway that adds upstream credentials a key and a model list, or restrict models in the gateway itself.

OpenMAIC v1.1.3 — Security

Choose a tag to compare

@wyuc wyuc released this 05 Oct 09:44

A security release. Course documents served by /api/persistence now carry only the slide HTML the renderer produces, on every write and every read. Read Behavior Changes before upgrading.

Security

  • Course documents: with server persistence enabled, /api/persistence/documents/... stored and returned slide HTML without sanitizing it. Document reads are capability-by-id, so anyone with a course link loads that course, and the classroom renders slide text, shape text, table cells and LaTeX snapshots as HTML. A course written through this path could therefore run script in the browser of anyone who opened its link. The owner-bound document store now applies the same sanitization policy as /api/classroom to the stage and scenes on every write and every read, so new documents are stored clean and documents stored earlier are served clean. GHSA-6c52-8h4v-5xvg #1799

The same fix ships in v1.2.0-rc.1.

Behavior Changes

  • Slide HTML written through /api/persistence is reduced to the renderer's formatting vocabulary (the policy /api/classroom already applies): scripts, event-handler attributes, javascript: URLs and embedded objects are removed, and inline styles are re-serialized without spaces (text-align: center; becomes text-align:center). Formatting the editor produces is kept.
  • Documents already stored are not rewritten in the database; they are sanitized when read, and stored clean the next time they are saved.

v1.2.0-rc.1 — server-first (release candidate)

Choose a tag to compare

@wyuc wyuc released this 04 Oct 14:41
636fab0

The release candidate for 1.2.0, server-first.

Up to 1.1.x the browser drove course generation one request per step and kept the courses, the provider keys and the model settings itself. Closing the tab stopped a course halfway, every browser had to be set up on its own, a deployment could offer providers but not fix which models its users get, and the headless API ran a separate pipeline that drifted from the web app. 1.2.0 moves all of this to the server: courses and media, identity, model configuration and course generation live there, and the browser is a client. Generation becomes a server-side run shared by the web app and the API, and models are configured once per deployment. The cost is the deployment shape: a long-running Node process and PostgreSQL instead of a serverless host.

Design: RFC #1754 (release) and #1701 (model configuration). Read Breaking Changes and Before you upgrade first.

Highlights

  • Generation runs on the server. Classic generation is a server-side run that keeps going when the page is closed, resumes from its last checkpoint after a restart or a crashed worker, streams progress to every open tab, and pauses at a failed step so that Retry re-runs only that step. Images and videos are generated alongside the scenes, and a single failed item can be retried. The web app and the headless API share one pipeline. #1756 #1759 #1761

  • Models are configured on the server. openmaic.yml declares providers and capability slots: llm with course.*, classroom and agent, plus tts, asr, image, video, webSearch and document.

    • slots are server defaults that users may change.
    • lock fixes slots (or all) for everyone.
    • allowUserKeys: false keeps users from adding their own providers.
    • The settings take the matching shape: set it up yourself, choose a model or configured by the administrator.
    • Keys are stored encrypted on the server and never leave it. #1727 #1733 #1767 #1793
  • Materials are parsed as soon as they are attached. The composer uploads and parses each file in place and shows progress, Ready, or Failed with Retry. Generate waits until every file is ready, and the preview then opens without a material-analysis step. Re-uploading the same file reuses the earlier parse. #1796

  • Identity. There are three modes:

    • single-user for personal installations (the Docker Compose default);
    • anonymous visitors, whose cookie now lasts 400 days and is renewed while in use;
    • accounts, through host auth methods.

    Anonymous work can be claimed into an account with POST /api/identity/claim.

  • Custom agents are stored on the server (/api/agents). #1758

  • The database schema is versioned (openmaic_schema_migrations). #1757

  • Upgrades carry browser data to the server. The first load after the upgrade moves the browser's courses, chat, progress, folders, media, custom agents and model settings to the server, once per browser.

Breaking Changes

  • PostgreSQL and a long-running server are required. DATABASE_URL is mandatory.

    • Deploy with Docker (docker compose up now includes PostgreSQL and runs single-user, on 127.0.0.1) or with pnpm start.
    • Serverless hosts, Vercel included, stay on 1.1.x; the README explains how to deploy it.
    • NEXT_PUBLIC_PERSISTENCE and vercel.json are removed.
  • MODEL_ROUTES without openmaic.yml stops the server at startup. Deployments running the Pro agent must write openmaic.yml before upgrading. The route-to-slot table is under "Migrating from the legacy configuration" in the configuration docs. Without openmaic.yml, the provider variables, server-providers.yml, DEFAULT_MODEL and MODEL_FALLBACK keep working, but are deprecated.

  • The browser no longer sends provider settings. The x-api-key, x-model, x-base-url, x-model-routes, x-image-* and x-video-* headers, and the matching body fields, are deprecated.

    • They are honoured only for a slot with nothing assigned.
    • They are never honoured under allowUserKeys: false.
  • Headless API. POST /api/generate-classroom takes { requirement, materialIds? }.

    • Upload documents first with POST /api/materials; pdfContent is refused.
    • Job ids are run ids, so job ids from earlier builds answer 404.
    • The enable*, agentMode and web-search request fields are ignored. Every capability the server configures runs, and GET /api/generate-classroom/capabilities reports which ones.
    • Submissions are checked up front (400 MISSING_MODEL, MISSING_API_KEY, …) and limited per owner (429 ACTIVE_RUN_LIMIT).
    • In anonymous-cookie mode, keep one cookie jar for the upload, the submission and the polls.
  • Routes removed:

    • /api/generate/{scene-outlines-stream,agent-profiles,scene-content,scene-actions}
    • /api/extract-document
    • /api/web-search
    • GET / POST /api/classroom

    Use /api/generation-runs instead.

  • A course is read-only while it is being generated. Other writers get 409 COURSE_GENERATING until its run completes or ends. Deleting the course and moving it between folders stay allowed.

  • Runtime sessions are keyed by the resolved owner. PERSISTENCE_DEV_TOKEN, NEXT_PUBLIC_PERSISTENCE_TOKEN and PERSISTENCE_ALLOW_INSECURE_DEV_AUTH are removed.

    • If the token was your only access gate, put the deployment behind ACCESS_CODE, a gateway or owner auth methods first.
    • Earlier runtime sessions are not migrated.
  • Assets belong to an owner. ASSET_QUOTA_BYTES is a per-owner limit.

  • Interrupted courses are not resumed. Courses interrupted in the browser before 1.2.0 show their remaining scenes as interrupted.

  • Embedders. @openmaic/storage 0.32–0.37 changes:

    • document ownership moves to the documentOwnership relation;
    • the browser storage seams have no IndexedDB fallback;
    • ServerPersistenceProvider.documentStore is removed.

Before you upgrade

  • Back up the database. The first start runs the schema migrations. On a large document_stages table, it builds an index under a write lock; you can build that index concurrently beforehand (see the full notes).
  • Rolling back to 1.1.x needs either the ownership copy-back SQL (under Breaking Changes in the full notes) or that backup.
  • Set OPENMAIC_SECRET_KEY when several replicas share the database, when data/ does not survive a restart, or when the working directory is read-only. Otherwise back up data/instance-secret.key together with the database.
  • Choose an identity mode: single-user, a shared team owner, anonymous, or host auth.
  • Keep data/classrooms. Classrooms stored there are imported once, in the background.
  • Check which capabilities will run. With the legacy configuration, the first configured provider of each kind becomes the server default. Course research then runs whenever web search is configured, and headless jobs use every configured capability. To turn one off for everybody, set its slot to null and list it in lock.
  • Connect PostgreSQL directly or through a session pool. A transaction-mode pooler (PgBouncer pool_mode = transaction) is not supported.
  • Follow the guide. The deployment guide's "Upgrading from 1.1.x" table lists every step.

Known issues

  • Web-search services in Settings → Model Services have no Test connection button.
  • A token plan connected with an invalid key shows as connected; the error appears only when a course is generated.
  • A very short requirement can drift off topic or ignore an explicit slide count.
Full change notes

Breaking Changes

  • Server-backed persistence is always on. Courses, folders and folder membership, chat history and learner runtime, and generated media are stored on the server through /api/persistence; the browser has no storage backend of its own any more. The build-time NEXT_PUBLIC_PERSISTENCE switch is removed (from the client, the Dockerfile and docker-compose.yml) and ignored. The server now requires DATABASE_URL and exits at startup without it ([boot] Invalid server configuration; the server will not start: DATABASE_URL is not set. ...); pnpm db:up / pnpm db:down start and stop a separate development database (the Compose postgres service definition under its own project and volume, openmaic-dev-db), published on 127.0.0.1 (OPENMAIC_DB_PORT, default 5432), for local development; other deployments point DATABASE_URL at a PostgreSQL database they run. Only device-local state stays in the browser (settings, playback position, the editor's current scene and undo history, a local cache of media the server already stores, and browser voice profiles), in a new maic-device-cache IndexedDB database; Settings → Clear Local Cache clears exactly that. Courses an earlier browser-only build stored in the browser are not deleted; the one-way importer below moves them to the server.
  • Docker Compose: docker compose up now starts PostgreSQL (no profile) and a server-backed app (DATABASE_URL set from PERSISTENCE_POSTGRES_PASSWORD) that waits for PostgreSQL to be healthy, in single-user mode (docker-compose.defaults.env, read before .env.local so it can be overridden there). The app port is published on 127.0.0.1 only; start with `O...
Read more

OpenMAIC v1.1.2 — Security

Choose a tag to compare

@wyuc wyuc released this 28 Sep 10:10

A security release. Server-side requests to provider URLs that a caller can choose now connect only to the addresses that passed validation and refuse redirects, and error responses no longer carry provider response bodies or connection details. Read Behavior Changes before upgrading.

Security

  • Provider connections: when a provider is not configured on the server, the settings UI can supply its own base URL, endpoint or model. Several routes validated such a URL once and then connected with a transport that resolved DNS again or followed redirects: PDF parsing and connectivity checks, the Azure voice list, model listing, image and video providers, and LLM calls. Some of these routes also echoed provider response bodies or connection errors back to the caller. This allowed requests to internal addresses and probing of internal services. These requests now go through the strict provider transport, which pins every connection to validated addresses and refuses redirects. IP-literal hosts and the built-in default URLs of unmanaged providers are held to the same policy. Caller-facing errors are fixed text. Client-supplied AliDocMind endpoints must be official hosts. GHSA-g87c-cm4q-cw5x #1704
  • Classroom media generation downloads provider-returned image and video URLs through the strict provider transport: HTTPS public addresses only, data: URLs decoded locally, and size bounded while streaming #1692 (by @Yi-111-a). Agent-runtime image and video tools now do the same #1704.

Behavior Changes

  • A caller-supplied LLM, image/video, model-list, PDF-check or self-hosted MinerU base URL that answers with a redirect is refused instead of followed. Configure the final URL.
  • A caller-supplied provider base URL containing a query string or fragment is refused.
  • A caller-chosen loopback or private address, including an IP literal or an unmanaged provider's built-in localhost default (Ollama, Lemonade, VoxCPM), needs ALLOW_LOCAL_NETWORKS. Configure the provider on the server to keep it operator-managed.
  • Server-configured providers (LLM, image/video, TTS/ASR, MinerU, MinerU Cloud) may use local network addresses without ALLOW_LOCAL_NETWORKS. Cloud metadata and reserved ranges stay blocked, and redirects from them follow ALLOW_LOCAL_NETWORKS.
  • A client-supplied AliDocMind endpoint must be an official docmind-api.<region>.aliyuncs.com host over HTTPS; other endpoints answer 403 INVALID_URL. Server-configured endpoints are unchanged.
  • Provider check and generation errors are fixed messages without the provider's response text or connection errors:
    • /api/verify-pdf-provider success no longer includes status;
    • /api/azure-voices answers provider failures with 502;
    • /api/provider/probe-models reports other HTTP failures as 502 with the status class only;
    • LLM errors for a client-selected endpoint read Cannot connect to API: connection failed (or request timed out, redirects are not allowed) or the HTTP reason phrase;
    • MinerU Cloud errors report the HTTP status or numeric code.
  • Agent-runtime video and poster downloads require HTTPS.
  • Pinned provider requests connect directly and do not use Node's environment proxy (NODE_USE_ENV_PROXY with HTTP_PROXY/HTTPS_PROXY).
  • A provider id that names an inherited object property (such as constructor) is no longer treated as server-configured.

OpenMAIC v1.1.1 — Security

Choose a tag to compare

@wyuc wyuc released this 26 Sep 16:20
3355336

A security release. One advisory is published with this release. There are no other changes since 1.1.0.

Security

  • MinerU Cloud parsing fetched provider-supplied URLs without the address policy. The presigned upload URL and the result ZIP URL returned in MinerU Cloud's JSON responses were fetched with a plain fetch: no SSRF validation, redirects followed unchecked, and no size limits. When MinerU Cloud is not configured on the server, a caller can supply its own base URL, so its endpoint could point the server's PUT of the uploaded document and the result download at loopback, private or other internal addresses. Every MinerU Cloud request now goes through the strict provider transport, which validates each redirect hop and connects only to the addresses the guard validated. The upload and ZIP URLs from the response must be HTTPS public addresses under every policy, and the upload does not follow redirects. Address-policy refusals are not retried. JSON responses, the ZIP download and each decompressed entry are size-bounded, with decompression stopped as soon as a limit is crossed. The configured API root keeps the operator's ALLOW_LOCAL_NETWORKS policy, so self-hosted setups are unaffected. The shared SSRF guard now also classifies IPv4-compatible IPv6 addresses (::/96) by their embedded IPv4. GHSA-cpjc-vgjh-c5jp — reported by @AbelWangYaBo (#1688)

Upgrade: deployments that let users bring their own MinerU Cloud base URL should upgrade. Deployments that configure MinerU Cloud on the server are not exposed through this path.

Full Changelog: https://github.com/THU-MAIC/OpenMAIC/blob/main/CHANGELOG.md

OpenMAIC v1.1.0 — Classroom chat on an agent loop

Choose a tag to compare

@wyuc wyuc released this 24 Sep 06:04
21d83ec

Classroom chat now runs on an agent loop by default: learners can point at a slide element, an interactive component or a whiteboard drawing and ask about it, and the teacher can read the lesson, check the live state of an interactive experiment and search the web before answering. Settings are reorganized around the course workflow, with a model choice per generation step and first-class Token Plan connections (TokenDance, MiniMax, Seed and Kimi). Read Behavior Changes before upgrading.

Highlights

  • Pi classroom chat is the default. The in-class conversation moves from the director graph to an agent loop that can read slides on demand, search the web and call classroom tools within a single answer #1628 #1637
  • Ask about what you're looking at. Reference a single PPT element, an interactive component or a whiteboard element from the playback bar and ask about it; interactive pages that declare state are sampled at question time, so the teacher can explain the result the learner is actually seeing, and read_scene exposes an interactive page's static instructions #1508 #1632 #1656
  • Settings, rebuilt around the course workflow. Choose a model for each generation step (outline, slides, interactive pages, scene actions and more), toggle each capability on or off, and manage Token Plans in one place #1644
  • Token Plans. One-key presets for TokenDance (every modality) and the Kimi Coding Plan (text only; other modalities stay on your own providers) #1525 #1664

Features

  • Models: add OpenRouter image and video providers #1356, Gemini 3.8 Flash and 3.7 Flash #1629, and Xiaomi MiMo V2.6 #1655
  • TTS: pace classroom narration requests and classify MiniMax RPM limits so rate-limited runs slow down instead of failing #1650; auto-detect Vietnamese for browser-native narration #1487
  • Storage: workbench image and video generation write through the asset pool (#1007 part 6) #1524; ZIP imports persist media in the server asset pool #1520
  • Persistence: optional single-tenant mode that resolves every request to one shared owner (PERSISTENCE_SHARED_OWNER_ID) #1639
  • Render service: admission control and per-task resource budgets #1492
  • Attribution: TokenDance gateway requests carry an X-APP-URL header identifying the OpenMAIC deployment #1675

Bug Fixes

  • Generation: reject quiz options whose values are not A–Z and constrain them at the source #1651; reject unusable interactive scripts and surface runtime errors on the page #1649; keep narration speech free of formulas and LaTeX #1586; tolerate non-array mediaGenerations in outlines #1469; add a browser-safe package entry #1609; stabilize model picker teardown #1618
  • Playback and audio: mobile narration survives past the first segment and discussion lines reuse one media element #1477 #1610; stop superseded scene engines #1510; queue widget messages until the iframe is ready #1532; resolve CDN-backed narration consistently #1521; keep refused narration instead of re-billing it #1523; derive the Azure SSML locale from the selected voice #1566; rebuild FormData bodies for the undici transport #1580
  • PPTX import and editor: preserve tab columns, text insets, arrows, text/chart/image styling, shape autofit, Wingdings checkmarks, diagonal corners, table typography and punctuation wrapping; include every color attribute in the style cache key; share line bounds for alignment and dragging; bound ZIP inflation by default #1518 #1534 #1577 #1581 #1571 #1631 #1588
  • Media and web search: refuse redirects on adapter generation and poll calls #1636; keep long Grok relay generations alive and inline image bytes #1364; emit keyframe images as data URLs #1444; stop leaking Brave's HTML challenge page into errors #1553; bound the model-discovery response body timeout #1478
  • Export: surface video render rejection reasons #1414; include active line geometry in bounds #1626
  • Server and storage: validate pdfContent input #1578; sanitize agent session text #1504; correlate 5xx responses with request IDs #1601; warn when access-code protection is disabled #1599; show effective upload limits in errors #1418
  • Docker: create /app/data owned by the runtime user so classroom persistence works #1442; build workspace packages in the builder stage #1598
  • Misc: send taskEngineMode on the on-demand vocational scene path #716; POSIX zip entry names for exported skills on Windows #1641; i18n and persistence fixes #1595 #1596

Behavior Changes

  • Pi is the default classroom chat runtime. To keep the legacy director-graph chat, build with NEXT_PUBLIC_PI_CHAT_ENABLED=false #1628
  • Stricter generated content. Quizzes whose option values are not A–Z and interactive pages with unparseable scripts are now rejected as invalid model output and retried or skipped by the existing path, instead of being saved broken #1651 #1649
  • Settings layout. The web-search toggle moved from the generation toolbar into Settings; an existing preference is migrated once on first load #1644
  • Courseware references are opt-in. The playback-bar reference entry (PPT, interactive and whiteboard) is enabled with NEXT_PUBLIC_COURSEWARE_REFERENCE_ENABLED=true #1656

Other Changes

  • Docs: align security and behavior claims with shipped code, and document the Docker builder heap limit #1592 #1607
  • Refactors and CI: shared per-course session lifecycle, shared narration walk for export, MIME policy from the format registry, Node 24 publish actions, Windows-safe media tests #1619 #1621 #1590 #1569 #1584 #1615

Contributors

Thanks to the community contributors in this release: @AbelWangYaBo, @acse-bq23, @Ai-Eastern, @BeAIcoder, @Cham1229, @ciclou1, @dajiaohuang, @Duang777, @Hosuke, @HuntercodeT, @hydraxman, @LeoParkerOu, @lianglaibin116-cloud, @ly-wang19, @mianbaofang, @nqthiep, @PassCode023, @puxiao, @Qnh233, @ttkm2023, @WizKid1968, @YizukiAme, @zdnemz.

OpenMAIC v1.0.3 — Security

Choose a tag to compare

@wyuc wyuc released this 15 Sep 10:09
e693e11

A security release. Three advisories are published with this release, and Next.js is upgraded to patch a critical remote code execution. It also carries the fixes and features merged since 1.0.2.

Security

  • Access-code tokens never expired, and verification was not throttled. Verification tokens (timestamp.HMAC) were accepted regardless of age because neither verifier checked the timestamp, and POST /api/access-code/verify had no attempt throttling. Both verifiers now enforce a 7-day server-side lifetime and reject non-canonical signatures, and verification is rate-limited per client when TRUST_PROXY_HEADERS=true; without a trusted proxy the app cannot attribute requests to a client, so a long random ACCESS_CODE is the protection and a warning is logged when it is short. GHSA-qpmr-534w-hhpg — reported by @CaptBoykin (#1513)
  • The render service ran untrusted HTML in headless Chromium without a network policy. On the /preview and /render paths the packager's Content-Security-Policy was not applied, so inline script could reach loopback and internal addresses, and on /render the response was painted 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/.xhtml documents are sanitized. In the shipped image the container's egress lockdown already limited the reachable surface to loopback; deployments that disable it or run the service unisolated were exposed. GHSA-vqq3-22q7-289w — reported by @CaptBoykin (#1512)
  • Audio provider requests followed redirects and re-resolved DNS unvalidated. TTS, ASR, voice registration and voice cloning validated a client-supplied base URL once and then issued a plain fetch, so a redirect or a DNS-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; a client base URL can never reach a private, loopback or cloud-metadata address, even with ALLOW_LOCAL_NETWORKS set. GHSA-9p8q-rcmg-pmjw — reported by @CaptBoykin (#1514)
  • Next.js upgraded to patch a critical RCE. Bumped 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. (#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/importer 0.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)

Full Changelog: https://github.com/THU-MAIC/OpenMAIC/blob/main/CHANGELOG.md