retiam 2.0.1 → 2.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. package/THIRD_PARTY_NOTICES.md +3 -3
  2. package/agent/AGENTS.md +67 -0
  3. package/agent/CLAUDE.md +2 -0
  4. package/agent/skill/SKILL.md +111 -0
  5. package/agent/skill/examples/AreaLesson.ts +48 -0
  6. package/agent/skill/examples/ExplainMotion.ts +32 -0
  7. package/agent/skill/examples/NarratedMotion.ts +42 -0
  8. package/agent/skill/examples/SecantToTangent.ts +142 -0
  9. package/agent/skill/references/api.md +109 -0
  10. package/agent/skill/references/explainers.md +121 -0
  11. package/agent/skill/references/quality.md +148 -0
  12. package/agent/skill/references/styles.md +58 -0
  13. package/agent/skill/references/tts.md +72 -0
  14. package/agent/templates/explainer/lesson.json +25 -0
  15. package/agent/templates/explainer/review.json +6 -0
  16. package/agent/templates/explainer/styles.json +92 -0
  17. package/bin/agent-kit.js +26 -0
  18. package/bin/cli.js +24 -4
  19. package/bin/context.js +57 -0
  20. package/bin/init.js +71 -12
  21. package/bin/lesson-project.js +30 -0
  22. package/bin/lesson.js +168 -0
  23. package/bin/lint.js +6 -6
  24. package/bin/snapshot-runtime.js +185 -0
  25. package/bin/snapshot.js +32 -225
  26. package/dist/THIRD_PARTY_NOTICES.md +3 -3
  27. package/dist/UTIF-BrQ3Ng5l.min.js +1 -0
  28. package/dist/{UTIF-2Ear_0Uo.js → UTIF-CN0-pEnd.js} +1 -1
  29. package/dist/decompress-D7LzbvPD.min.js +15 -0
  30. package/dist/index-3sAseSJQ.min.js +10472 -0
  31. package/dist/{index-B2sJBy4c.js → index-yQIdejOj.js} +15 -13
  32. package/dist/libs/explainer/example.d.ts +3 -0
  33. package/dist/libs/explainer/index.d.ts +5 -0
  34. package/dist/libs/explainer/index.js +134 -0
  35. package/dist/libs/explainer/plan.d.ts +12 -0
  36. package/dist/libs/explainer/plan.js +197 -0
  37. package/dist/libs/explainer/runtime.d.ts +24 -0
  38. package/dist/libs/explainer/styles.d.ts +3 -0
  39. package/dist/libs/explainer/types.d.ts +119 -0
  40. package/dist/libs/explainer/visuals.d.ts +18 -0
  41. package/dist/libs/tts/index.js +386 -1009
  42. package/dist/libs/vite/index.d.ts +28 -0
  43. package/dist/libs/vite/index.js +158 -0
  44. package/dist/{main-D_G4uIju.js → main-BTk_9jtl.js} +1 -1
  45. package/dist/main-lQwYAed8.min.js +5939 -0
  46. package/dist/msEdgeV2-BLEnvPJa.js +641 -0
  47. package/dist/opentype.module-B-1cYAb-.min.js +1 -0
  48. package/dist/retiam.es.js +1 -1
  49. package/dist/retiam.es.min.js +1 -0
  50. package/dist/src/engine/animation/Animation.d.ts +1 -0
  51. package/package.json +13 -8
  52. package/readme.md +7 -6
@@ -0,0 +1,121 @@
1
+ # Explainer production with Retiam
2
+
3
+ Use this for educational animations. Ordinary title animations and other short
4
+ edits do not need a lesson plan. An AI coding harness authors the subject model,
5
+ script and TypeScript scenes; the CLI supplies deterministic production tools.
6
+ No particular AI provider or additional agent service is required.
7
+
8
+ ## Start from the learner's question
9
+
10
+ Read `lesson/lesson.json` and the existing source. Establish the topic, audience,
11
+ prerequisites, learning objective, duration constraints and requested style from
12
+ the prompt. Infer routine choices; ask only about consequential missing context.
13
+ The supplied area lesson is a working API reference, not the requested subject.
14
+ Replace its model and beats when the user asks for another topic.
15
+
16
+ Research claims that need verification. Record source IDs, titles, links or
17
+ notes in `sources`, and connect factual claims to those IDs. Explicitly mark an
18
+ illustrative model. A numeric simulation may be correct for its assumptions yet
19
+ misrepresent the real system; explain assumptions and avoid false causality.
20
+
21
+ Plan a visible construction and the narration together. Useful beats include a
22
+ question, a prediction, a counterexample, a mechanism, a generalization, an
23
+ application and a resolved takeaway. Choose the sequence for the subject rather
24
+ than forcing every topic into the same chapter count. Each beat records `goal`,
25
+ `visibleChange` and `focus`. Text such as “explain the process” is not a visible
26
+ change; “a molecule passes through the membrane while concentration decreases” is.
27
+
28
+ ## Select the visual mechanism
29
+
30
+ - Algorithms: derive graph, table, queue and code updates from one execution trace.
31
+ Check a result against an independent reference. Use native `Code` and
32
+ `retiam/graphs`; introduce auxiliary representations only when they help.
33
+ - Mathematics: vary a parameter, deform geometry, decompose areas, or connect a
34
+ construction to `Tex`. Transfer identity and color into the notation.
35
+ - Physics: use `retiam/physics` when rigid-body dynamics explain the phenomenon;
36
+ mathematical fields or a deterministic analytic model may be more appropriate.
37
+ - Biology and other processes: author an accurate conceptual model and use
38
+ local interactions, flows and scale changes. Use vectors, shapes or labeled
39
+ assets; a process illustration need not pretend to be a physical simulation.
40
+ - History, economics and data: anchor timelines, maps, comparisons and charts to
41
+ sources. Reveal changes and relationships without animating an unsupported
42
+ causal claim.
43
+
44
+ Use the matching native sublibrary for supported features. Do not import every
45
+ library just to exercise the engine. Novel subjects still need original scenes.
46
+
47
+ ## Write for a curious teacher
48
+
49
+ Keep formal definitions and conditions exact. Around them, invite the learner to
50
+ predict, give space to think, and explain why an observed event matters. Vary the
51
+ rhythm: not every sentence needs a question. Avoid forced jokes and filler.
52
+
53
+ For example: “A currently says four. What if we go through B?” Then a real pause
54
+ while the route lights up. “Two, plus one… three. That's better. Let's remember it.”
55
+ Do not expose the candidate or subtitle answer during that prediction pause.
56
+
57
+ Keep performance notes out of spoken text. A narration segment has an `id`,
58
+ `text`, and optional `pauseAfterMs`. Segments need not correspond one-to-one to
59
+ visual actions. Split at purposeful thinking pauses, retaining coherent speech
60
+ between them. The built-in voice remains the default. Change a provider only when
61
+ requested; additional providers may normalize recordings into `PreparedSpeech`.
62
+ Include narration in an explainer unless the user requests a silent treatment.
63
+ The sample's disabled narration is an offline-preview convenience, not a reason
64
+ to omit the requested video's spoken explanation.
65
+
66
+ ## Public workflow
67
+
68
+ The core authoring types and runtime are exported by `retiam/explainer`. Pure
69
+ validation, compilation and style resolution also import in Node through
70
+ `retiam/explainer/plan`. Find declarations with `retiam context --json`.
71
+
72
+ 1. Edit the lesson and write a subject model under `src/`. Persist the requested
73
+ profile in `style`. `retiam lesson style excalidraw` selects the whiteboard look;
74
+ custom style objects extend a preset. Read [styles.md](styles.md) for the look.
75
+ 2. Run `npm run lesson:check`. It checks schema/source references and any prepared
76
+ audio. Its `requiredReview` remains a separate obligation, not a quality score.
77
+ 3. For narration set `narration.enabled` to true, then run
78
+ `npm run lesson:prepare`. First-time native synthesis needs network access;
79
+ subsequent calls use the native cache. It writes `lesson/prepared.json` and
80
+ public audio files. Keep them for reproducible export. Silent preview timings
81
+ are explicitly marked `estimated` and are not locked speech timings.
82
+ 4. Import the lesson and optional prepared manifest into the scene. Use
83
+ `prepareLesson(this, plan, {prepared})`, then `await lesson.run(handlers)`.
84
+ All handlers are built before playback. Put mutations in animations or `b.at()`;
85
+ do not mutate shared objects directly while constructing later beat handlers.
86
+ 5. Bind timing to `b.cue('name')` and `b.durationMs`. A cue identifies a segment
87
+ and optionally a spoken phrase; repeated phrases require `occurrence`.
88
+ Missing, ambiguous or stale cues fail visibly instead of drifting silently.
89
+ Check timing with `npm run lesson:timeline`.
90
+ 6. Type-check and lint, then capture setup, prediction, reveal, transition and
91
+ conclusion frames. `lesson check --json` lists useful sample times. Open the
92
+ PNGs and watch representative short clips for pacing. Fix observed issues.
93
+ 7. Render with the normal Retiam renderer and export captions with
94
+ `npm run lesson:captions`. Inspect final video/audio streams, listen to speech,
95
+ check synchronization and pauses, and update `lesson/review.json` with concrete
96
+ evidence. Report any unavailable checks honestly.
97
+
98
+ The runtime preloads audio, compiles one frame-aligned clock, and schedules all
99
+ clips and visual beat groups on that clock. Native speech and imported assets
100
+ share `durationMs`, word timestamps and a URL in `PreparedSpeech`. Caption cues
101
+ are grouped within speech segments so they cannot bridge a thinking pause.
102
+
103
+ ## Small executable reference
104
+
105
+ Copy `../examples/AreaLesson.ts` from the skill directory into `src/scenes/` to
106
+ run it. `npx create-retiam my-video --template explainer` opens this construction
107
+ with the lesson JSON editable outside the scene. The sample is silent by default
108
+ so a fresh preview works offline; enable native narration when needed.
109
+
110
+ `styleGeometry`, `drawGeometry`, `transferValue` and `emphasize` supply reusable
111
+ motion behaviors. Use public Retiam entities for the rest of the construction.
112
+ A style profile does not automatically make a static scene explanatory.
113
+
114
+ ## Review evidence
115
+
116
+ In `lesson/review.json`, keep automatic command results separate from observed
117
+ facts. Record a frame/clip path, the beat reviewed, what was observed and whether
118
+ it was fixed. Inspect overlaps, readable label sizes, stable identity, meaningful
119
+ motion, prediction/reveal order, and a conclusion with time to read. Check claims
120
+ against sources and domain calculations against independent results. A passing
121
+ plan check cannot establish factual or pedagogical correctness.
@@ -0,0 +1,148 @@
1
+ # 3Blue1Brown-inspired visual explanations
2
+
3
+ The default direction is a 3Blue1Brown-inspired mathematical explainer, built
4
+ with Retiam. Teach through visual intuition and evolving constructions. Match
5
+ the user's subject, audience, duration, and aspect ratio; an explicitly different
6
+ style or palette overrides this default.
7
+
8
+ ## Default visual and narrative direction
9
+
10
+ - **Start with a question worth seeing answered.** Give the viewer a concrete
11
+ example to predict or inspect. Build intuition before naming the general rule.
12
+ - **Make the mathematical objects the main actors.** Let a graph, geometry,
13
+ field, system, or construction occupy the stage. Develop it through the
14
+ explanation, with enough spatial continuity to follow what changed and why.
15
+ - **Use a clean dark canvas.** Favor black or deep charcoal, crisp geometry,
16
+ white mathematical typography, and a few clear accents. Blue and warm yellow
17
+ are useful starting accents; assign colors by mathematical role and preserve
18
+ those roles between diagrams, symbols, and transitions. Keep grids subdued.
19
+ - **Let notation grow from the construction.** Introduce a formula when the
20
+ diagram has established its meaning. Place corresponding terms and objects
21
+ in the same colors. Transform relevant terms deliberately, exposing the
22
+ reasoning instead of replacing complete screens of equations.
23
+ - **Choreograph discoveries.** Use smooth drawing, motion, decomposition,
24
+ regrouping, comparison, and parameter sweeps. Focus the camera or emphasize
25
+ an object when a detail becomes important. Leave time for the viewer to make
26
+ an inference before stating it, then test or generalize the insight.
27
+ - **Narrate as an explanation.** When using narration, generate it through
28
+ `retiam/tts`. Use conversational questions and precise language, synchronize
29
+ speech with visible events, and allow meaningful silent pauses. Keep requested
30
+ subtitles unobtrusive so they leave room for the mathematical construction.
31
+
32
+ The goal is a clear, satisfying visual argument. Choose 2D or 3D according to
33
+ the concept. Use a slide, dashboard, or another aesthetic when requested.
34
+
35
+ ## Plan events the viewer can see
36
+
37
+ For each substantial beat, identify:
38
+
39
+ | Decision | Useful answer |
40
+ | --- | --- |
41
+ | What must become clear? | A relationship, cause, comparison, or mechanism |
42
+ | What visibly changes? | A path, configuration, parameter, grouping, or viewpoint |
43
+ | What carries continuity? | The same point, node, symbol, shape, or color meaning |
44
+ | Where should the eye go? | One object or relationship at a time |
45
+ | What warrants a pause? | A meaningful comparison or resolved result |
46
+
47
+ Write an action such as “the second point travels along the curve while the
48
+ secant rotates and the gap collapses.” “Explain the derivative” or “show the next
49
+ heading” does not specify a visual event. Derive the number and length of beats
50
+ from the explanation; do not impose the same five scenes on every subject.
51
+
52
+ Prefer an evolving construction: establish the objects, expose a contrast or
53
+ problem, show the mechanism changing the state, then resolve and generalize.
54
+ Preserve enough context that the viewer can understand each transformation.
55
+
56
+ ## Choreograph meaning
57
+
58
+ - **Carry the idea in geometry.** Trace an actual route, move a point along its
59
+ function, deform the existing object, reveal how pieces assemble, or run the
60
+ simulation. Text describes a result after the viewer has seen its cause.
61
+ - **Preserve identity.** Move or transform the same object between states. Keep
62
+ variable colors consistent between diagrams and formulas. Use matching-symbol
63
+ transforms for a meaningful equation change when appropriate.
64
+ When unrelated symbols should disappear, use `morphUnmatched: false` rather
65
+ than deforming every leftover glyph into a new one.
66
+ - **Direct attention.** Establish context, emphasize the current relationship,
67
+ and widen the view for the result. Zoom or pan only when a close relationship,
68
+ changing frontier, or new scale benefits from it. A well-composed static shot
69
+ can support excellent motion; constant camera movement can obscure it.
70
+ - **Use a few distinct motion functions.** Drawing reveals structure; travel
71
+ shows flow; a morph preserves correspondence; a brief pulse marks a state
72
+ change; a hold gives time to infer. Choose the functions the concept needs.
73
+ - **Coordinate timing.** Related changes should happen together. Give an action
74
+ an appropriate acceleration, settle, and readable pause. Use `Concurrent`
75
+ with an explicit group duration so its defaults do not retime the children.
76
+ Use linear progress for uniform physical/data sweeps and eased motion for
77
+ entrances or changes that should settle; follow the actual simulated model.
78
+ - **Keep labels local and short.** Anchor a cost near the affected node or a
79
+ quantity beside its geometric span. Prefer a few precise words to paragraphs.
80
+ Use `Tex` for formulas and meaningful term matching, not plain text equations.
81
+ - **Let narration explain why.** Align each utterance with the event it explains.
82
+ If requested, use `retiam/tts` and its prepared audio duration. Repeatedly
83
+ replacing paragraphs beside an otherwise idle diagram is not enough motion.
84
+
85
+ Choose colors for hierarchy and meaning, with enough contrast for the output.
86
+ Keep guides quieter than active geometry and leave negative space. The default
87
+ dark palette supports the construction; glow, 3D, and sound effects need an
88
+ explanatory purpose.
89
+
90
+ ## Presentation patterns to revise
91
+
92
+ For an animation brief, revise these patterns unless they serve a specific need:
93
+
94
+ - A permanent title/header, large body panel, footer, chapter number, and page
95
+ counter framing every beat in the same layout.
96
+ - A diagram occupying one corner while most of the frame is explanatory text.
97
+ - An entire screen fading away, followed by a new heading and another fade-in.
98
+ - A long voiceover over a static scene with only a progress bar or decorative glow.
99
+ - Identical reveal timing for every beat, or unrelated objects appearing at once.
100
+ - An algorithm shown mainly as table rows changing while its mechanism stays idle.
101
+
102
+ For example, a Dijkstra explanation can begin with a question about competing
103
+ routes in the graph. Let the viewer predict a winner, then show why counting
104
+ roads can fail when their costs differ. Make the reason for finalizing the
105
+ cheapest unsettled cost visible using the nonnegative-edge assumption.
106
+ Trace the inspected edge, show the candidate cost beside the affected node, and
107
+ visibly retain or reject that route. Move attention with the active frontier,
108
+ keep cost and settled-state meanings consistent, then dim explored clutter and
109
+ trace the winning path. Use a priority queue or table when explaining that
110
+ structure, rather than reserving half the canvas for one throughout the video.
111
+ Follow actual weighted relaxation order; decorative propagation must not imply
112
+ an incorrect algorithm.
113
+
114
+ ## Working reference
115
+
116
+ [SecantToTangent.ts](../examples/SecantToTangent.ts) is a silent visual reference:
117
+
118
+ | Time | Visible event | Purpose |
119
+ | --- | --- | --- |
120
+ | 0–3.1 s | Draw the curve, mark two points, introduce the secant and its gap | Establish the construction |
121
+ | 3.1–6.3 s | Move the second point along the curve; the line rotates and the gap shrinks | Show what determines the secant slope |
122
+ | 6.3–11.1 s | Bring attention closer and continue the convergence | Make the limiting relationship visible |
123
+ | 11.1–13.1 s | Resolve the tangent and transform the equation | Connect geometry to notation |
124
+ | 13.1–19.5 s | Move the tangent point across both sides of the curve, updating the slope | Generalize beyond one frozen example |
125
+ | 19.5–21.5 s | Hold the resolved construction | Allow the takeaway to register |
126
+
127
+ The smaller `ExplainMotion.ts` and `NarratedMotion.ts` examples isolate API and
128
+ speech mechanics. They are not visual templates for finished explainers.
129
+
130
+ ## Review the rendered evidence
131
+
132
+ Capture the setup, the middle of the main mechanism, a transition, and the resolved
133
+ state at the intended aspect ratio. Open the PNGs and watch playback.
134
+
135
+ - Is the mathematical/data relationship correct throughout the motion?
136
+ - Does the construction establish intuition before introducing the general rule?
137
+ - Do corresponding geometric objects and mathematical terms keep their color meaning?
138
+ - Is the focal object clear, with readable labels and no accidental overlap or clipping?
139
+ - Does the main action demonstrate the idea without requiring every caption?
140
+ - Can the viewer follow the same object through transitions and reframing?
141
+ - Do motion and pauses feel purposeful when watched at normal speed?
142
+ - Does the conclusion remain visible long enough to read?
143
+
144
+ Compare the middle of adjacent beats. If only the heading or paragraph changes,
145
+ redesign the visible action. A deliberate reading hold or final rest is useful;
146
+ idle slides throughout an explanation need revision. Record concrete observed
147
+ issues and fix them. Lint and type checks cannot judge aesthetic quality or
148
+ explanatory correctness, and static screenshots cannot establish pacing.
@@ -0,0 +1,58 @@
1
+ # Visual style profiles
2
+
3
+ Teaching goals and visual style are independent. Read the user's prompt first.
4
+ An explicit requested style overrides `lesson/lesson.json`; save that choice so
5
+ future revisions remain consistent. Keep the same mathematical/content model and
6
+ narration cues when restyling. Preserve explicit brand, aspect and accessibility
7
+ constraints. `retiam lesson styles --json` gives actual tokens for this version.
8
+
9
+ ## mathematical — default, matching the Dijkstra video
10
+
11
+ Use navy `#0A1020`, light text, vivid blue and gold, with mint, coral, violet and
12
+ teal available as stable object identities. Color carries meaning across the
13
+ construction, labels, formulas and data transfers. Do not turn the palette into
14
+ random per-frame decoration. Let lines trace real paths, values travel between
15
+ representations, replacements settle smoothly and discarded candidates fade.
16
+ Ask a question, allow a thinking pause, then reveal its answer through geometry.
17
+ Use native `Tex` and syntax-highlighted `Code` where they explain the subject.
18
+ Introduce tables and queues as teaching objects only when relevant. Maintain
19
+ spatial continuity through derivations and applications; conclude with the idea
20
+ that the evolving construction has established.
21
+
22
+ ## excalidraw — hand-drawn whiteboard
23
+
24
+ Use warm paper, dark ink, blue and amber markers. The profile selects Retiam's
25
+ bundled `excalifont` for vector labels. Use native `toExcalidraw` through
26
+ `styleGeometry`, and `drawGeometry` for progressive sketch drawing. Use seeded,
27
+ restrained roughness, intentional arrows and light hatching. Keep mathematical
28
+ symbols readable in `Tex`. A question, sketched experiment and resolving annotation
29
+ can share one evolving board. Use dark paper as a custom override if requested.
30
+ Do not apply roughness to every text glyph or continuously jitter all labels.
31
+
32
+ ## minimal — clear vector construction
33
+
34
+ Use a light canvas, precise outlines, generous negative space and a small number
35
+ of semantic colors. Motion should isolate a relation: align, compare, decompose,
36
+ transfer or resolve. Keep labels local and avoid filling the quiet space with
37
+ paragraphs. Minimal graphics can still carry a lively teacher's narration.
38
+
39
+ ## cinematic — deliberate depth and staging
40
+
41
+ Use a dark canvas, violet/teal accents, slower establishing moves and a strong
42
+ focus for the current event. Use depth or 3D when it explains a spatial relation;
43
+ 2D with deliberate staging is also valid. Lighting and highlights support the
44
+ mechanism. Keep labels and formulas clear as the camera moves, and let the
45
+ resolved state rest. Motion quality does not require constant camera movement.
46
+
47
+ ## Custom override
48
+
49
+ A prompt can describe a new palette or reference look. Preserve the selected
50
+ profile's useful behavior while overriding tokens in JSON, for example:
51
+
52
+ ```json
53
+ {"style":{"extends":"excalidraw","name":"Night chalkboard","background":"#122322","ink":"#F4F2DD","primary":"#7DE1C4","secondary":"#F1CC75","muted":"#94AAA5","accents":["#7DE1C4","#F1CC75"]}}
54
+ ```
55
+
56
+ `resolveStyle` validates the tokens. Fonts must be bundled aliases or available
57
+ user-supplied font assets. Profile changes affect only entities using the profile;
58
+ agent-authored custom colors/materials must be reviewed during a restyle.
@@ -0,0 +1,72 @@
1
+ # Native Retiam narration
2
+
3
+ Generate speech for Retiam scenes through `retiam/tts`. It supplies synthesis,
4
+ timing, subtitle synchronization, and playback through the scene's voiceover bus.
5
+ The built-in provider uses Microsoft Edge neural speech over the network. It
6
+ does not require installing Python TTS packages.
7
+
8
+ Use [NarratedMotion.ts](../examples/NarratedMotion.ts) as the executable recipe.
9
+ Copy it into `src/scenes/` to preview or render it. Adapt the text, voice, and
10
+ motion to the brief. Use a different speech generator only if the user requests
11
+ one; diagnose failures in this path instead of silently replacing it.
12
+
13
+ ## Browser and renderer setup
14
+
15
+ New projects enable the native proxy in their Vite configuration. For an existing
16
+ project using an engine release that provides `retiam/vite`, preserve its other
17
+ plugins and add:
18
+
19
+ ```ts
20
+ import { defineConfig } from 'vite';
21
+ import { msEdgeTTSPlugin } from 'retiam/vite';
22
+
23
+ export default defineConfig({ plugins: [msEdgeTTSPlugin()] });
24
+ ```
25
+
26
+ This is a **server-side** import. Scene code imports speech APIs from `retiam/tts`.
27
+ The middleware serves `/api/tts/msedge/synthesize` in Vite development and preview
28
+ servers, including the Vite server started by Retiam's render/snapshot commands.
29
+ A static production host needs an equivalent server endpoint or pre-generated
30
+ audio; bundling the page alone does not host speech synthesis.
31
+
32
+ ## Timeline recipe
33
+
34
+ - Use `Speak` as an animation for simultaneous narration and motion. Set `entity`
35
+ to an entity already added to the scene so speech uses that scene's audio bus.
36
+ Call `prepareAudio()` first; its result sets the animation's exact duration.
37
+ - Register the **synthesis promise** in `this.composer.pendingTasks` before
38
+ awaiting it. Headless tools can then wait for network speech generation without
39
+ advancing the scene past the narration. Do not register `this.play(...)` or
40
+ `speak(...)` promises there: they need timeline updates and would deadlock.
41
+ - Set accompanying motion duration from the prepared `Speak.duration`. Avoid
42
+ guessing speech duration from word counts. Also pass that duration explicitly
43
+ to `Concurrent` so the group's defaults do not rescale the prepared narration.
44
+ - For sequential narration, `await speak(this, text, options)` synthesizes,
45
+ plays, synchronizes optional subtitles, and waits for the utterance duration.
46
+ Pre-synthesize that text with `TTS.synthesize(text, options)` and register only
47
+ its synthesis promise before headless rendering; the default provider caches
48
+ the result in memory.
49
+ - `TTS.speak(...)` is a different, lower-level client facade. Its playback result
50
+ does not itself provide the scene's `wait(...)` pacing.
51
+ - Add `new Subtitles({ fontSize, bottomOffset, maxWidth, ... })` to the scene, and
52
+ pass it as `subtitles`. Keep the caption area within the shot. Caption timing
53
+ uses the generated audio metadata.
54
+ - `voice` is a voice ID such as `en-US-JennyNeural`; `speed` is a multiplier
55
+ such as `1.0`, `pitch` accepts values such as `'+0Hz'`, and playback `volume`
56
+ is 0–1. Follow installed types for more options.
57
+
58
+ ## Diagnose native TTS failures
59
+
60
+ 1. A missing `retiam/vite` import means the installed engine predates this setup
61
+ or its build is incomplete. Check `retiam context --json` and the installed
62
+ package version before changing providers.
63
+ 2. HTTP 404 at `/api/tts/msedge/synthesize` means the middleware is absent or the
64
+ configured endpoint differs. Fix the Vite configuration and restart the server.
65
+ 3. HTTP 502 means the proxy ran but synthesis failed. Read the server error;
66
+ check network access and the requested voice. Do not present silent audio as
67
+ a successful narration render.
68
+ 4. Browser autoplay may require a click or keypress to unlock audio in Studio.
69
+ The headless CLI supplies its autoplay flag.
70
+ 5. For exported video, verify an audio stream exists and listen to the result.
71
+ Snapshots verify visuals only. Speech generation requires network access on a
72
+ cache miss; the middleware caches audio in `node_modules/.cache/msedge-tts`.
@@ -0,0 +1,25 @@
1
+ {
2
+ "version": 1,
3
+ "title": "Why does area grow so fast?",
4
+ "topic": "How a square's area changes when its side length doubles",
5
+ "audience": "Curious beginners",
6
+ "objective": "See why doubling both side lengths produces four unit squares.",
7
+ "style": "mathematical",
8
+ "narration": {"enabled": false, "provider": "msedge", "voice": "en-US-AndrewNeural", "speed": 1, "pitch": "+0Hz", "volume": 1},
9
+ "sources": [],
10
+ "claims": [{"id":"area-model","text":"A square of side two can be partitioned into four squares of side one.","sourceIds":[],"illustrative":true}],
11
+ "beats": [
12
+ {"id":"predict","goal":"Invite a prediction before exposing the area.","visibleChange":"Draw one unit square and mark its side length.","focus":"The original square","minDurationMs":4500,
13
+ "narration":[{"id":"question","text":"Here is one unit square. If we double its side length, what happens to its area?","pauseAfterMs":900}],
14
+ "cues":[{"id":"show","segment":"question"}]},
15
+ {"id":"grow","goal":"Separate a change in side length from a change in area.","visibleChange":"Expand the outline while retaining the original square.","focus":"Both sides grow","minDurationMs":5000,
16
+ "narration":[{"id":"expand","text":"Let's double both sides. The original square still fits in the corner. How much new space have we made?","pauseAfterMs":700}],
17
+ "cues":[{"id":"expand","segment":"expand"}]},
18
+ {"id":"count","goal":"Discover the four equal areas through decomposition.","visibleChange":"Reveal the three additional unit squares in sequence.","focus":"Four equal pieces","minDurationMs":5000,
19
+ "narration":[{"id":"reveal","text":"One here, another above, and one more in the corner. Together with our original square, that makes four."}],
20
+ "cues":[{"id":"reveal","segment":"reveal"}]},
21
+ {"id":"connect","goal":"Connect the construction to the general area relationship.","visibleChange":"Keep all four pieces visible and reveal the equation below them.","focus":"Side length and area","minDurationMs":4500,
22
+ "narration":[{"id":"insight","text":"Two times the side length gives four times the area. That's the square in side squared: two growing directions, multiplied together."}],
23
+ "cues":[{"id":"equation","segment":"insight"}]}
24
+ ]
25
+ }
@@ -0,0 +1,6 @@
1
+ {
2
+ "automated": {},
3
+ "observations": [],
4
+ "requiredReview": ["Check factual claims and illustrative model assumptions.","Inspect the beginning, prediction pause, main mechanism, transition and conclusion.","Watch a short preview at normal speed to assess pacing and attention.","Verify the final audio track, captions and video dimensions."],
5
+ "status": "not-reviewed"
6
+ }
@@ -0,0 +1,92 @@
1
+ {
2
+ "mathematical": {
3
+ "name": "Dijkstra-style mathematical explainer",
4
+ "background": "#0A1020",
5
+ "ink": "#ECF0F5",
6
+ "muted": "#74869C",
7
+ "primary": "#6CD5FF",
8
+ "secondary": "#F7CF73",
9
+ "font": "roboto",
10
+ "strokeWidth": 0.035,
11
+ "rough": false,
12
+ "roughness": 0,
13
+ "fillStyle": "solid",
14
+ "motion": {
15
+ "drawMs": 1200,
16
+ "moveMs": 1400,
17
+ "holdMs": 700
18
+ },
19
+ "accents": [
20
+ "#65F0C4",
21
+ "#FF879F",
22
+ "#BA98FF",
23
+ "#55DDE0"
24
+ ]
25
+ },
26
+ "excalidraw": {
27
+ "name": "Excalidraw whiteboard",
28
+ "background": "#FFFDF7",
29
+ "ink": "#263238",
30
+ "muted": "#7B858C",
31
+ "primary": "#1971C2",
32
+ "secondary": "#D46B08",
33
+ "font": "excalifont",
34
+ "strokeWidth": 0.04,
35
+ "rough": true,
36
+ "roughness": 0.7,
37
+ "fillStyle": "hachure",
38
+ "motion": {
39
+ "drawMs": 1600,
40
+ "moveMs": 1500,
41
+ "holdMs": 900
42
+ },
43
+ "accents": [
44
+ "#1971C2",
45
+ "#D46B08"
46
+ ]
47
+ },
48
+ "minimal": {
49
+ "name": "Minimal vector",
50
+ "background": "#F8FAFC",
51
+ "ink": "#17212B",
52
+ "muted": "#68788A",
53
+ "primary": "#2563EB",
54
+ "secondary": "#C2410C",
55
+ "font": "roboto",
56
+ "strokeWidth": 0.025,
57
+ "rough": false,
58
+ "roughness": 0,
59
+ "fillStyle": "solid",
60
+ "motion": {
61
+ "drawMs": 900,
62
+ "moveMs": 1100,
63
+ "holdMs": 650
64
+ },
65
+ "accents": [
66
+ "#2563EB",
67
+ "#C2410C"
68
+ ]
69
+ },
70
+ "cinematic": {
71
+ "name": "Cinematic diagrams",
72
+ "background": "#080B18",
73
+ "ink": "#F4F1FF",
74
+ "muted": "#8290AA",
75
+ "primary": "#B79AFF",
76
+ "secondary": "#58E0CE",
77
+ "font": "roboto",
78
+ "strokeWidth": 0.04,
79
+ "rough": false,
80
+ "roughness": 0,
81
+ "fillStyle": "solid",
82
+ "motion": {
83
+ "drawMs": 1500,
84
+ "moveMs": 2000,
85
+ "holdMs": 1000
86
+ },
87
+ "accents": [
88
+ "#B79AFF",
89
+ "#58E0CE"
90
+ ]
91
+ }
92
+ }
@@ -0,0 +1,26 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ import { fileURLToPath } from 'node:url';
4
+ import {copyLessonKit} from './lesson-project.js';
5
+
6
+ export const agentKitRoot = fileURLToPath(new URL('../agent/', import.meta.url));
7
+
8
+ /** Used only while creating an empty project or preparing a fresh template. */
9
+ export function copyAgentKit(directory, options = {}) {
10
+ const files = [];
11
+ for (const name of ['AGENTS.md', 'CLAUDE.md']) {
12
+ fs.copyFileSync(path.join(agentKitRoot, name), path.join(directory, name));
13
+ files.push(name);
14
+ }
15
+ const destination = path.join(directory, '.agents/skills/retiam');
16
+ fs.cpSync(path.join(agentKitRoot, 'skill'), destination, { recursive: true });
17
+ function collect(folder) {
18
+ for (const entry of fs.readdirSync(folder, { withFileTypes: true })) {
19
+ const location = path.join(folder, entry.name);
20
+ if (entry.isDirectory()) collect(location);
21
+ else files.push(path.relative(directory, location).split(path.sep).join('/'));
22
+ }
23
+ }
24
+ collect(destination);
25
+ return [...files,...copyLessonKit(directory,options)];
26
+ }
package/bin/cli.js CHANGED
@@ -20,13 +20,17 @@ const exportScript = path.join(__dirname, 'export.js');
20
20
  const lintScript = path.join(__dirname, 'lint.js');
21
21
  const snapshotScript = path.join(__dirname, 'snapshot.js');
22
22
  const initScript = path.join(__dirname, 'init.js');
23
+ const contextScript = path.join(__dirname, 'context.js');
24
+ const lessonScript = path.join(__dirname, 'lesson.js');
23
25
 
24
26
  function runScript(scriptPath, scriptArgs) {
25
27
  if (scriptPath === renderScript || scriptPath === snapshotScript) {
26
28
  try {
27
29
  createRequire(import.meta.url).resolve('puppeteer');
28
30
  } catch {
29
- console.error('Retiam installation is incomplete: its required Puppeteer dependency is missing. Reinstall Retiam in your project with: npm install retiam');
31
+ const message = 'Retiam installation is incomplete: its required Puppeteer dependency is missing. Reinstall Retiam in your project with: npm install retiam';
32
+ if (scriptPath === snapshotScript && scriptArgs.includes('--json')) console.log(JSON.stringify({ status: 'error', message }));
33
+ console.error(message);
30
34
  process.exit(1);
31
35
  }
32
36
  }
@@ -48,6 +52,8 @@ Usage:
48
52
  npx retiam help <command> (detailed help for a single command)
49
53
 
50
54
  Commands Overview:
55
+ lesson Teaching plans, styles, native narration, cue timelines, and captions
56
+ context Locate version-matched agent guidance, examples, and API declarations
51
57
  init, create Initialize a complete Retiam WebGPU animation skeleton project
52
58
  lint Statically analyze scenes for runtime hazards and async timing bugs
53
59
  snapshot Capture multi-timestamp visual PNG keyframes via headless WebGPU
@@ -85,7 +91,7 @@ Commands Overview:
85
91
 
86
92
  ================================================================================
87
93
  2. SNAPSHOT (npx retiam snapshot <file> [options])
88
- Capture visual PNG keyframe snapshots at specific timeline seconds.
94
+ Run the named scene directly and capture PNGs at fixed-step timeline seconds.
89
95
 
90
96
  Arguments:
91
97
  <file> Target scene TypeScript file (e.g. MyScene.ts)
@@ -95,6 +101,8 @@ Commands Overview:
95
101
  -w, --width <px> Snapshot width in pixels (default: 1280)
96
102
  -h, --height <px> Snapshot height in pixels (default: 720)
97
103
  -o, --out <dir> Output directory for images (default: ./outputs/snapshot)
104
+ --fps <num> Timeline step rate (default: 60)
105
+ --timeout <ms> Browser operation timeout (default: 120000)
98
106
  --json Output structured JSON for agents & CI automation
99
107
  --help Show snapshot-specific help
100
108
 
@@ -113,6 +121,8 @@ Commands Overview:
113
121
  Options:
114
122
  -n, --name <name> Project name for package.json (default: directory name)
115
123
  --title <text> Hero text for starter Hello World scene (default: Hello World)
124
+ --template <name> basic (default) or explainer worked construction
125
+ --style <name> mathematical (Dijkstra default), excalidraw, minimal, cinematic
116
126
  --pm <manager> Package manager: npm, pnpm, yarn, bun (default: auto or npm)
117
127
  -f, --force Overwrite destination directory if files already exist
118
128
  -y, --yes Skip interactive prompts and use defaults
@@ -167,7 +177,13 @@ Commands Overview:
167
177
  `);
168
178
  }
169
179
 
170
- if (command === 'lint') {
180
+ if (command === 'lesson') {
181
+ runScript(lessonScript, args.slice(1));
182
+ }
183
+ else if (command === 'context') {
184
+ runScript(contextScript, args.slice(1));
185
+ }
186
+ else if (command === 'lint') {
171
187
  // Usage: npx retiam lint src/MyScene.ts [--json]
172
188
  runScript(lintScript, args.slice(1));
173
189
  }
@@ -189,7 +205,11 @@ else if (command === 'render') {
189
205
  }
190
206
  else if (command === 'help') {
191
207
  const sub = args[1];
192
- if (sub === 'lint') {
208
+ if (sub === 'lesson') {
209
+ runScript(lessonScript, ['--help']);
210
+ } else if (sub === 'context') {
211
+ runScript(contextScript, ['--help']);
212
+ } else if (sub === 'lint') {
193
213
  runScript(lintScript, ['--help']);
194
214
  } else if (sub === 'snapshot') {
195
215
  runScript(snapshotScript, ['--help']);