@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 +66 -0
- package/dist/validate.test.d.ts +2 -0
- package/dist/validate.test.d.ts.map +1 -0
- package/dist/validate.test.js +45 -0
- package/dist/validate.test.js.map +1 -0
- package/package.json +1 -1
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 @@
|
|
|
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