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

> Discover the purpose of the @openmaic/dsl package, the contract-keystone of OpenMAIC SDK. It provides zero-dependency TypeScript specifications for data structures, validation, and migration.

- Repository: [MAIC/OpenMAIC](https://github.com/THU-MAIC/OpenMAIC)
- Tags: deep-dive
- Published: 2026-09-12

---

**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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/asset-manifest.ts)**: Provides **asset-enumeration utilities** that scan documents for media references without performing IO operations.
- **[`src/runtime.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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:

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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:

```typescript
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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/slides.ts), [`src/stage.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/src/stage.ts), and [`src/action.ts`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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`](https://github.com/THU-MAIC/OpenMAIC/blob/main/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.