@ai-rpg-engine/presentation 2.0.0 → 2.0.1

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.
package/README.md ADDED
@@ -0,0 +1,66 @@
1
+ <p align="center">
2
+ <img src="https://raw.githubusercontent.com/mcp-tool-shop-org/brand/main/logos/ai-rpg-engine/readme.png" width="300" alt="AI RPG Engine">
3
+ </p>
4
+
5
+ <p align="center">
6
+ <a href="https://www.npmjs.com/package/@ai-rpg-engine/presentation"><img src="https://img.shields.io/npm/v/@ai-rpg-engine/presentation.svg" alt="npm"></a>
7
+ <a href="https://github.com/mcp-tool-shop-org/ai-rpg-engine/actions/workflows/ci.yml"><img src="https://github.com/mcp-tool-shop-org/ai-rpg-engine/actions/workflows/ci.yml/badge.svg" alt="CI"></a>
8
+ <a href="https://github.com/mcp-tool-shop-org/ai-rpg-engine/blob/main/LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
9
+ </p>
10
+
11
+ # @ai-rpg-engine/presentation
12
+
13
+ Narration plan schema, render contracts, and presentation state types for the [AI RPG Engine](https://github.com/mcp-tool-shop-org/ai-rpg-engine).
14
+
15
+ Part of the **Immersion Runtime** — the multi-modal presentation pipeline that transforms game state into structured audio-visual experiences.
16
+
17
+ ## Install
18
+
19
+ ```bash
20
+ npm install @ai-rpg-engine/presentation
21
+ ```
22
+
23
+ ## What It Does
24
+
25
+ Instead of outputting raw prose, the narrator produces a **NarrationPlan** — a structured recipe describing text, sound effects, ambient layers, music cues, UI effects, and voice synthesis parameters.
26
+
27
+ Any frontend (terminal, web, Electron) implements the `PresentationRenderer` interface to receive and execute these plans.
28
+
29
+ ## Key Types
30
+
31
+ | Type | Purpose |
32
+ |------|---------|
33
+ | `NarrationPlan` | Structured narration recipe (text + SFX + ambient + music + UI) |
34
+ | `SpeakerCue` | Voice synthesis parameters (voice ID, emotion, speed) |
35
+ | `SfxCue` | Sound effect trigger (effect ID, timing, intensity) |
36
+ | `AmbientCue` | Ambient layer control (start, stop, crossfade) |
37
+ | `MusicCue` | Background music control (play, stop, intensify, soften) |
38
+ | `UiEffect` | Terminal/screen visual effects (flash, shake, fade) |
39
+ | `VoiceProfile` | Voice configuration for speech synthesis |
40
+ | `PresentationRenderer` | Render contract — any frontend implements this |
41
+
42
+ ## Usage
43
+
44
+ ```typescript
45
+ import type { NarrationPlan, PresentationRenderer } from '@ai-rpg-engine/presentation';
46
+ import { validateNarrationPlan, isValidNarrationPlan } from '@ai-rpg-engine/presentation';
47
+
48
+ // Validate a plan from Claude's output
49
+ const errors = validateNarrationPlan(planFromClaude);
50
+ if (errors.length === 0) {
51
+ // Plan is valid, execute it
52
+ }
53
+
54
+ // Type guard
55
+ if (isValidNarrationPlan(data)) {
56
+ console.log(data.sceneText);
57
+ }
58
+ ```
59
+
60
+ ## Part of AI RPG Engine
61
+
62
+ This package is part of the [AI RPG Engine](https://github.com/mcp-tool-shop-org/ai-rpg-engine) monorepo. See the root README for the full architecture.
63
+
64
+ ## License
65
+
66
+ MIT
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=validate.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.d.ts","sourceRoot":"","sources":["../src/validate.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,45 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { validateNarrationPlan, isValidNarrationPlan } from './validate.js';
3
+ describe('validateNarrationPlan', () => {
4
+ const validPlan = {
5
+ sceneText: 'You step into a dimly lit chapel.',
6
+ tone: 'dread',
7
+ urgency: 'normal',
8
+ sfx: [{ effectId: 'ui_whoosh', timing: 'immediate', intensity: 0.5 }],
9
+ ambientLayers: [{ layerId: 'ambient_drone', action: 'start', volume: 0.3, fadeMs: 1000 }],
10
+ uiEffects: [],
11
+ interruptibility: 'free',
12
+ };
13
+ it('should accept a valid plan', () => {
14
+ const errors = validateNarrationPlan(validPlan);
15
+ expect(errors).toHaveLength(0);
16
+ expect(isValidNarrationPlan(validPlan)).toBe(true);
17
+ });
18
+ it('should reject non-object', () => {
19
+ expect(validateNarrationPlan(null)).toHaveLength(1);
20
+ expect(validateNarrationPlan('string')).toHaveLength(1);
21
+ });
22
+ it('should reject empty sceneText', () => {
23
+ const errors = validateNarrationPlan({ ...validPlan, sceneText: '' });
24
+ expect(errors.some((e) => e.field === 'sceneText')).toBe(true);
25
+ });
26
+ it('should reject invalid tone', () => {
27
+ const errors = validateNarrationPlan({ ...validPlan, tone: 'invalid' });
28
+ expect(errors.some((e) => e.field === 'tone')).toBe(true);
29
+ });
30
+ it('should reject invalid sfx timing', () => {
31
+ const errors = validateNarrationPlan({
32
+ ...validPlan,
33
+ sfx: [{ effectId: 'x', timing: 'invalid', intensity: 0.5 }],
34
+ });
35
+ expect(errors.some((e) => e.field.includes('timing'))).toBe(true);
36
+ });
37
+ it('should reject sfx intensity out of range', () => {
38
+ const errors = validateNarrationPlan({
39
+ ...validPlan,
40
+ sfx: [{ effectId: 'x', timing: 'immediate', intensity: 1.5 }],
41
+ });
42
+ expect(errors.some((e) => e.field.includes('intensity'))).toBe(true);
43
+ });
44
+ });
45
+ //# sourceMappingURL=validate.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"validate.test.js","sourceRoot":"","sources":["../src/validate.test.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ai-rpg-engine/presentation",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "Narration plan schema, render contracts, and presentation state types for AI RPG Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",