retiam 2.0.1 → 2.0.3
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/THIRD_PARTY_NOTICES.md +3 -3
- package/agent/AGENTS.md +70 -0
- package/agent/CLAUDE.md +2 -0
- package/agent/skill/SKILL.md +114 -0
- package/agent/skill/examples/AreaLesson.ts +48 -0
- package/agent/skill/examples/ExplainMotion.ts +32 -0
- package/agent/skill/examples/NarratedMotion.ts +50 -0
- package/agent/skill/examples/SecantToTangent.ts +142 -0
- package/agent/skill/references/api.md +111 -0
- package/agent/skill/references/explainers.md +123 -0
- package/agent/skill/references/quality.md +151 -0
- package/agent/skill/references/styles.md +58 -0
- package/agent/skill/references/tts.md +166 -0
- package/agent/templates/explainer/lesson.json +25 -0
- package/agent/templates/explainer/review.json +6 -0
- package/agent/templates/explainer/styles.json +92 -0
- package/bin/agent-kit.js +26 -0
- package/bin/cli.js +24 -4
- package/bin/context.js +57 -0
- package/bin/init.js +71 -12
- package/bin/lesson-project.js +30 -0
- package/bin/lesson.js +195 -0
- package/bin/lint.js +6 -6
- package/bin/snapshot-runtime.js +185 -0
- package/bin/snapshot.js +32 -225
- package/dist/THIRD_PARTY_NOTICES.md +3 -3
- package/dist/UTIF-D6vx2UEX.min.js +1 -0
- package/dist/{UTIF-2Ear_0Uo.js → UTIF-mkffT70R.js} +1 -1
- package/dist/decompress-D7LzbvPD.min.js +15 -0
- package/dist/{index-B2sJBy4c.js → index-CdBPrYbr.js} +3830 -3795
- package/dist/index-jgFyrc2D.min.js +10472 -0
- package/dist/libs/explainer/example.d.ts +3 -0
- package/dist/libs/explainer/index.d.ts +5 -0
- package/dist/libs/explainer/index.js +135 -0
- package/dist/libs/explainer/plan.d.ts +12 -0
- package/dist/libs/explainer/plan.js +219 -0
- package/dist/libs/explainer/runtime.d.ts +24 -0
- package/dist/libs/explainer/styles.d.ts +3 -0
- package/dist/libs/explainer/types.d.ts +124 -0
- package/dist/libs/explainer/visuals.d.ts +18 -0
- package/dist/libs/tts/animations/Speak.d.ts +13 -7
- package/dist/libs/tts/components/TTSNarrationComponent.d.ts +9 -7
- package/dist/libs/tts/core/TTSCache.d.ts +3 -3
- package/dist/libs/tts/core/TTSClient.d.ts +3 -3
- package/dist/libs/tts/core/types.d.ts +48 -6
- package/dist/libs/tts/index.d.ts +2 -1
- package/dist/libs/tts/index.js +203 -1333
- package/dist/libs/tts/node/index.d.ts +10 -0
- package/dist/libs/tts/node/index.js +791 -0
- package/dist/libs/tts/providers/ElevenLabsTTSProvider.d.ts +30 -0
- package/dist/libs/tts/providers/ITTSProvider.d.ts +2 -2
- package/dist/libs/vite/index.d.ts +28 -0
- package/dist/libs/vite/index.js +158 -0
- package/dist/main-Cc4QQbSK.min.js +5939 -0
- package/dist/{main-D_G4uIju.js → main-DMu_5Qy7.js} +1 -1
- package/dist/msEdgeV2-D3w4Xsn-.js +642 -0
- package/dist/opentype.module-B-1cYAb-.min.js +1 -0
- package/dist/retiam.es.js +1 -1
- package/dist/retiam.es.min.js +1 -0
- package/dist/src/engine/animation/Animation.d.ts +1 -0
- package/dist/src/engine/entities/composites/text/mathjaxInterop.d.ts +6 -0
- package/package.json +15 -8
- package/readme.md +27 -7
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ITTSProvider } from './ITTSProvider';
|
|
2
|
+
import { ElevenLabsTTSConfig, TTSAudioResult, TTSGenerateOptions, TTSStreamChunk, VoiceInfo } from '../core/types';
|
|
3
|
+
/**
|
|
4
|
+
* Direct REST provider for browser and Node runtimes. Initialize with your API key;
|
|
5
|
+
* no Vite middleware or SDK is needed. Browser-supplied keys remain browser-visible.
|
|
6
|
+
*/
|
|
7
|
+
export declare class ElevenLabsTTSProvider implements ITTSProvider {
|
|
8
|
+
#private;
|
|
9
|
+
readonly name = "elevenlabs";
|
|
10
|
+
private _ready;
|
|
11
|
+
private _revision;
|
|
12
|
+
private _voices;
|
|
13
|
+
private _cache;
|
|
14
|
+
private readonly _pending;
|
|
15
|
+
private readonly _controllers;
|
|
16
|
+
get isReady(): boolean;
|
|
17
|
+
/** Validates and stores configuration locally. Does not spend credits or fetch voices. */
|
|
18
|
+
init(config?: ElevenLabsTTSConfig): Promise<void>;
|
|
19
|
+
synthesize(text: string, options?: TTSGenerateOptions): Promise<TTSAudioResult>;
|
|
20
|
+
/** Sentence-sized synthesis, matching Retiam's stream contract (not byte streaming). */
|
|
21
|
+
stream(text: string, options?: TTSGenerateOptions): AsyncGenerator<TTSStreamChunk>;
|
|
22
|
+
getVoices(): VoiceInfo[];
|
|
23
|
+
/** Fetches the authenticated, paginated voice catalog explicitly. */
|
|
24
|
+
fetchVoices(): Promise<VoiceInfo[]>;
|
|
25
|
+
clearCache(): void;
|
|
26
|
+
dispose(): Promise<void>;
|
|
27
|
+
private _assertReady;
|
|
28
|
+
private _reset;
|
|
29
|
+
private _request;
|
|
30
|
+
}
|
|
@@ -5,7 +5,7 @@ import { TTSAudioResult, TTSConfig, TTSGenerateOptions, TTSStreamChunk, VoiceInf
|
|
|
5
5
|
export interface ITTSProvider {
|
|
6
6
|
/** Distinct provider identifier (for example, "msedge-tts"). */
|
|
7
7
|
readonly name: string;
|
|
8
|
-
/** Indicates whether the
|
|
8
|
+
/** Indicates whether the provider is initialized for synthesis. */
|
|
9
9
|
readonly isReady: boolean;
|
|
10
10
|
/**
|
|
11
11
|
* Initializes provider configuration and any required runtime resources.
|
|
@@ -24,7 +24,7 @@ export interface ITTSProvider {
|
|
|
24
24
|
*/
|
|
25
25
|
getVoices(): VoiceInfo[];
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
27
|
+
* Releases provider resources and cached audio.
|
|
28
28
|
*/
|
|
29
29
|
dispose(): Promise<void>;
|
|
30
30
|
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { Plugin } from 'vite';
|
|
2
|
+
export interface MsEdgeTTSPluginOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Base route path for the Edge TTS endpoints.
|
|
5
|
+
* Defaults to "/api/tts/msedge".
|
|
6
|
+
*/
|
|
7
|
+
basePath?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Directory for persisting synthesized audio and metadata to disk.
|
|
10
|
+
* Defaults to "node_modules/.cache/msedge-tts".
|
|
11
|
+
*/
|
|
12
|
+
cacheDir?: string;
|
|
13
|
+
/**
|
|
14
|
+
* Whether to log synthesis and voice fetching events in the console.
|
|
15
|
+
* Defaults to true.
|
|
16
|
+
*/
|
|
17
|
+
verbose?: boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Vite plugin that serves high-performance Microsoft Edge Text-To-Speech endpoints
|
|
21
|
+
* during development (`npm run dev`) and preview (`npm run cdn`).
|
|
22
|
+
*
|
|
23
|
+
* Provides:
|
|
24
|
+
* - `GET /api/tts/msedge/voices` - Live catalog of all 320+ Edge neural voices
|
|
25
|
+
* - `POST /api/tts/msedge/synthesize` - Synthesizes text with word boundaries and MP3 audio
|
|
26
|
+
* - `GET /api/tts/msedge/synthesize` - Stream-friendly GET endpoint for direct HTML5 audio playback
|
|
27
|
+
*/
|
|
28
|
+
export declare function msEdgeTTSPlugin(options?: MsEdgeTTSPluginOptions): Plugin;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
import { f as I, c as j, p as K } from "../../msEdgeV2-D3w4Xsn-.js";
|
|
2
|
+
import l from "node:fs";
|
|
3
|
+
import B from "node:path";
|
|
4
|
+
import z from "node:crypto";
|
|
5
|
+
/*! Retiam: noncommercial use only unless separately licensed. See ../../LICENSE and ../../COMMERCIAL_LICENSE.md. Third-party notices: ../../THIRD_PARTY_NOTICES.md and ../../THIRD_PARTY_LICENSES.txt. */
|
|
6
|
+
const h = /* @__PURE__ */ new Map();
|
|
7
|
+
function Y(P = {}) {
|
|
8
|
+
const b = (P.basePath || "/api/tts/msedge").replace(/\/$/, ""), U = P.verbose !== !1, x = async (a, e, C) => {
|
|
9
|
+
if (!a.url || !a.url.startsWith(b))
|
|
10
|
+
return C();
|
|
11
|
+
const J = a.url.split("?")[0].substring(b.length);
|
|
12
|
+
if (e.setHeader("Access-Control-Allow-Origin", "*"), e.setHeader("Access-Control-Allow-Methods", "GET, POST, OPTIONS"), e.setHeader("Access-Control-Allow-Headers", "Content-Type"), e.setHeader(
|
|
13
|
+
"Access-Control-Expose-Headers",
|
|
14
|
+
"X-Audio-Duration-Ms, X-Audio-Sample-Rate, X-Word-Boundaries"
|
|
15
|
+
), a.method === "OPTIONS") {
|
|
16
|
+
e.statusCode = 204, e.end();
|
|
17
|
+
return;
|
|
18
|
+
}
|
|
19
|
+
if (J === "/voices" && a.method === "GET")
|
|
20
|
+
try {
|
|
21
|
+
const d = await I();
|
|
22
|
+
e.statusCode = 200, e.setHeader("Content-Type", "application/json; charset=utf-8"), e.setHeader("Cache-Control", "public, max-age=86400"), e.end(JSON.stringify(d));
|
|
23
|
+
return;
|
|
24
|
+
} catch (d) {
|
|
25
|
+
console.error("[MsEdge TTS Plugin] Error fetching voices:", d), e.statusCode = 502, e.end(JSON.stringify({ error: d.message }));
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
if (J === "/synthesize") {
|
|
29
|
+
let d = "", m = "en-US-JennyNeural", g = 1, y, r;
|
|
30
|
+
if (a.method === "GET") {
|
|
31
|
+
const t = new URL(a.url, "http://localhost");
|
|
32
|
+
d = t.searchParams.get("text") || "", m = t.searchParams.get("voice") || m, g = parseFloat(t.searchParams.get("speed") || "1.0"), y = t.searchParams.get("pitch") || void 0, r = t.searchParams.get("volume") || void 0;
|
|
33
|
+
} else if (a.method === "POST")
|
|
34
|
+
try {
|
|
35
|
+
const t = await new Promise((p, n) => {
|
|
36
|
+
let u = "";
|
|
37
|
+
a.on("data", (w) => u += w), a.on("end", () => p(u)), a.on("error", n);
|
|
38
|
+
}), s = JSON.parse(t || "{}");
|
|
39
|
+
d = s.text || "", m = s.voice || m, g = typeof s.speed == "number" ? s.speed : g, y = s.pitch, r = s.volume;
|
|
40
|
+
} catch {
|
|
41
|
+
e.statusCode = 400, e.end(JSON.stringify({ error: "Invalid JSON body" }));
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
else
|
|
45
|
+
return C();
|
|
46
|
+
const S = d.trim();
|
|
47
|
+
if (!S) {
|
|
48
|
+
e.statusCode = 400, e.end(JSON.stringify({ error: "Text cannot be empty" }));
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
const T = `${m}_${g}_${y || ""}_${r || ""}_${S}`;
|
|
52
|
+
let c = h.get(T);
|
|
53
|
+
const M = P.cacheDir || B.resolve(process.cwd(), "node_modules/.cache/msedge-tts"), $ = z.createHash("sha256").update(T).digest("hex"), A = B.join(M, `${$}.mp3`), H = B.join(M, `${$}.json`);
|
|
54
|
+
if (!c && l.existsSync(A) && l.existsSync(H))
|
|
55
|
+
try {
|
|
56
|
+
const t = l.readFileSync(A), s = JSON.parse(l.readFileSync(H, "utf-8"));
|
|
57
|
+
c = {
|
|
58
|
+
audioBuffer: t,
|
|
59
|
+
durationMs: s.durationMs,
|
|
60
|
+
sampleRate: s.sampleRate,
|
|
61
|
+
wordBoundaries: s.wordBoundaries || []
|
|
62
|
+
}, h.set(T, c);
|
|
63
|
+
} catch {
|
|
64
|
+
}
|
|
65
|
+
if (c) {
|
|
66
|
+
e.statusCode = 200, e.setHeader("Content-Type", "audio/mpeg"), e.setHeader("X-Audio-Duration-Ms", c.durationMs.toString()), e.setHeader("X-Audio-Sample-Rate", c.sampleRate.toString()), e.setHeader(
|
|
67
|
+
"X-Word-Boundaries",
|
|
68
|
+
encodeURIComponent(JSON.stringify(c.wordBoundaries))
|
|
69
|
+
), e.end(c.audioBuffer);
|
|
70
|
+
return;
|
|
71
|
+
}
|
|
72
|
+
try {
|
|
73
|
+
U && console.log(`[MsEdge TTS Plugin] 🎙️ Synthesizing: "${S.slice(0, 40)}..." (${m})`);
|
|
74
|
+
const t = Math.round((g - 1) * 100), p = { rate: t >= 0 ? `+${t}%` : `${t}%` };
|
|
75
|
+
if (y && (p.pitch = y), r != null && r !== "") {
|
|
76
|
+
const o = parseFloat(String(r));
|
|
77
|
+
!isNaN(o) && !String(r).includes("%") && !String(r).startsWith("+") && !String(r).startsWith("-") ? p.volume = o <= 1 && o > 0 ? Math.round(o * 100) : Math.round(o) : p.volume = r;
|
|
78
|
+
}
|
|
79
|
+
let n = null, u = [], w = null;
|
|
80
|
+
for (let o = 0; o < 3; o++)
|
|
81
|
+
try {
|
|
82
|
+
const { MsEdgeTTS: v, OUTPUT_FORMAT: N } = await import("msedge-tts");
|
|
83
|
+
j(v);
|
|
84
|
+
const D = new v();
|
|
85
|
+
await D.setMetadata(m, N.AUDIO_24KHZ_96KBITRATE_MONO_MP3, {
|
|
86
|
+
wordBoundaryEnabled: !0
|
|
87
|
+
});
|
|
88
|
+
const { audioStream: R, metadataStream: W } = D.toStream(S, p), _ = [];
|
|
89
|
+
if (u = [], W && W.on("data", (E) => {
|
|
90
|
+
try {
|
|
91
|
+
const O = JSON.parse(E.toString());
|
|
92
|
+
if (Array.isArray(O?.Metadata)) {
|
|
93
|
+
for (const i of O.Metadata)
|
|
94
|
+
if (i.Type === "WordBoundary" && i.Data) {
|
|
95
|
+
const X = (i.Data.Offset || 0) / 1e4, k = (i.Data.Duration || 0) / 1e4, F = i.Data.text?.Text || "";
|
|
96
|
+
u.push({
|
|
97
|
+
text: F,
|
|
98
|
+
offsetMs: X,
|
|
99
|
+
durationMs: k,
|
|
100
|
+
boundaryType: "WordBoundary"
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
} catch {
|
|
105
|
+
}
|
|
106
|
+
}), await new Promise((E, O) => {
|
|
107
|
+
R.on("data", (i) => _.push(i)), R.on("end", () => E()), R.on("error", (i) => O(i));
|
|
108
|
+
}), n = Buffer.concat(_), n.length > 0)
|
|
109
|
+
break;
|
|
110
|
+
} catch (v) {
|
|
111
|
+
w = v, await new Promise((N) => setTimeout(N, 350));
|
|
112
|
+
}
|
|
113
|
+
if (!n || n.length === 0)
|
|
114
|
+
throw w || new Error("Synthesis failed after 3 attempts.");
|
|
115
|
+
const f = K(new Uint8Array(n));
|
|
116
|
+
if (h.size > 256) {
|
|
117
|
+
const o = h.keys().next().value;
|
|
118
|
+
o && h.delete(o);
|
|
119
|
+
}
|
|
120
|
+
h.set(T, {
|
|
121
|
+
audioBuffer: n,
|
|
122
|
+
durationMs: f.durationMs,
|
|
123
|
+
sampleRate: f.sampleRate,
|
|
124
|
+
wordBoundaries: u
|
|
125
|
+
});
|
|
126
|
+
try {
|
|
127
|
+
l.existsSync(M) || l.mkdirSync(M, { recursive: !0 }), l.writeFileSync(A, n), l.writeFileSync(H, JSON.stringify({
|
|
128
|
+
durationMs: f.durationMs,
|
|
129
|
+
sampleRate: f.sampleRate,
|
|
130
|
+
wordBoundaries: u
|
|
131
|
+
}));
|
|
132
|
+
} catch {
|
|
133
|
+
}
|
|
134
|
+
e.statusCode = 200, e.setHeader("Content-Type", "audio/mpeg"), e.setHeader("X-Audio-Duration-Ms", f.durationMs.toString()), e.setHeader("X-Audio-Sample-Rate", f.sampleRate.toString()), e.setHeader(
|
|
135
|
+
"X-Word-Boundaries",
|
|
136
|
+
encodeURIComponent(JSON.stringify(u))
|
|
137
|
+
), e.end(n);
|
|
138
|
+
return;
|
|
139
|
+
} catch (t) {
|
|
140
|
+
console.error("[MsEdge TTS Plugin] Synthesis error:", t), e.statusCode = 502, e.end(JSON.stringify({ error: t.message || "Synthesis failed" }));
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
C();
|
|
145
|
+
};
|
|
146
|
+
return {
|
|
147
|
+
name: "msedge-tts-server-plugin",
|
|
148
|
+
configureServer(a) {
|
|
149
|
+
a.middlewares.use(x);
|
|
150
|
+
},
|
|
151
|
+
configurePreviewServer(a) {
|
|
152
|
+
a.middlewares.use(x);
|
|
153
|
+
}
|
|
154
|
+
};
|
|
155
|
+
}
|
|
156
|
+
export {
|
|
157
|
+
Y as msEdgeTTSPlugin
|
|
158
|
+
};
|