What Is the Purpose of the @openmaic/dsl Package in OpenMAIC?

The @openmaic/dsl package serves as the contract-keystone of the OpenMAIC SDK, providing zero-dependency TypeScript specifications for slide data structures, validation logic, and version migration utilities.

In the THU-MAIC/OpenMAIC repository, @openmaic/dsl operates as the foundational layer that defines how slide documents, lesson stages, and playback actions are structured and validated. By maintaining zero runtime dependencies, this package ensures that renderers, importers, and storage engines across the ecosystem can share a common data contract without dragging in framework-specific code.

Zero-Runtime-Dependency Architecture

The @openmaic/dsl package deliberately excludes React, PPTX libraries, and charting dependencies. This architectural choice guarantees that any consumer—whether a React-based renderer or a Node.js CLI importer—can depend on the contract layer without pulling in extraneous code.

According to the source README, this package contains "only a pure TypeScript specification" encompassing the slide object model, lesson skeleton, playback actions, and supporting utilities【/cache/repos/github.com/THU-MAIC/OpenMAIC/main/packages/@openmaic/dsl/README.md#L3-L6】.

Core Modules and Source Files

The package organizes its functionality into discrete modules under packages/@openmaic/dsl/src/:

Slide and Stage Definitions

  • src/slides.ts: Defines the core slide object model including Slide, PPTElement, and related enums that represent visual elements within a presentation.
  • src/stage.ts: Contains the lesson skeleton definitions including Stage, generic Scene types, SceneType enum, StageMode, and Whiteboard interfaces. These structures organize how slides are sequenced and presented during a lesson.

Actions and Type Guards

  • src/action.ts: Specifies the playback verb set through the Action union type, ACTION_TYPES constants, and category lists that define how the presentation engine should transition between states.
  • src/guards.ts: Provides discriminant type-guards such as isTextElement that enable runtime narrowing of union types without external validation libraries.

Validation and Normalization

  • src/validate.ts: Exports pure, side-effect-free validators including validateStage(), validateScene(), and validateAction(). These functions return a ValidationResult structure and can execute in any JavaScript environment without external dependencies【/cache/repos/github.com/THU-MAIC/OpenMAIC/main/packages/@openmaic/dsl/README.md#L105-L112】.
  • src/normalize.ts: Contains default-filling and repair functions like normalizeElement() and normalizeSlide() that ensure incoming data conforms to the expected schema by populating missing fields and deriving geometric properties.

Versioning, Assets, and Runtime

  • src/version.ts: Defines DSL_VERSION constants and the migrate() function alongside DSL_MIGRATIONS to upgrade persisted slide documents automatically as the contract evolves.
  • src/asset-manifest.ts: Provides asset-enumeration utilities that scan documents for media references without performing IO operations.
  • src/runtime.ts: Defines runtime envelope types (RuntimeSession, RuntimeRecord) for storing learner-generated data such as chat messages and quiz attempts in a version-aware format.

Practical Usage Examples

Importing Types and Utilities

Consumers import type definitions and runtime utilities from the package index:

import type {
  Slide,
  PPTElement,
  Action,
} from '@openmaic/dsl';
import {
  isTextElement,
  DSL_VERSION,
  SYNC_ACTIONS,
} from '@openmaic/dsl';

This pattern demonstrates how the package serves as the single source of truth for all slide-related data structures, preventing type duplication across the codebase【/cache/repos/github.com/THU-MAIC/OpenMAIC/main/packages/@openmaic/dsl/README.md#L37-L40】.

Validating Stage Documents

Validate structural integrity before processing:

import { validateStage } from '@openmaic/dsl';

const result = validateStage(myStageDoc);
if (!result.valid) {
  console.error('Stage is invalid:', result.errors);
}

The validators are pure functions that return deterministic results without external library calls【/cache/repos/github.com/THU-MAIC/OpenMAIC/main/packages/@openmaic/dsl/README.md#L105-L112】.

Normalizing Raw Input

Repair incomplete data structures before storage:

import { normalizeSlide } from '@openmaic/dsl';

const cleanSlide = normalizeSlide(rawSlide);
// `cleanSlide` now has all required defaults and derived geometry.

Normalizers fill required fields and calculate derived geometry automatically【/cache/repos/github.com/THU-MAIC/OpenMAIC/main/packages/@openmaic/dsl/README.md#L30-L34】.

Enumerating Asset Manifests

Extract media references without filesystem operations:

import {
  enumerateAssetManifest,
  type AssetManifest,
} from '@openmaic/dsl';

const manifest: AssetManifest = enumerateAssetManifest(document, {
  metadata(ref, kind) {
    // Optional: provide extra info such as size or mime type.
    return lookupMetadata(ref, kind);
  },
});

The enumerateAssetManifest utility remains IO-free and returns deterministic entries regardless of execution environment【/cache/repos/github.com/THU-MAIC/OpenMAIC/main/packages/@openmaic/dsl/README.md#L44-L51】.

Migrating Legacy Documents

Handle version upgrades programmatically:

import {
  DSL_VERSION,
  migrate,
  dslVersionOf,
  needsMigration,
} from '@openmaic/dsl';

if (needsMigration(oldDoc)) {
  const upgraded = migrate(oldDoc);
  console.log('Upgraded to version', DSL_VERSION);
}

Versioning and migration functions are pure and idempotent, ensuring safe repeated application【/cache/repos/github.com/THU-MAIC/OpenMAIC/main/packages/@openmaic/dsl/README.md#L58-L66】.

JSON Schema and Language-Neutral Validation

Beyond TypeScript definitions, @openmaic/dsl ships JSON-Schema artifacts generated directly from the TypeScript types. This enables validation in languages other than TypeScript, allowing Python services or Go microservices to validate OpenMAIC documents against the same contract without requiring TypeScript compilation.

Summary

  • @openmaic/dsl functions as the contract-keystone for the entire OpenMAIC ecosystem, defining data structures in src/slides.ts, src/stage.ts, and src/action.ts.
  • Zero runtime dependencies prevent downstream packages from inheriting framework-specific bloat.
  • Pure validation and normalization functions (validateStage, normalizeSlide) operate without side effects or external libraries.
  • Version migration utilities (migrate, DSL_VERSION) ensure backward compatibility as the specification evolves.
  • JSON-Schema generation enables cross-language validation of slide documents.

Frequently Asked Questions

What does DSL stand for in @openmaic/dsl?

DSL stands for Domain-Specific Language. The package defines the specific vocabulary and structure for describing slides, lessons, and playback actions within the OpenMAIC presentation ecosystem, effectively creating a language for interactive educational content.

Why does @openmaic/dsl have zero runtime dependencies?

The zero-dependency constraint ensures maximum portability across the OpenMAIC ecosystem. Rendering engines, import tools, and storage services can all import type definitions and validation logic without pulling in React, charting libraries, or file-format parsers that would bloat their bundles and create version conflicts.

How does versioning work in @openmaic/dsl?

The package exports a DSL_VERSION constant and a migrate() function defined in src/version.ts. When document structures evolve, migration functions registered in DSL_MIGRATIONS transform older documents to the current schema. The needsMigration() helper checks document versions before processing, making upgrades automatic and idempotent.

Can I use @openmaic/dsl without the rest of OpenMAIC?

Yes. Because the package has no runtime dependencies, you can install it independently to validate slide data, normalize user-generated content, or generate asset manifests in any TypeScript or JavaScript project. The JSON-Schema artifacts also enable validation in non-JavaScript environments.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →