retiam 2.0.0 → 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.
- package/THIRD_PARTY_NOTICES.md +3 -3
- package/agent/AGENTS.md +67 -0
- package/agent/CLAUDE.md +2 -0
- package/agent/skill/SKILL.md +111 -0
- package/agent/skill/examples/AreaLesson.ts +48 -0
- package/agent/skill/examples/ExplainMotion.ts +32 -0
- package/agent/skill/examples/NarratedMotion.ts +42 -0
- package/agent/skill/examples/SecantToTangent.ts +142 -0
- package/agent/skill/references/api.md +109 -0
- package/agent/skill/references/explainers.md +121 -0
- package/agent/skill/references/quality.md +148 -0
- package/agent/skill/references/styles.md +58 -0
- package/agent/skill/references/tts.md +72 -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 +168 -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-BrQ3Ng5l.min.js +1 -0
- package/dist/{UTIF-2Ear_0Uo.js → UTIF-CN0-pEnd.js} +1 -1
- package/dist/decompress-D7LzbvPD.min.js +15 -0
- package/dist/index-3sAseSJQ.min.js +10472 -0
- package/dist/{index-B2sJBy4c.js → index-yQIdejOj.js} +15 -13
- package/dist/libs/explainer/example.d.ts +3 -0
- package/dist/libs/explainer/index.d.ts +5 -0
- package/dist/libs/explainer/index.js +134 -0
- package/dist/libs/explainer/plan.d.ts +12 -0
- package/dist/libs/explainer/plan.js +197 -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 +119 -0
- package/dist/libs/explainer/visuals.d.ts +18 -0
- package/dist/libs/tts/index.js +386 -1009
- package/dist/libs/vite/index.d.ts +28 -0
- package/dist/libs/vite/index.js +158 -0
- package/dist/{main-D_G4uIju.js → main-BTk_9jtl.js} +1 -1
- package/dist/main-lQwYAed8.min.js +5939 -0
- package/dist/msEdgeV2-BLEnvPJa.js +641 -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/package.json +12 -6
- package/readme.md +14 -7
|
@@ -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-BLEnvPJa.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
|
+
};
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { g as Jh, a as Zh } from "./index-
|
|
1
|
+
import { g as Jh, a as Zh } from "./index-yQIdejOj.js";
|
|
2
2
|
/*! 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. */
|
|
3
3
|
function Qh(n, t) {
|
|
4
4
|
for (var e = 0; e < t.length; e++) {
|