Skip to content
Documentation

Architecture

GAS turns a score into requests for a music model, and streams the model’s audio back to your application:

score → language → timeline → session → renderer → connector → model

Your application loads the score into a session, chooses a connector for the model, and supplies provider access. The renderer schedules the score’s intent against a clock and sends it through the connector. Audio comes back the same way to the host’s playback engine: Web Audio in a browser, or whatever output another host supplies.

Runtime boundaries

Component Responsibility
Language Parse, validate, and compile a score into a timeline
Protocol Shared payload types and schemas
Core Validate commands and derive effective state through the cascade
API The session your application uses: loading, commands, playback, and events
Renderer Convert musical time to real time, schedule intent, and manage generation
Connector Translate intent into one model’s requests, and stream its audio back
Browser host Combine the runtime with Web Audio playback and an audible playhead

Everything model-specific lives in the connector. The score, timeline, session, and renderer describe intent the same way whichever model plays it.

Core works from input state alone, with no clock, network, or model. You can test commands and layering without generating audio.

Dependencies point toward the shared contracts. Protocol and highlight depend on nothing else in GAS. Language, Core, notation, and each connector depend on protocol. The renderer uses Core and notation, and the API uses language and Core. Nothing depends on a connector: the host creates one and passes it in.

Packages and imports

Install the umbrella package to get a set of packages tested together:

bash
npm install --save-exact @luna-estelar/gas@0.2.0

Import each part from its subpath of @luna-estelar/gas:

Subpath Surface Individual package/version
Root and /api Session, source helpers, errors gas-api 0.2.1
/browser/session Browser session and Web Audio composition gas-browser 0.3.0
/browser/audio ChainedSourceEngine, context and support helpers gas-browser 0.3.0
/browser/capture PcmCapture and encodeWave gas-browser 0.3.0
/browser/compile Compile, highlight, and preview live input gas-browser 0.3.0
/browser/timeline Timeline view models and clock formatting gas-browser 0.3.0
/browser/inspect Effective state inspection without the parser gas-browser 0.3.0
/language Compile documents and parse live fragments gas-language 0.1.3
/renderer Scheduling against a host clock, generation, audio delivery gas-renderer 0.3.0
/lyria Lyria connector, capabilities, configuration helpers gas-connector-lyria 0.2.1
/protocol Shared types and helpers gas-protocol 0.3.0
/protocol/validation Precompiled timeline payload validation gas-protocol 0.3.0
/core Session semantics, cascade, musical-time conversion gas-core 0.2.1
/notation Supported Alda subset, note events and MIDI encoding gas-notation 0.1.3
/highlight Syntax-presentation helpers and token classes gas-highlight 0.1.3

The individual packages are published too. If you install them separately, use a matched set rather than mixing versions, and import browser features from matching subpaths such as @luna-estelar/gas-browser/session.

The umbrella also includes gas-cli 0.1.3, which supplies the gas compile command:

bash
npx @luna-estelar/gas@0.2.0 compile song.gas --out song.timeline.json

Install @luna-estelar/gas-cli on its own if you only need the command. Diagnostics describes its error output.

Everything is ESM, with bundled TypeScript declarations. Browser applications need a bundler; there is no script-tag build. The umbrella, CLI, parser, API, browser, and highlight packages require Node 22. Protocol, Core, notation, the renderer, and the Lyria connector declare Node 20.

Imports only load what they need. Only /language and /browser/compile load the parser directly; the session loads it on demand when it compiles source or live text, and loadTimeline never needs it. Only /lyria loads Google’s SDK, so import it only where you create the connector.

Connector interface

A connector translates effective state into model requests, streams audio chunks to an AudioSink, and declares how it handles each kind of intent. It does not parse scores or schedule events.

The Connector interface in /protocol has:

Method Responsibility
describe() Identify the model, audio format, and capabilities
open(settings) Open with credentials and settings
prepare(initialState, config) Prepare the initial effective state
start(sink, timing, runId) Start streaming a run
update(update, requestedBoundary) Apply intent and report its applied boundary
stop(runId) End a run
close() Release the connector
setGenerationPaused?(paused) Optional generation flow control
validateConfig?(config) Optional configuration validation

A connector’s capabilities table rates every intent as supported, approximated, or unsupported. The session warns when a score uses intent the model will approximate or ignore. Only the session can produce these warnings; the compiler doesn’t know which model will play the score.

Connector failures are classified as auth, network, quota, provider, or internal, with the raw WebSocket close code when there is one. Connectors sanitise provider error text before passing it on. Close codes from 4000 to 4999 belong to whoever operates the endpoint, so the host interprets them.

The interface is in-process TypeScript and still evolving, with no conformance suite or frozen wire contract. The public Lyria connector is the reference implementation, and Supported models describes how it behaves. To discuss a connector for another model, get in touch.

What stays the same between runs

The timeline is the same every time a score compiles: the same tracks, section spans, and intent at the same musical positions. The audio is not. The model chooses the notes, phrasing, and sound, so each run is a new performance, and GAS has no model-independent way to repeat one. To keep a performance, record it with /browser/capture, which supplies PCM capture and WAV encoding.

Test your application’s commands and musical structure separately from the audio a model produces.

Versions and stability

Packages release independently, and their 0.x APIs can change in a minor release. Pin the umbrella version and commit your lockfile.

The timeline and session schemas have their own format version, currently 1.0, separate from the package versions. Timeline format covers the schema.

FMOD integration and C++ or Python ports are not released or scheduled. If a model or host matters to your project, tell us what you need.

Terms

Term Meaning
Score, document GAS text containing globals, tracks, sections, and calls
Arrangement The section calls in playback order; a reprise is a repeated call
Layer, build A track’s contribution; a build introduces layers or density over time
Timeline Compiled intent placed in musical time
Effective state Values and track activation derived for a position
Override, cascade A covering value, and the precedence used to resolve it
Session The application interface for loading, playback, commands, and events
Renderer Scheduling and generation against a clock
Connector, capabilities A model adapter, and its declared support for each kind of intent
Wiring The host’s composition of a session, renderer, and connector