This page describes code and deployment configuration, not a record of successful provider runs.
Runtime evidence belongs on Status.
The deployment supplies no provider credentials and leaves DEFAULT_MODEL empty; browser-driven
provider features therefore use the visitor’s configuration. Sources: deploy/maic.env.example,
lib/utils/model-config.ts:6-21, lib/server/resolve-model.ts:30-54.
How to read the matrix
configuredmeans the implementation is present and its entry point is available, not that a browser, remote endpoint, or provider has been tested.credential-dependentmeans the provider-backed operation requires the visitor’s own usable key in this deployment.blockedmeans the specified operation cannot work here; its row or accompanying text gives the reason.
“Requires credential” below concerns provider credentials, not access to the site.
The entire app vhost, including assets and /api/, has a server-level HTTP Basic gate over TLS;
nginx removes that gate’s Authorization header before proxying. Source: deploy/nginx/maic.loca.zone.conf.
Visitor provider keys instead persist in browser settings-storage and travel in application requests
through the server. Sources: lib/store/settings.ts:944-946, app/generation-preview/page.tsx:91-116.
Prompt and PDF to classroom
The browser creates a generation session, requests an outline, generates scene content and actions,
then saves the classroom locally. These are separate operations, not one offline browser model.
Sources: app/page.tsx:233-297, app/generation-preview/page.tsx:472-488,
app/generation-preview/page.tsx:595-647, lib/store/stage.ts:249-264.
| Capability | Where it runs | Requires credential | State in this deployment | Evidence (path:line) |
|---|---|---|---|---|
| Enter requirements and attach a PDF | Browser form and generation session | No provider key to edit the form | configured | app/page.tsx:233-297; components/generation/generation-toolbar.tsx:99-107 |
| Prompt and parsed PDF to scene outlines | Server LLM call; browser consumes /api/generate/scene-outlines-stream SSE | Visitor LLM key | credential-dependent | app/generation-preview/page.tsx:472-488; app/api/generate/scene-outlines-stream/route.ts:99-117,248-255,350-355 |
| Outline to scene content | Server through /api/generate/scene-content | Visitor LLM key | credential-dependent | app/generation-preview/page.tsx:595-617; app/api/generate/scene-content/route.ts:26-74,139-162 |
| Scene content to playback actions | Server through /api/generate/scene-actions | Visitor LLM key | credential-dependent | app/generation-preview/page.tsx:623-647; app/api/generate/scene-actions/route.ts:34-78,128-153 |
| Generate remaining scenes after entering the classroom | Browser orchestrates the same server content/actions endpoints | Visitor LLM key | credential-dependent | lib/hooks/use-scene-generator.ts:33-118; app/classroom/[id]/page.tsx:103-138 |
| Save an authored classroom for this browser | Browser IndexedDB | No provider key for the save itself | configured | lib/store/stage.ts:249-264; lib/utils/stage-storage.ts:36-71 |
A prompt is still required: attaching a PDF alone does not enable generation, and a missing model
selection opens setup rather than starting the pipeline. Selecting a model is not proof that its key
is valid. Sources: app/page.tsx:233-248, app/page.tsx:316-322, app/page.tsx:577-589.
Opening an unfinished classroom can automatically resume generation; opening a classroom whose scenes
are complete can resume missing media work. Do not treat every classroom visit as a passive read.
Source: app/classroom/[id]/page.tsx:103-149.
PDF parsing
| Capability | Where it runs | Requires credential | State in this deployment | Evidence (path:line) |
|---|---|---|---|---|
Local unpdf text and image extraction, the default parser | App server through /api/parse-pdf; not browser-only | No provider key | configured | lib/store/settings.ts:276-282; lib/pdf/constants.ts:12-18; lib/pdf/pdf-providers.ts:170-172,194-205 |
| Remote MinerU adapter with a visitor-supplied endpoint | App server sends the PDF to the chosen service’s /file_parse | Endpoint URL required; key only if that service requires one | configured | lib/pdf/constants.ts:20-25; lib/pdf/pdf-providers.ts:280-285,314-325 |
For MinerU, configured describes the reachable adapter, not a bundled running MinerU service.
The Compose overlay defines only the maic application, and the parser throws if no MinerU base URL
is supplied. Sources: deploy/compose.yml, lib/pdf/pdf-providers.ts:280-285.
Both parsers receive uploaded bytes through the application server. The edge caps request bodies at
32m; this is separate from downstream prompt truncation. Sources: app/api/parse-pdf/route.ts:23-55,
deploy/nginx/maic.loca.zone.conf, lib/constants/generation.ts:6-10.
Classroom playback and assessment
| Capability | Where it runs | Requires credential | State in this deployment | Evidence (path:line) |
|---|---|---|---|---|
| Render an existing slide classroom | Browser stage and slide renderer | No new LLM key for existing content | configured | components/stage/scene-renderer.tsx:15-31; components/stage.tsx:248-264 |
| Playback and action engines | Browser PlaybackEngine and ActionEngine | No new LLM key for existing actions | configured | components/stage.tsx:248-264; lib/playback/engine.ts:544-555 |
| Execute existing whiteboard actions and use clear/history controls | Browser action engine and whiteboard UI | No provider key | configured | lib/action/engine.ts:274-305; components/whiteboard/index.tsx:37-64,110-143 |
| Play existing narration or use text timing | Browser audio player/playback engine | No provider key for existing audio or reading timer | configured | lib/utils/audio-player.ts:25-54; lib/playback/engine.ts:442-488 |
| Grade objective choice questions | Browser compares submitted and correct answer arrays | No provider key | configured | components/scene-renderers/quiz-view.tsx:61-80 |
| Grade short-answer questions with an LLM | App server through /api/quiz-grade | Visitor LLM key | credential-dependent | components/scene-renderers/quiz-view.tsx:82-120; app/api/quiz-grade/route.ts:28-38,58-90 |
| Short-answer service-error fallback | Browser assigns rounded half-credit after request failure | No working key needed to reach the fallback; this is not AI grading | configured | components/scene-renderers/quiz-view.tsx:122-134 |
The fallback awards Math.round(points * 0.5) and displays a service-unavailable comment.
It must not be interpreted as a successful assessment of the answer.
Source: components/scene-renderers/quiz-view.tsx:122-134.
Existing content is distinct from new AI-authored content: whiteboard actions execute locally,
while generation and live chat obtain new actions from provider-backed paths.
Sources: lib/action/engine.ts:274-305, app/api/generate/scene-actions/route.ts:34-78,
components/chat/use-chat-sessions.ts:400-414.
Interactive HTML and PBL
| Capability | Where it runs | Requires credential | State in this deployment | Evidence (path:line) |
|---|---|---|---|---|
| Display existing interactive HTML or a scene URL | Browser iframe using srcDoc or src | No LLM key for rendering; embedded content may contact other services | configured | components/scene-renderers/interactive-renderer.tsx:12-26 |
| Generate interactive scene content | App server scene-content generator | Visitor LLM key | credential-dependent | app/api/generate/scene-content/route.ts:139-162; components/stage/scene-renderer.tsx:24-26 |
| Display an existing PBL project, select roles, and show its workspace | Browser PBL renderer | No LLM key for existing project display | configured | components/scene-renderers/pbl-renderer.tsx:39-64,108-126; components/scene-renderers/pbl/workspace.tsx:28-32,75-88 |
| Generate PBL scene content through the browser workflow | Server scene-content route supplies a language model | Visitor LLM key | credential-dependent | app/api/generate/scene-content/route.ts:139-147; lib/generation/scene-generator.ts:826-833 |
| PBL agent replies and next-issue questions | App server through /api/pbl/chat | Visitor LLM key | credential-dependent | components/scene-renderers/pbl/use-pbl-chat.ts:58-88,187-223; app/api/pbl/chat/route.ts:25-35,58-69 |
| Generate PBL scenes through the headless job pipeline | Server runner omits the model required by the PBL branch and skips null content | A key alone would not fix this code path | blocked | lib/server/classroom-generation.ts:323-335; lib/generation/scene-generator.ts:826-833 |
The interactive iframe’s exact sandbox flags are
allow-scripts allow-same-origin allow-forms allow-popups.
This is not a promise of inert or offline content. Source: components/scene-renderers/interactive-renderer.tsx:20-26.
The headless PBL limitation is separate from the browser PBL route: the latter passes the required
language model, while the former does not. Sources: app/api/generate/scene-content/route.ts:139-147,
lib/server/classroom-generation.ts:323-335, lib/generation/scene-generator.ts:826-833.
AI agents and discussion
| Capability | Where it runs | Requires credential | State in this deployment | Evidence (path:line) |
|---|---|---|---|---|
| Select built-in teacher and classmate personas | Browser registry and agent controls | No provider key | configured | components/agent/agent-bar.tsx:14-32; lib/orchestration/registry/store.ts:43-67,203-230 |
| Teacher/classmate chat and Q&A | Browser agent loop calls server /api/chat | Visitor LLM key | credential-dependent | components/chat/use-chat-sessions.ts:400-414,879-890; app/api/chat/route.ts:45-100 |
| Discussion and roundtable responses | Stage discussion delegates to the chat loop | Visitor LLM key | credential-dependent | components/stage.tsx:459-469; components/chat/use-chat-sessions.ts:1066-1081 |
| Generate classroom-specific agent profiles | Server /api/generate/agent-profiles, then browser persistence | Visitor LLM key | credential-dependent | app/generation-preview/page.tsx:376-439; app/api/generate/agent-profiles/route.ts:50-71,114-121 |
Automatic profile-generation errors fall back to preset agents; seeing agent avatars therefore does
not demonstrate successful profile generation. Source: app/generation-preview/page.tsx:408-439.
Missing chat model/key configuration stops the response path with setup feedback.
Source: components/chat/use-chat-sessions.ts:879-890.
Image and video generation
| Capability | Where it runs | Requires credential | State in this deployment | Evidence (path:line) |
|---|---|---|---|---|
| Seedream image generation | Server image endpoint and Seedream adapter | Visitor image-provider key | credential-dependent | lib/media/image-providers.ts:17-28,93-95; app/api/generate/image/route.ts:30-77 |
Qwen Image generation, provider ID qwen-image | Server image endpoint and Qwen adapter | Visitor image-provider key | credential-dependent | lib/media/image-providers.ts:30-46,96-97; app/api/generate/image/route.ts:30-77 |
Nano Banana image generation, provider ID nano-banana | Server image endpoint and Gemini adapter | Visitor image-provider key | credential-dependent | lib/media/image-providers.ts:48-52,98-99; app/api/generate/image/route.ts:30-77 |
| Seedance video generation | Server video endpoint and Seedance adapter | Visitor video-provider key | credential-dependent | lib/media/video-providers.ts:17-38,145-147; app/api/generate/video/route.ts:31-82 |
| Kling video generation | Server video endpoint and Kling adapter | Visitor video-provider key | credential-dependent | lib/media/video-providers.ts:39-51,148-149; app/api/generate/video/route.ts:31-82 |
| Veo video generation | Server video endpoint and Veo adapter | Visitor video-provider key | credential-dependent | lib/media/video-providers.ts:52-68,150-151; app/api/generate/video/route.ts:31-82 |
| Sora video generation | Registry entry exists, but dispatch has no Sora implementation | A key cannot add the missing implementation | blocked | lib/media/video-providers.ts:69-76,145-154 |
Image/video requests use their own provider settings; an LLM key is not automatically an image/video
configuration. The media orchestrator calls separate endpoints and downloads returned media through
/api/proxy-media. Source: lib/media/media-orchestrator.ts:193-280.
Sora’s registry entry has an empty model list and falls into the unsupported-provider error.
Do not count its presence in settings or environment-key documentation as a fourth implemented video
backend. Source: lib/media/video-providers.ts:69-76,145-154.
Speech synthesis and recognition
| Capability | Where it runs | Requires credential | State in this deployment | Evidence (path:line) |
|---|---|---|---|---|
| Native Web Speech TTS, the fresh-settings default | Browser and its available voices | No OpenMAIC provider key | configured | lib/store/settings.ts:255-268; lib/audio/constants.ts:609-620 |
| OpenAI cloud TTS | App server /api/generate/tts | Visitor TTS key | credential-dependent | lib/audio/constants.ts:43-47; lib/audio/tts-providers.ts:120-122; lib/hooks/use-scene-generator.ts:123-156 |
| Azure cloud TTS | App server /api/generate/tts | Visitor TTS key and concrete regional endpoint | credential-dependent | lib/audio/constants.ts:148-152; lib/audio/tts-providers.ts:124-125,186-206 |
| GLM cloud TTS | App server /api/generate/tts | Visitor TTS key | credential-dependent | lib/audio/constants.ts:191-195; lib/audio/tts-providers.ts:127-128,223-239 |
| Qwen cloud TTS | App server /api/generate/tts | Visitor TTS key | credential-dependent | lib/audio/constants.ts:252-256; lib/audio/tts-providers.ts:130-131,266-289 |
| Native speech recognition, the fresh-settings ASR default | Browser SpeechRecognition implementation | No OpenMAIC provider key; browser support and permission required | configured | lib/store/settings.ts:255-273; lib/audio/constants.ts:747-751; lib/hooks/use-audio-recorder.ts:43-76,93-124 |
OpenAI ASR, provider ID openai-whisper | Recorded audio uploaded to server /api/transcription | Visitor ASR key | credential-dependent | lib/audio/constants.ts:631-635; lib/audio/asr-providers.ts:172-188; lib/hooks/use-audio-recorder.ts:128-168 |
Qwen ASR, provider ID qwen-asr | Recorded audio uploaded to server /api/transcription | Visitor ASR key | credential-dependent | lib/audio/constants.ts:704-708; lib/audio/asr-providers.ts:199-224; lib/hooks/use-audio-recorder.ts:128-168 |
Browser-native audio is not a server synthesis/transcription service and is not an offline guarantee.
The browser recorder handles support, permission, and network errors; server dispatch rejects native
TTS/ASR providers. Sources: lib/hooks/use-audio-recorder.ts:43-76,
lib/audio/tts-providers.ts:133-136, lib/audio/asr-providers.ts:244-292.
Web research
| Capability | Where it runs | Requires credential | State in this deployment | Evidence (path:line) |
|---|---|---|---|---|
| Tavily research before outline generation | App server /api/web-search calls Tavily | Visitor Tavily key; none supplied by this deployment | credential-dependent | lib/web-search/constants.ts:10-16; app/generation-preview/page.tsx:307-321; app/api/web-search/route.ts:15-45; deploy/maic.env.example |
The toolbar disables search without a local key or server configuration. This enrichment is separate
from the mandatory LLM generation path. Sources: components/generation/generation-toolbar.tsx:67-74,349-357,
app/generation-preview/page.tsx:307-321,472-488.
Exports
| Capability | Where it runs | Requires credential | State in this deployment | Evidence (path:line) |
|---|---|---|---|---|
| Download slide content as PPTX | Browser builds and downloads the presentation | No new provider-generation key; existing remote media may be fetched | configured | lib/export/use-export-pptx.ts:965-968,1082-1118 |
| Download a resource ZIP with PPTX and existing interactive HTML | Browser builds a ZIP; only interactive scenes with stored HTML are included | No new provider-generation key | configured | lib/export/use-export-pptx.ts:1133-1164 |
| Export classroom as PDF | No such export implementation in the routed export UI | Not a credential issue | blocked | components/header.tsx:267-295; lib/export/use-export-pptx.ts:1180 |
| Export classroom as video or MP4 | No such export implementation in the routed export UI | Not a credential issue | blocked | components/header.tsx:267-295; lib/export/use-export-pptx.ts:1180 |
The menu waits for scenes, no pending or failed outlines, and settled media tasks; failed media tasks
also count as settled. Both export actions additionally require at least one slide.
Sources: components/header.tsx:50-54, lib/export/use-export-pptx.ts:1082-1088.
A resource ZIP is not a full classroom/database backup: it adds a PPTX and existing interactive HTML,
not the full browser state, chats, settings, or generation metadata.
Source: lib/export/use-export-pptx.ts:1133-1164.
Headless classroom API
| Capability | Where it runs | Requires credential | State in this deployment | Evidence (path:line) |
|---|---|---|---|---|
Complete a headless POST /api/generate-classroom job | App server deferred runner | Server LLM key and usable model configuration; browser BYOK is not consumed here | blocked | deploy/maic.env.example; lib/server/classroom-generation.ts:178-189; lib/server/resolve-model.ts:30; lib/ai/providers.ts:945-947 |
| Submit a job and poll its recorded state | App server routes and filesystem job store | Site gate access; submission is not generation success | configured | app/api/generate-classroom/route.ts:34-50; app/api/generate-classroom/[jobId]/route.ts:11-38 |
A valid submission can receive 202 and a jobId before the deferred runner fails.
The runner resolves only server configuration, selecting implicit OpenAI gpt-4o-mini when
DEFAULT_MODEL is empty; constructing that model throws without an OpenAI key.
Sources: app/api/generate-classroom/route.ts:34-50, lib/server/classroom-generation.ts:178,
lib/server/resolve-model.ts:30-54, lib/ai/providers.ts:945-947.
Known limitations in the pinned code
These headless limitations remain relevant to any later server-key enablement; the current deployment
is already blocked before their generation phases. Sources: deploy/maic.env.example,
lib/server/classroom-generation.ts:178-189.
- PDF images ignored by headless generation.
pdfContent.imagesis accepted, but only text reaches outline generation and the headlessaiCallignores its_imagesargument. Sources:lib/server/classroom-generation.ts:34-42,191-211,264-275. - PBL scenes skipped headlessly. The runner does not supply the model needed by the PBL branch;
null scene content is skipped rather than persisted.
Sources:
lib/server/classroom-generation.ts:323-335,lib/generation/scene-generator.ts:826-833. - Success does not guarantee complete media. Headless media and TTS failures are logged and
swallowed before classroom persistence, so a
succeededjob may lack requested images, video, or audio. Sources:lib/server/classroom-generation.ts:365-417,lib/server/classroom-job-runner.ts:34-41. - Jobs are process-local execution, not a durable queue. Restart loses in-flight promises; saved
job summaries do not restart them. Polling reports a
runningjob as stale/failed after 30 minutes without an update, computed on read rather than written back; queued jobs do not get that timeout. Sources:lib/server/classroom-job-runner.ts:11-49,lib/server/classroom-job-store.ts:78-96,124-130. - Qwen TTS file suffix mismatch. Headless audio filenames use the first registry format, MP3 for
Qwen, although the synthesis result reports WAV; the returned format is not used for the suffix.
Sources:
lib/server/classroom-media-generation.ts:227-250,lib/audio/constants.ts:606,lib/audio/tts-providers.ts:311-316. - Health flags are configuration presence only.
/api/healthchecks provider-map lengths; its booleans do not test credentials, connectivity, generation quality, or storage writability. Source:app/api/health/route.ts:11-20.
Related pages
- Quickstart for the visitor configuration path.
- Architecture for request flow and the two storage domains.
- Security for gate and untrusted-input boundaries.
- Status for the separate runtime evidence record.