Repository Analysis

THU-MAIC/OpenMAIC

Open Multi-Agent Interactive Classroom — Get an immersive, multi-agent learning experience in just one click

2.2 Likely human-written View on GitHub
2.2
Adjusted Score
2.2
Raw Score
100%
Time Factor
2026-05-30
Last Push
18,127
Stars
TypeScript
Language
178,762
Lines of Code
706
Files
183
Pattern Hits
2026-05-31
Scan Date

Score History

Severity Breakdown

CRITICAL 8HIGH 2MEDIUM 41LOW 132

Pattern Findings

183 matches across 6 categories. Click a row to expand file-level details.

Decorative Section Separators41 hits · 123 pts
SeverityFileLineSnippet
MEDIUMapp/page.tsx1093// ─── Classroom Card — clean, minimal style ──────────────────────
MEDIUMtests/export/classroom-zip.test.ts9// ─── rewriteAudioRefsToIds ────────────────────────────────────
MEDIUMtests/export/classroom-zip.test.ts82// ─── actionsToManifest ────────────────────────────────────────
MEDIUMtests/export/classroom-zip.test.ts168// ─── Manifest round-trip ──────────────────────────────────────
MEDIUMcomponents/scene-renderers/quiz-view.tsx35// ─── Types ──────────────────────────────────────────────────────────────────
MEDIUMcomponents/scene-renderers/quiz-view.tsx99// ─── Sub-components ─────────────────────────────────────────────────────────
MEDIUMcomponents/scene-renderers/quiz-view.tsx647// ─── Main Component ─────────────────────────────────────────────────────────
MEDIUMcomponents/chat/inline-action-tag.tsx32// ── Style tokens ──────────────────────────────────────────────
MEDIUMcomponents/chat/inline-action-tag.tsx47// ── Action config ─────────────────────────────────────────────
MEDIUMcomponents/chat/inline-action-tag.tsx83// ── Component ─────────────────────────────────────────────────
MEDIUMcomponents/generation/outlines-editor.tsx385// ────────────────────────────────────────────────────────────────────────────────
MEDIUMcomponents/generation/outlines-editor.tsx387// ────────────────────────────────────────────────────────────────────────────────
MEDIUMcomponents/generation/outlines-editor.tsx648// ────────────────────────────────────────────────────────────────────────────────
MEDIUMcomponents/generation/outlines-editor.tsx650// ────────────────────────────────────────────────────────────────────────────────
MEDIUMcomponents/generation/outlines-editor.tsx1131// ────────────────────────────────────────────────────────────────────────────────
MEDIUMcomponents/generation/outlines-editor.tsx1133// ────────────────────────────────────────────────────────────────────────────────
MEDIUMcomponents/generation/generation-toolbar.tsx40// ─── Constants ───────────────────────────────────────────────
MEDIUMcomponents/generation/generation-toolbar.tsx44// ─── Types ───────────────────────────────────────────────────
MEDIUMcomponents/generation/generation-toolbar.tsx55// ─── Component ───────────────────────────────────────────────
MEDIUMcomponents/generation/generation-toolbar.tsx126 // ─── Pill button helper ─────────────────────────────
MEDIUMcomponents/generation/generation-toolbar.tsx642// ─── ModelSettingsPopover (provider + model picker) ─────
MEDIUMpackages/pptxgenjs/src/gen-media.ts56 // ──────────── NODE LOCAL FILE ────────────
MEDIUMpackages/pptxgenjs/src/gen-media.ts74 // ──────────── NODE HTTP(S) ────────────
MEDIUMpackages/pptxgenjs/src/gen-media.ts99 // ──────────── BROWSER ────────────
MEDIUMlib/pdf/mineru-cloud.ts65// ── API envelope ──────────────────────────────────────────────────────────────
MEDIUMlib/pdf/mineru-cloud.ts94// ── Filename sanitization ─────────────────────────────────────────────────────
MEDIUMlib/pdf/mineru-cloud.ts105// ── ZIP parsing ───────────────────────────────────────────────────────────────
MEDIUMlib/pdf/mineru-cloud.ts208// ── Main entry point ──────────────────────────────────────────────────────────
MEDIUMlib/export/classroom-zip-utils.ts7// ─── Export: Collect Media ─────────────────────────────────────
MEDIUMlib/export/classroom-zip-utils.ts51// ─── Export: Action Serialization ──────────────────────────────
MEDIUMlib/export/classroom-zip-utils.ts82// ─── Import: Reference Rewriting ───────────────────────────────
MEDIUMlib/buffer/stream-buffer.ts18// ─── Buffer Item Types ───────────────────────────────────────────────
MEDIUMlib/buffer/stream-buffer.ts91// ─── Callbacks ───────────────────────────────────────────────────────
MEDIUMlib/buffer/stream-buffer.ts141// ─── Options ─────────────────────────────────────────────────────────
MEDIUMlib/buffer/stream-buffer.ts161// ─── StreamBuffer Class ──────────────────────────────────────────────
MEDIUMlib/buffer/stream-buffer.ts202 // ─── Push Methods ────────────────────────────────────────────────
MEDIUMlib/buffer/stream-buffer.ts282 // ─── Control ─────────────────────────────────────────────────────
MEDIUMlib/buffer/stream-buffer.ts418 // ─── Internals ───────────────────────────────────────────────────
MEDIUMe2e/tests/full-happy-path.spec.ts22 // ── Phase 1: Home page ──────────────────────────────────────────────
MEDIUMe2e/tests/full-happy-path.spec.ts39 // ── Phase 2: Generation preview ─────────────────────────────────────
MEDIUMe2e/tests/full-happy-path.spec.ts49 // ── Phase 3: Classroom ──────────────────────────────────────────────
Hyper-Verbose Identifiers99 hits · 101 pts
SeverityFileLineSnippet
LOWapp/generation-preview/components/visualizers.tsx246function StreamingOutlineVisualizer({
LOWapp/generation-preview/components/visualizers.tsx386function AgentGenerationVisualizer() {
LOWtests/ai/openai-provider.test.ts16async function captureInjectedRequestBody(
LOWcomponents/settings/utils.ts41export function createCustomProviderSettings(
LOWcomponents/scene-renderers/classroom-complete.tsx499export function ClassroomCompletePageConnected() {
LOWcomponents/whiteboard/whiteboard-canvas.tsx107>(function InteractiveWhiteboardCanvas(
LOWcomponents/roundtable/presentation-speech-overlay.tsx41export function buildPresentationBubbleModel({
LOWcomponents/roundtable/presentation-speech-overlay.tsx388export function PresentationSpeechOverlay({
LOW…r/components/element/VideoElement/BaseVideoElement.tsx22function isLegacySequentialVideoRef(value: string | undefined): boolean {
LOW…er/Editor/Canvas/hooks/useInsertFromCreateSelection.ts5export function useInsertFromCreateSelection(viewportRef: RefObject<HTMLElement | null>) {
LOWcomponents/generation/generation-toolbar.tsx417function formatCompactThinkingValue(value?: string, t?: (key: string) => string) {
LOWpackages/pptxgenjs/src/gen-objects.ts1147export function addPlaceholdersToSlideLayouts(slide: PresSlide): void {
LOWpackages/pptxgenjs/src/gen-xml.ts819function slideObjectRelationsToXml (slide: PresSlide | SlideLayout, defaultRels: Array<{ target: string, type: string }>
LOWpackages/pptxgenjs/src/gen-xml.ts884function genXmlParagraphProperties (textObj: ISlideObject | TextProps, isDefault: boolean): string {
LOWlib/server/resolve-model.ts88function getThinkingConfigFromBody(body: unknown): ThinkingConfig | undefined {
LOWlib/server/provider-config.ts325export function canUseServerApiKeyForBaseUrl(
LOWlib/server/provider-config.ts472export function getServerWebSearchProviders(): Record<string, { baseUrl?: string }> {
LOWlib/server/provider-config.ts510export function resolveServerWebSearchProviderId(preferredProviderId?: string): string | undefined {
LOWlib/server/classroom-job-runner.ts13export function runClassroomGenerationJob(
LOWlib/server/classroom-media-generation.ts70export async function generateMediaForClassroom(
LOWlib/server/web-search-config.ts31function assertWebSearchProviderId(
LOWlib/server/web-search-config.ts37export function resolveSafeClientWebSearchBaseUrl(
LOWlib/server/web-search-config.ts59export function resolveWebSearchRouteBaseUrl(
LOWlib/server/web-search-config.ts67export function resolveClassroomWebSearchConfig(input: {
LOWlib/server/classroom-job-store.ts100export async function createClassroomGenerationJob(
LOWlib/server/classroom-job-store.ts122export async function readClassroomGenerationJob(
LOWlib/server/classroom-job-store.ts137export async function updateClassroomGenerationJob(
LOWlib/server/classroom-job-store.ts158export async function markClassroomGenerationJobRunning(
LOWlib/server/classroom-job-store.ts180export async function updateClassroomGenerationJobProgress(
LOWlib/server/classroom-job-store.ts194export async function markClassroomGenerationJobSucceeded(
LOWlib/server/classroom-job-store.ts213export async function markClassroomGenerationJobFailed(
LOWlib/server/search-query-builder.ts22function normalizeSearchRequirement(requirement: string): string {
LOWlib/utils/geometry.ts11export function getElementPercentageGeometry(
LOWlib/utils/stage-storage.ts191function isLegacySequentialVideoRef(value: unknown): value is string {
LOWlib/utils/stage-storage.ts220export function revokeThumbnailSlideMediaUrls(slides: Record<string, ThumbnailSlide>) {
LOWlib/utils/database.ts466export async function deleteStageWithRelatedData(stageId: string): Promise<void> {
LOWlib/utils/database.ts493export async function getGeneratedAgentsByStageId(
LOWlib/audio/voice-resolver.ts105export function getAvailableProvidersWithVoices(
LOWlib/audio/voxcpm.ts75export function voxCPMBackendSupportsReferenceAudio(backend: VoxCPMBackendType): boolean {
LOWlib/audio/voxcpm.ts91export function getVoxCPMProfileIdFromVoiceId(voiceId: string): string | null {
LOWlib/audio/voxcpm.ts96function sanitizeAutoVoicePromptPart(value?: string): string {
LOWlib/audio/voxcpm.ts105export function buildAutoVoxCPMVoicePrompt(context: VoxCPMVoicePromptContext = {}): string {
LOWlib/audio/asr-providers.ts289function getOptionalBearerAuthHeaders(apiKey?: string): Record<string, string> {
LOWlib/audio/voxcpm-voices.ts23function notifyVoiceProfilesChanged(): void {
LOWlib/audio/voxcpm-voices.ts129export async function validateVoxCPMReferenceAudio(blob: Blob): Promise<void> {
LOWlib/audio/voxcpm-voices.ts140export async function normalizeVoxCPMReferenceAudio(
LOWlib/ai/providers.ts1129function getCompatThinkingBodyParams(
LOWlib/ai/providers.ts1246function normalizeMiniMaxAnthropicBaseUrl(
LOWlib/ai/providers.ts1264function shouldUseOpenAIResponsesApi(providerId: ProviderId, modelId: string): boolean {
LOWlib/ai/llm.ts129function buildThinkingProviderOptions(
LOWlib/ai/model-metadata.ts351export function getCatalogThinkingCapability(
LOWlib/ai/thinking-config.ts13export function supportsConfigurableThinking(
LOWlib/ai/thinking-config.ts103function defaultEffortForCapability(thinking: ThinkingCapability): ThinkingEffort | undefined {
LOWlib/ai/thinking-config.ts107function defaultLevelForCapability(thinking: ThinkingCapability): ThinkingLevel | undefined {
LOWlib/web-search/format.ts6export function formatSearchResultsAsContext(result: WebSearchResult): string {
LOWlib/web-search/constants.ts66export function getWebSearchProviderDisplayName(
LOWlib/orchestration/director-prompt.ts94function summarizeAgentWhiteboardActions(actions: WhiteboardActionRecord[]): string {
LOWlib/orchestration/director-prompt.ts165export function summarizeWhiteboardForDirector(ledger: WhiteboardActionRecord[]): {
LOWlib/orchestration/director-prompt.ts194function buildWhiteboardStateForDirector(ledger?: WhiteboardActionRecord[]): string {
LOWlib/orchestration/prompt-builder.ts79function buildStudentProfileSection(userProfile?: { nickname?: string; bio?: string }): string {
39 more matches not shown…
Hallucination Indicators8 hits · 95 pts
SeverityFileLineSnippet
CRITICAL…lide-renderer/components/element/ProsemirrorEditor.tsx163 const mark = editorView.current.state.schema.marks.fontname.create({
CRITICAL…lide-renderer/components/element/ProsemirrorEditor.tsx173 const mark = editorView.current.state.schema.marks.fontsize.create({
CRITICAL…lide-renderer/components/element/ProsemirrorEditor.tsx186 const mark = editorView.current.state.schema.marks.fontsize.create({
CRITICAL…lide-renderer/components/element/ProsemirrorEditor.tsx199 const mark = editorView.current.state.schema.marks.fontsize.create({
CRITICAL…lide-renderer/components/element/ProsemirrorEditor.tsx208 const mark = editorView.current.state.schema.marks.forecolor.create({
CRITICAL…lide-renderer/components/element/ProsemirrorEditor.tsx218 const mark = editorView.current.state.schema.marks.backcolor.create({
CRITICAL…lide-renderer/components/element/ProsemirrorEditor.tsx318 const mark = editorView.current.state.schema.marks.link.create({
CRITICAL…lide-renderer/components/element/ProsemirrorEditor.tsx336 const mark = editorView.current.state.schema.marks.link.create({
Verbosity Indicators31 hits · 50 pts
SeverityFileLineSnippet
LOWapp/generation-preview/page.tsx243 // Step 0: Parse PDF if needed
LOWapp/generation-preview/page.tsx808 // Step 2: Generate content (currentStepIndex is already 2)
LOWlib/pdf/mineru-cloud.ts232 // Step 1: Create batch — request presigned upload URL
LOWlib/pdf/mineru-cloud.ts262 // Step 2: Upload PDF to presigned URL
LOWlib/pdf/mineru-cloud.ts287 // Step 3: Poll for completion
LOWlib/audio/asr-providers.ts44 * // Step 1: Upload audio file
LOWlib/audio/asr-providers.ts69 * // Step 2: Request transcription
LOWlib/audio/asr-providers.ts84 * // Step 3: Poll for completion
LOWlib/hooks/use-scene-generator.ts341 // Step 1: Generate content
LOWlib/hooks/use-scene-generator.ts375 // Step 2: Generate actions + assemble scene
LOWlib/hooks/use-scene-generator.ts497 // Step 1: Content
LOWlib/hooks/use-scene-generator.ts517 // Step 2: Actions
LOWlib/hooks/use-scene-generator.ts545 // Step 3: TTS
LOWlib/orchestration/stateless-generate.ts150 // Step 1: Find the opening `[` if not yet found
LOWlib/orchestration/stateless-generate.ts161 // Step 2: Check if the array is complete (closing `]` found)
LOWlib/orchestration/stateless-generate.ts165 // Step 3: Try incremental parse — jsonrepair first (fixes unescaped quotes), fallback to partial-json
LOWlib/orchestration/stateless-generate.ts186 // Step 4: Determine how many items are fully complete
LOWlib/orchestration/stateless-generate.ts200 // Step 5: Emit newly completed items
LOWlib/orchestration/stateless-generate.ts234 // Step 6: Stream partial text delta for the trailing item
LOWlib/orchestration/stateless-generate.ts246 // Step 7: Mark done if array is closed
LOWlib/generation/scene-builder.ts87 // Step 1: Generate content (with images if available)
LOWlib/generation/scene-builder.ts111 // Step 2: Generate Actions
LOWlib/generation/action-parser.ts47 // Step 1: Strip markdown code fences if present
LOWlib/generation/action-parser.ts50 // Step 2: Find the JSON array range
LOWlib/generation/action-parser.ts61 // Step 3: Parse — try JSON.parse first, then jsonrepair, fallback to partial-json
LOWlib/generation/action-parser.ts88 // Step 4: Convert items to Action[]
LOWlib/generation/action-parser.ts123 // Step 5: Post-processing — discussion must be the last action, and at most one
LOWlib/generation/action-parser.ts129 // Step 6: Filter out slide-only actions for non-slide scenes (defense in depth)
LOWlib/generation/action-parser.ts139 // Step 7: Filter by allowedActions whitelist (defense in depth for role-based isolation)
LOWlib/media/adapters/minimax-video-adapter.ts160 // Step 1: Submit task
LOWlib/media/adapters/minimax-video-adapter.ts163 // Step 2: Poll until complete
Synthetic Comment Markers2 hits · 15 pts
SeverityFileLineSnippet
HIGHlib/types/generation.ts97 // AI-generated media requests (when PDF images are insufficient)
HIGHlib/utils/database.ts319 // Version 8: Add generatedAgents table for AI-generated agent profiles
Over-Commented Block2 hits · 2 pts
SeverityFileLineSnippet
LOWlib/hooks/use-canvas-operations.ts181 // Copy selected element data to clipboard
LOWlib/generation/json-repair.ts141 let fixed = jsonStr;