Changelog
View SourceAll notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[Unreleased]
Added
- Top-level façade (
Lmml) -- Added convenience delegators (Lmml.open/1,open!/1,resolve/1,resolve!/1,render/2,to_md/2,validate/1,pack/2,pack!/2,inline/2,inline!/2,segment/2,render_turns/2,settings/2,manifest/1,embeds/1,narrative/1). - Turn-level / multi-message segmentation (
Lmml.Narrative.Segment) -- Splits a narrative into role-labeled messages (:user,:assistant,:system,:tool,:context), assigning embeds to their respective turns and mapping to API message structures. - Typed project settings (
Lmml.Settings) -- Structured helper for loadingsettings.yaml/settings.jsonembeds, featuring a built-in YAML-subset parser. Manifest.fetch/2andSettings.fetch/2-- Exposes key fetching distinguishing missing keys (:error) from explicitnullvalues ({:ok, nil}).- Embed helper accessors (
Lmml.Embed.content/1,Lmml.Embed.entry_name/1). - CLI Mix Tasks -- Added
mix lmml.render SOURCEfor rendering LLM-ready content parts (with optional--jsonand--max-embed-bytes), andmix lmml.to_md SOURCE [DEST]for lossy-but-readable Markdown export. - Markdown export tooling (
Lmml.to_md/2,Lmml.Narrative.Renderer.to_md/2) -- Converts embed syntax into clean human-readable placeholders ([Image: name],[Attachment: name]). - MIME & budget controls -- Expanded MIME coverage (audio, video, diff, pdf, csv, log, svg) and added per-embed payload budgeting via
max_embed_bytesinRenderer.render/2.
Fixed & Hardened
- Pack name collisions (
Lmml.Pack.pack/2) -- Added defensive check rejecting inline embed names that collide with external references or existing zip entries, preventing silent data loss. - Stable inlining order (
Lmml.Pack.inline/2) -- Appends inlined@@@name ... @@@blocks in first-occurrence narrative order while maintaining prefix-safe substitution. - Archive path traversal protection (
Lmml.Bundle) -- Validates raw archive central directory tables via:zip.table/1up front, returning clean{:error, {:unsafe_entry, name}}error tuples. - Comprehensive test coverage -- Added test suites for
Lmml.Narrative.Segment,Lmml.Settings,LmmlTest, new Mix tasks, end-to-end zip archive roundtrips, invalid UTF-8 parse handling, 4-kind aggregate validation reporting, and failure ordering.
0.1.0 - 2026-08-31
Initial release.
Added
- Narrative syntax (
Lmml.Narrative.Parser) -- a strict superset of Markdown built onmd, adding@name.extexternal references and@@@name.ext ... @@@inline embeds. Any bare.md/text file with none of this syntax is already a valid, triviallmmlnarrative. - Core data model --
Lmml.Embed(inline vs. external content),Lmml.Document(parsed AST plus every embed it mentions), andLmml.Bundle, the uniform entry point over both on-disk forms:.lmml-- a bare, self-contained text file..lmmlz-- a zip archive whose canonical narrative entry is named by stripping the trailingzfrom the archive's own filename, carrying whatever other files its narrative references.
manifest.jsonconvention (Lmml.Manifest) -- an optional embed literally namedmanifest.json, decoded with OTP's built-in:json.- Validation (
Lmml.Bundle.validate/1) -- cross-checks a bundle's references, zip entries, and embed names, reporting every issue found in one pass (missing references, orphaned entries, malformed embed names, conflicting embeds). - LLM payload rendering (
Lmml.Narrative.Resolver,Lmml.Narrative.Renderer) -- resolves every embed a bundle mentions and renders it into the typed content-part shape (text,image_url,attachment) a multimodal chat completion API expects. - Lossless packing (
Lmml.Pack) --pack/2andinline/2convert a bundle between its.lmmland.lmmlzforms, preserving every resolvable embed's content. - Mix tasks --
mix lmml.new,mix lmml.pack,mix lmml.inline,mix lmml.validatefor command-line ergonomics without writing Elixir. - Documentation -- a full language reference
(
docs/LANGUAGE_REFERENCE.md) and two worked examples underexamples/.
Notes
- Requires
md >= 0.12.2, which fixes aMd.Parser.Syntax.merge/2crash on a custom:settingsmap and adds theescape: falseblock:propertylmml's@@@embed syntax relies on to carry content through verbatim.