@pie-players/pie-assessment-toolkit 0.3.73 → 0.3.74
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 +171 -56
- package/dist/attempt/AssessmentSession.d.ts +1 -5
- package/dist/attempt/AssessmentSession.js +0 -29
- package/dist/components/ItemToolBar.custom-element.d.ts +1 -0
- package/dist/components/ItemToolBar.custom-element.js +1 -1
- package/dist/components/PieAssessmentToolkit.custom-element.d.ts +1 -0
- package/dist/components/PieAssessmentToolkit.custom-element.js +14 -14
- package/dist/components/SectionToolBar.custom-element.d.ts +1 -0
- package/dist/components/SectionToolBar.custom-element.js +1 -1
- package/dist/components/chunks/ItemToolBar-b9dz5jvd.js +40 -0
- package/dist/components/chunks/ItemToolBar-gmrryv2v.js +2 -0
- package/dist/components/chunks/ItemToolBar-h4xap0t0.js +4 -0
- package/dist/components/chunks/ItemToolBar-wr2myaah.js +2 -0
- package/dist/components/chunks/sre-engine-wf9s43gg.js +1 -0
- package/dist/context/assessment-toolkit-context.d.ts +5 -0
- package/dist/context/runtime-context-consumer.js +5 -38
- package/dist/index.d.ts +6 -6
- package/dist/index.js +8 -9
- package/dist/policy/core/ToolPolicyEngine.d.ts +8 -2
- package/dist/policy/core/ToolPolicyEngine.js +12 -0
- package/dist/runtime/adapter/SectionEngineAdapter.d.ts +3 -3
- package/dist/runtime/adapter/SectionEngineAdapter.js +3 -3
- package/dist/runtime/registration-events.d.ts +3 -0
- package/dist/runtime/section-runtime-engine-host-context.d.ts +3 -9
- package/dist/runtime/section-runtime-engine-host-context.js +5 -43
- package/dist/runtime/tool-host-contract.d.ts +20 -0
- package/dist/runtime/tool-host-contract.js +21 -0
- package/dist/services/HighlightCoordinator.d.ts +1 -7
- package/dist/services/HighlightCoordinator.js +1 -3
- package/dist/services/TTSService.d.ts +15 -1
- package/dist/services/TTSService.js +88 -35
- package/dist/services/ToolCoordinator.d.ts +1 -7
- package/dist/services/ToolCoordinator.js +1 -3
- package/dist/services/ToolRegistry.d.ts +13 -6
- package/dist/services/ToolRegistry.js +19 -7
- package/dist/services/ToolkitCoordinator.d.ts +110 -18
- package/dist/services/ToolkitCoordinator.js +273 -85
- package/dist/services/catalog-owner.d.ts +11 -0
- package/dist/services/catalog-owner.js +25 -0
- package/dist/services/create-tools-config.d.ts +2 -2
- package/dist/services/framework-error.d.ts +8 -1
- package/dist/services/interfaces.d.ts +9 -9
- package/dist/services/pnp-standard-features.d.ts +1 -1
- package/dist/services/section-controller-types.d.ts +15 -0
- package/dist/services/spoken-audio-cards.js +1 -1
- package/dist/services/tool-config-validation.d.ts +13 -2
- package/dist/services/tool-config-validation.js +33 -16
- package/dist/services/tool-context.js +29 -13
- package/dist/services/tool-providers/TTSToolProvider.d.ts +27 -65
- package/dist/services/tool-providers/TTSToolProvider.js +47 -9
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts +4 -4
- package/dist/services/tool-providers/ToolProviderRegistry.js +4 -16
- package/dist/services/tool-providers/index.d.ts +0 -9
- package/dist/services/tool-providers/index.js +2 -4
- package/dist/services/tools-config-normalizer.d.ts +20 -1
- package/dist/services/tts/catalog-span-alignment.d.ts +2 -17
- package/dist/services/tts/catalog-span-alignment.js +17 -142
- package/dist/services/tts/generated-speech/types.d.ts +0 -12
- package/dist/services/tts/highlight-pipeline/boundary-normalizer.js +12 -62
- package/dist/services/tts/highlight-pipeline/create-highlight-plan.js +26 -1
- package/dist/services/tts/highlight-pipeline/normalize-speech-chunks.js +3 -6
- package/dist/services/tts/math-alignment/index.d.ts +0 -5
- package/dist/services/tts/math-alignment/index.js +5 -25
- package/dist/services/tts/math-alignment/speech-tokenizer.d.ts +9 -1
- package/dist/services/tts/math-alignment/speech-tokenizer.js +38 -36
- package/dist/services/tts/math-alignment/types.d.ts +4 -2
- package/dist/services/tts/math-aware-text-processing.js +44 -2
- package/dist/services/tts/math-speech.d.ts +5 -1
- package/dist/services/tts/math-speech.js +9 -6
- package/dist/services/tts/sre-engine.d.ts +7 -0
- package/dist/services/tts/sre-engine.js +11 -0
- package/dist/services/tts/sre-locales.d.ts +14 -0
- package/dist/services/tts/sre-locales.js +57 -0
- package/dist/services/tts/text-processing.d.ts +0 -1
- package/dist/services/tts/text-processing.js +0 -1
- package/dist/services/tts-runtime-config.d.ts +21 -3
- package/dist/services/tts-runtime-config.js +11 -3
- package/dist/tools/client.d.ts +1 -3
- package/dist/tools/client.js +1 -5
- package/dist/tools/internal.d.ts +6 -5
- package/dist/tools/internal.js +6 -8
- package/package.json +17 -36
- package/dist/components/chunks/ItemToolBar-byq80z42.js +0 -40
- package/dist/components/chunks/ItemToolBar-d36g3aw4.js +0 -49
- package/dist/services/ToolConfigResolver.d.ts +0 -161
- package/dist/services/ToolConfigResolver.js +0 -229
- package/dist/services/catalog-media.d.ts +0 -56
- package/dist/services/catalog-media.js +0 -190
- package/dist/services/createDefaultToolRegistry.d.ts +0 -53
- package/dist/services/createDefaultToolRegistry.js +0 -45
- package/dist/services/tool-providers/CortexToolProvider.d.ts +0 -13
- package/dist/services/tool-providers/CortexToolProvider.js +0 -32
- package/dist/services/tool-providers/DesmosToolProvider.d.ts +0 -14
- package/dist/services/tool-providers/DesmosToolProvider.js +0 -32
- package/dist/services/tool-providers/GeoGebraToolProvider.d.ts +0 -16
- package/dist/services/tool-providers/GeoGebraToolProvider.js +0 -32
- package/dist/services/tool-providers/LazyCalculatorToolProvider.d.ts +0 -35
- package/dist/services/tool-providers/LazyCalculatorToolProvider.js +0 -95
- package/dist/services/tts/visual-line-ranges.d.ts +0 -18
- package/dist/services/tts/visual-line-ranges.js +0 -226
- package/dist/tools/index.d.ts +0 -8
- package/dist/tools/index.js +0 -10
- package/dist/tools/response-discovery.d.ts +0 -61
- package/dist/tools/response-discovery.js +0 -113
- package/dist/tools/types.d.ts +0 -337
- package/dist/tools/types.js +0 -12
- package/dist/tools/variant-resolver.d.ts +0 -41
- package/dist/tools/variant-resolver.js +0 -207
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { extractSpokenText } from "../ssml/spoken-text.js";
|
|
2
2
|
import { createSpeechAlignmentTokenPattern } from "../text-processing.js";
|
|
3
|
-
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
3
|
+
// The one tokenizer and normalization table for TTS alignment. Spoken text,
|
|
4
|
+
// visible catalog text and provider boundary words all tokenize here, so a word
|
|
5
|
+
// normalizes the same way on the catalog, math and generated-speech paths.
|
|
6
6
|
const TOKEN_PATTERN = createSpeechAlignmentTokenPattern();
|
|
7
7
|
const NUMERIC_WORDS = new Map([
|
|
8
8
|
["zero", "0"],
|
|
@@ -21,24 +21,27 @@ const normalizedTokenValue = (value) => {
|
|
|
21
21
|
const normalized = value.toLowerCase();
|
|
22
22
|
return NUMERIC_WORDS.get(normalized) || normalized;
|
|
23
23
|
};
|
|
24
|
-
const
|
|
24
|
+
export const tokenizeAlignmentText = (text) => {
|
|
25
25
|
const tokens = [];
|
|
26
|
-
for (const match of
|
|
27
|
-
const
|
|
26
|
+
for (const match of text.matchAll(TOKEN_PATTERN)) {
|
|
27
|
+
const value = match[0];
|
|
28
28
|
const start = match.index ?? 0;
|
|
29
29
|
tokens.push({
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
normalized: normalizedTokenValue(text),
|
|
30
|
+
text: value,
|
|
31
|
+
normalized: normalizedTokenValue(value),
|
|
33
32
|
start,
|
|
34
|
-
end: start +
|
|
35
|
-
sourceStart: start,
|
|
36
|
-
sourceEnd: start + text.length,
|
|
37
|
-
coordinateSystem: "normalized-speech",
|
|
33
|
+
end: start + value.length,
|
|
38
34
|
});
|
|
39
35
|
}
|
|
40
36
|
return tokens;
|
|
41
37
|
};
|
|
38
|
+
const tokenizeSpokenText = (spokenText) => tokenizeAlignmentText(spokenText).map((token, index) => ({
|
|
39
|
+
...token,
|
|
40
|
+
id: `speech-token-${index}`,
|
|
41
|
+
sourceStart: token.start,
|
|
42
|
+
sourceEnd: token.end,
|
|
43
|
+
coordinateSystem: "normalized-speech",
|
|
44
|
+
}));
|
|
42
45
|
export const tokenizeSpeechSource = (args) => {
|
|
43
46
|
const extracted = extractSpokenText(args.speechText);
|
|
44
47
|
return {
|
|
@@ -55,15 +58,17 @@ export const tokenizeSpeechSource = (args) => {
|
|
|
55
58
|
hasMarkup: extracted.hasMarkup,
|
|
56
59
|
};
|
|
57
60
|
};
|
|
58
|
-
const
|
|
59
|
-
|
|
61
|
+
const isControlTagWord = (word) => Boolean(word && /^<[^>]+>$/.test(word.trim()));
|
|
62
|
+
/**
|
|
63
|
+
* A provider boundary word in the form spoken tokens compare in, or null when
|
|
64
|
+
* the word carries no token (empty, a control tag, punctuation). The word goes
|
|
65
|
+
* through the same SSML extraction as the chunk, so an entity-encoded word
|
|
66
|
+
* normalizes to the text it encodes.
|
|
67
|
+
*/
|
|
68
|
+
export const normalizeBoundaryWord = (word) => {
|
|
69
|
+
if (!word || isControlTagWord(word))
|
|
60
70
|
return null;
|
|
61
|
-
|
|
62
|
-
return null;
|
|
63
|
-
const match = word.match(TOKEN_PATTERN);
|
|
64
|
-
if (!match?.[0])
|
|
65
|
-
return null;
|
|
66
|
-
return normalizedTokenValue(match[0]);
|
|
71
|
+
return (tokenizeSpeechSource({ speechText: word }).tokens[0]?.normalized ?? null);
|
|
67
72
|
};
|
|
68
73
|
const findTokenAtOffset = (tokens, offset) => tokens.find((token) => token.start <= offset && offset < token.end) || null;
|
|
69
74
|
const mapRawOffsetToSpokenOffset = (tokenization, position) => {
|
|
@@ -92,32 +97,29 @@ const candidateForOffset = (tokenization, offset, length) => {
|
|
|
92
97
|
confidence: 0.75,
|
|
93
98
|
};
|
|
94
99
|
};
|
|
95
|
-
const candidateMatchesWord = (candidate,
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
normalizedBoundary &&
|
|
99
|
-
candidate.token.normalized === normalizedBoundary);
|
|
100
|
-
};
|
|
100
|
+
const candidateMatchesWord = (candidate, normalizedWord) => Boolean(candidate &&
|
|
101
|
+
normalizedWord &&
|
|
102
|
+
candidate.token.normalized === normalizedWord);
|
|
101
103
|
export const resolveBoundaryToSpeechToken = (args) => {
|
|
102
104
|
if (args.tokenization.boundaryOffsetSpace === "unsupported" ||
|
|
103
105
|
!Number.isFinite(args.position) ||
|
|
104
|
-
(args.boundaryWord
|
|
106
|
+
isControlTagWord(args.boundaryWord)) {
|
|
105
107
|
return null;
|
|
106
108
|
}
|
|
107
109
|
const safeLength = Math.max(1, Number.isFinite(args.length) ? args.length : 1);
|
|
110
|
+
const normalizedWord = normalizeBoundaryWord(args.boundaryWord);
|
|
108
111
|
const rawCandidate = candidateForOffset(args.tokenization, mapRawOffsetToSpokenOffset(args.tokenization, args.position), safeLength);
|
|
109
112
|
const plainCandidate = candidateForOffset(args.tokenization, args.position >= 0 && args.position < args.tokenization.spokenText.length
|
|
110
113
|
? args.position
|
|
111
114
|
: null, safeLength);
|
|
112
|
-
if (candidateMatchesWord(rawCandidate,
|
|
115
|
+
if (candidateMatchesWord(rawCandidate, normalizedWord)) {
|
|
113
116
|
return { ...rawCandidate, confidence: 1 };
|
|
114
117
|
}
|
|
115
|
-
if (candidateMatchesWord(plainCandidate,
|
|
118
|
+
if (candidateMatchesWord(plainCandidate, normalizedWord)) {
|
|
116
119
|
return { ...plainCandidate, confidence: 1 };
|
|
117
120
|
}
|
|
118
|
-
if (
|
|
121
|
+
if (normalizedWord)
|
|
119
122
|
return null;
|
|
120
|
-
}
|
|
121
123
|
return args.tokenization.boundaryOffsetSpace === "raw-ssml"
|
|
122
124
|
? rawCandidate || plainCandidate
|
|
123
125
|
: plainCandidate || rawCandidate;
|
|
@@ -125,18 +127,18 @@ export const resolveBoundaryToSpeechToken = (args) => {
|
|
|
125
127
|
export const resolveSpokenOffsetToSpeechToken = (args) => {
|
|
126
128
|
if (args.tokenization.boundaryOffsetSpace === "unsupported" ||
|
|
127
129
|
!Number.isFinite(args.position) ||
|
|
128
|
-
(args.boundaryWord
|
|
130
|
+
isControlTagWord(args.boundaryWord)) {
|
|
129
131
|
return null;
|
|
130
132
|
}
|
|
131
133
|
const safeLength = Math.max(1, Number.isFinite(args.length) ? args.length : 1);
|
|
134
|
+
const normalizedWord = normalizeBoundaryWord(args.boundaryWord);
|
|
132
135
|
const spokenCandidate = candidateForOffset(args.tokenization, args.position >= 0 && args.position < args.tokenization.spokenText.length
|
|
133
136
|
? args.position
|
|
134
137
|
: null, safeLength);
|
|
135
|
-
if (candidateMatchesWord(spokenCandidate,
|
|
138
|
+
if (candidateMatchesWord(spokenCandidate, normalizedWord)) {
|
|
136
139
|
return { ...spokenCandidate, confidence: 1 };
|
|
137
140
|
}
|
|
138
|
-
if (
|
|
141
|
+
if (normalizedWord)
|
|
139
142
|
return null;
|
|
140
|
-
}
|
|
141
143
|
return spokenCandidate;
|
|
142
144
|
};
|
|
@@ -34,12 +34,14 @@ export interface MathMLTokenizationResult {
|
|
|
34
34
|
}
|
|
35
35
|
export type BoundaryCoordinateSystem = "normalized-speech" | "raw-ssml" | "provider-speech-marks";
|
|
36
36
|
export type BoundaryOffsetSpace = "plain-spoken-text" | "raw-ssml" | "unsupported";
|
|
37
|
-
export interface
|
|
38
|
-
id: string;
|
|
37
|
+
export interface AlignmentTextToken {
|
|
39
38
|
text: string;
|
|
40
39
|
normalized: string;
|
|
41
40
|
start: number;
|
|
42
41
|
end: number;
|
|
42
|
+
}
|
|
43
|
+
export interface SpeechAlignmentToken extends AlignmentTextToken {
|
|
44
|
+
id: string;
|
|
43
45
|
sourceStart: number;
|
|
44
46
|
sourceEnd: number;
|
|
45
47
|
coordinateSystem: BoundaryCoordinateSystem;
|
|
@@ -44,7 +44,6 @@ const findCanonicalMathML = (element) => {
|
|
|
44
44
|
}
|
|
45
45
|
return null;
|
|
46
46
|
};
|
|
47
|
-
const isMathContainer = (element) => Boolean(findCanonicalMathML(element));
|
|
48
47
|
const TEXT_CHUNK_SOURCE_TAGS = new Set([
|
|
49
48
|
"P",
|
|
50
49
|
"H1",
|
|
@@ -223,6 +222,49 @@ const textFallbackFromMathML = (mathml) => {
|
|
|
223
222
|
visit(parsed.documentElement);
|
|
224
223
|
return normalizeTextForSpeech(parts.join(" "));
|
|
225
224
|
};
|
|
225
|
+
// MathJax CHTML paints its glyphs from CSS, so a typeset equation's only text
|
|
226
|
+
// nodes are the source MathML it keeps, clipped, in mjx-assistive-mml. Mapping
|
|
227
|
+
// the fallback text onto them places a catalog word inside its equation, where
|
|
228
|
+
// the rendered-math resolver finds the glyph. Any divergence between the two
|
|
229
|
+
// texts leaves the fallback unmapped.
|
|
230
|
+
const mapFallbackToAssistiveMath = (element, fallbackText) => {
|
|
231
|
+
const map = new Map();
|
|
232
|
+
const sourceMath = isMathJaxElement(element)
|
|
233
|
+
? element.querySelector("mjx-assistive-mml math")
|
|
234
|
+
: null;
|
|
235
|
+
if (!sourceMath)
|
|
236
|
+
return map;
|
|
237
|
+
const characters = [];
|
|
238
|
+
const visit = (node) => {
|
|
239
|
+
if (node.nodeType === 3) {
|
|
240
|
+
const text = node.textContent || "";
|
|
241
|
+
for (let offset = 0; offset < text.length; offset++) {
|
|
242
|
+
if (!/\s/.test(text[offset])) {
|
|
243
|
+
characters.push({ node: node, offset });
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
if (node.nodeType !== 1 || isAnnotationElement(node))
|
|
249
|
+
return;
|
|
250
|
+
for (const child of Array.from(node.childNodes)) {
|
|
251
|
+
visit(child);
|
|
252
|
+
}
|
|
253
|
+
};
|
|
254
|
+
visit(sourceMath);
|
|
255
|
+
let next = 0;
|
|
256
|
+
for (let index = 0; index < fallbackText.length; index++) {
|
|
257
|
+
if (/\s/.test(fallbackText[index]))
|
|
258
|
+
continue;
|
|
259
|
+
const mapping = characters[next];
|
|
260
|
+
if (mapping?.node.textContent?.[mapping.offset] !== fallbackText[index]) {
|
|
261
|
+
return new Map();
|
|
262
|
+
}
|
|
263
|
+
map.set(index, mapping);
|
|
264
|
+
next++;
|
|
265
|
+
}
|
|
266
|
+
return next === characters.length ? map : new Map();
|
|
267
|
+
};
|
|
226
268
|
const collectVisibleMathFallback = (element, canonicalMathML, options) => {
|
|
227
269
|
const mathAcc = createAccumulator(options);
|
|
228
270
|
const visit = (node) => {
|
|
@@ -255,7 +297,7 @@ const collectVisibleMathFallback = (element, canonicalMathML, options) => {
|
|
|
255
297
|
}
|
|
256
298
|
return {
|
|
257
299
|
text: fallbackText,
|
|
258
|
-
map:
|
|
300
|
+
map: mapFallbackToAssistiveMath(element, fallbackText),
|
|
259
301
|
};
|
|
260
302
|
};
|
|
261
303
|
const trimTrailingWhitespace = (acc) => {
|
|
@@ -25,7 +25,11 @@ export interface SREMathSpeechOptions {
|
|
|
25
25
|
domain?: string;
|
|
26
26
|
/** Raw SRE style/preference string. ClearSpeak preferences are ":"-joined. */
|
|
27
27
|
style?: string;
|
|
28
|
-
/**
|
|
28
|
+
/**
|
|
29
|
+
* Extra SRE setupEngine options for hosts that need a newly exposed SRE knob.
|
|
30
|
+
* In a browser, SRE's locale tables load from the host's bundle unless `json`
|
|
31
|
+
* (a base URL or path) or `custom` (a loader) names another source.
|
|
32
|
+
*/
|
|
29
33
|
engineOptions?: Record<string, unknown>;
|
|
30
34
|
}
|
|
31
35
|
export interface ResolvedMathSpeech {
|
|
@@ -1,12 +1,12 @@
|
|
|
1
|
+
import { setSreStartupLocaleSource, sreLocaleSource } from "./sre-locales.js";
|
|
1
2
|
import { normalizeTextForSpeech } from "./text-processing.js";
|
|
2
3
|
let sreLoadPromise = null;
|
|
3
4
|
let sreOperationQueue = Promise.resolve();
|
|
4
5
|
const normalizeLocale = (language) => (language || "en").split("-")[0].toLowerCase() || "en";
|
|
5
|
-
const defaultLoadSre = async () => {
|
|
6
|
+
const defaultLoadSre = async (engineOptions) => {
|
|
6
7
|
if (!sreLoadPromise) {
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
module;
|
|
8
|
+
setSreStartupLocaleSource(engineOptions);
|
|
9
|
+
sreLoadPromise = import("./sre-engine.js").then(({ default: candidate }) => {
|
|
10
10
|
if (!candidate || typeof candidate.toSpeech !== "function") {
|
|
11
11
|
throw new Error("speech-rule-engine did not expose toSpeech");
|
|
12
12
|
}
|
|
@@ -41,8 +41,10 @@ export const normalizeSREMathSpeechOptions = (options) => {
|
|
|
41
41
|
const setupSre = async (sre, language, markup, mathSpeech) => {
|
|
42
42
|
const locale = normalizeLocale(language);
|
|
43
43
|
const normalizedMathSpeech = normalizeSREMathSpeechOptions(mathSpeech);
|
|
44
|
+
const engineOptions = normalizedMathSpeech?.engineOptions || {};
|
|
44
45
|
await sre.setupEngine?.({
|
|
45
|
-
...(
|
|
46
|
+
...sreLocaleSource(engineOptions),
|
|
47
|
+
...engineOptions,
|
|
46
48
|
locale,
|
|
47
49
|
domain: normalizedMathSpeech?.domain || domainForLocale(locale),
|
|
48
50
|
...(normalizedMathSpeech?.style
|
|
@@ -97,7 +99,8 @@ export const resolveMathSpeechFromChunks = async (chunks, options = {}) => {
|
|
|
97
99
|
let sre = null;
|
|
98
100
|
let usedMathSpeech = false;
|
|
99
101
|
let usedFallback = false;
|
|
100
|
-
const loadSre = options.loadSre ||
|
|
102
|
+
const loadSre = options.loadSre ||
|
|
103
|
+
(() => defaultLoadSre(normalizeSREMathSpeechOptions(options.mathSpeech)?.engineOptions));
|
|
101
104
|
const speechParts = [];
|
|
102
105
|
for (const chunk of chunks) {
|
|
103
106
|
if (chunk.type === "text") {
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import * as speechRuleEngine from "speech-rule-engine";
|
|
2
|
+
import { sreStartupLocaleSource } from "./sre-locales.js";
|
|
3
|
+
const sre = speechRuleEngine.default ?? speechRuleEngine;
|
|
4
|
+
// SRE starts itself up while this module's import of it evaluates, then loads
|
|
5
|
+
// `base` and `en` a few microtasks later from whatever locale source is set by
|
|
6
|
+
// then. In a bundle this call runs synchronously after that evaluation, so it
|
|
7
|
+
// lands first; configuring SRE after awaiting an `import()` of it lands after
|
|
8
|
+
// those loads. Bun drains microtasks between evaluating a CommonJS module and
|
|
9
|
+
// its importer, so there SRE reads `base` from its own package directory.
|
|
10
|
+
void sre.setupEngine(sreStartupLocaleSource());
|
|
11
|
+
export default sre;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `setupEngine` options naming where SRE reads locale tables from: the
|
|
3
|
+
* host's `json` (a base URL or path) or `custom` (a loader) when its
|
|
4
|
+
* `engineOptions` set either, otherwise the packaged tables wherever SRE would
|
|
5
|
+
* fetch them. SRE prefers `custom` over `json`, so the packaged loader is left
|
|
6
|
+
* out whenever the host names a source.
|
|
7
|
+
*/
|
|
8
|
+
export declare const sreLocaleSource: (engineOptions?: Record<string, unknown>) => Record<string, unknown>;
|
|
9
|
+
/**
|
|
10
|
+
* Sets the source SRE loads its start-up locales from; see `./sre-engine.ts`.
|
|
11
|
+
* Only a call made before that module first loads has any effect.
|
|
12
|
+
*/
|
|
13
|
+
export declare const setSreStartupLocaleSource: (engineOptions?: Record<string, unknown>) => void;
|
|
14
|
+
export declare const sreStartupLocaleSource: () => Record<string, unknown>;
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
// SRE loads each locale's rule tables at runtime, from a public CDN unless it is
|
|
2
|
+
// handed a source. An import per table lets the host's bundler emit each as a
|
|
3
|
+
// lazy chunk served from the host's own origin, but a build that inlines every
|
|
4
|
+
// `import()` into one file carries every table listed here, at 0.2 to 0.4 MB
|
|
5
|
+
// each. So only `base`, which every locale builds on, and the `en` and `es`
|
|
6
|
+
// locales are packaged; any other locale needs a source from the host's
|
|
7
|
+
// `engineOptions`. No `with { type: "json" }`: bundlers infer JSON from the
|
|
8
|
+
// extension, while Vite's dev server and Bun's bundler turn a table into
|
|
9
|
+
// JavaScript and keep the attribute, which a browser then rejects.
|
|
10
|
+
const SRE_LOCALE_TABLES = {
|
|
11
|
+
base: () => import("speech-rule-engine/lib/mathmaps/base.json"),
|
|
12
|
+
en: () => import("speech-rule-engine/lib/mathmaps/en.json"),
|
|
13
|
+
es: () => import("speech-rule-engine/lib/mathmaps/es.json"),
|
|
14
|
+
};
|
|
15
|
+
// SRE's `custom` loader contract: called with a locale name, resolving to that
|
|
16
|
+
// locale's table as a JSON string or an already-parsed object. SRE falls back
|
|
17
|
+
// to English when a table fails to load.
|
|
18
|
+
const loadPackagedSreLocale = async (locale) => {
|
|
19
|
+
if (!Object.hasOwn(SRE_LOCALE_TABLES, locale)) {
|
|
20
|
+
throw new Error(`no speech-rule-engine locale table is packaged for "${locale}"; name a source with mathSpeech.engineOptions.json or .custom`);
|
|
21
|
+
}
|
|
22
|
+
return (await SRE_LOCALE_TABLES[locale]()).default;
|
|
23
|
+
};
|
|
24
|
+
// SRE's own test for fetching tables over HTTP (`common/system_external.js`).
|
|
25
|
+
// Elsewhere it reads them from its package directory, which Node's ESM loader
|
|
26
|
+
// could not replace with the imports above: it requires the attribute.
|
|
27
|
+
const sreFetchesTables = () => (typeof window !== "undefined" && typeof window.document !== "undefined") ||
|
|
28
|
+
typeof globalThis
|
|
29
|
+
.DedicatedWorkerGlobalScope !== "undefined";
|
|
30
|
+
/**
|
|
31
|
+
* The `setupEngine` options naming where SRE reads locale tables from: the
|
|
32
|
+
* host's `json` (a base URL or path) or `custom` (a loader) when its
|
|
33
|
+
* `engineOptions` set either, otherwise the packaged tables wherever SRE would
|
|
34
|
+
* fetch them. SRE prefers `custom` over `json`, so the packaged loader is left
|
|
35
|
+
* out whenever the host names a source.
|
|
36
|
+
*/
|
|
37
|
+
export const sreLocaleSource = (engineOptions = {}) => {
|
|
38
|
+
const { json, custom } = engineOptions;
|
|
39
|
+
if (json || custom) {
|
|
40
|
+
return { ...(json ? { json } : {}), ...(custom ? { custom } : {}) };
|
|
41
|
+
}
|
|
42
|
+
return sreFetchesTables() ? { custom: loadPackagedSreLocale } : {};
|
|
43
|
+
};
|
|
44
|
+
// Resolved on first read: a call at module scope would keep the table imports
|
|
45
|
+
// in every bundle that includes this module, math speech used or not.
|
|
46
|
+
let startupLocaleSource;
|
|
47
|
+
/**
|
|
48
|
+
* Sets the source SRE loads its start-up locales from; see `./sre-engine.ts`.
|
|
49
|
+
* Only a call made before that module first loads has any effect.
|
|
50
|
+
*/
|
|
51
|
+
export const setSreStartupLocaleSource = (engineOptions) => {
|
|
52
|
+
startupLocaleSource = sreLocaleSource(engineOptions);
|
|
53
|
+
};
|
|
54
|
+
export const sreStartupLocaleSource = () => {
|
|
55
|
+
startupLocaleSource ??= sreLocaleSource();
|
|
56
|
+
return startupLocaleSource;
|
|
57
|
+
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { TTSConfig } from "./TTSService.js";
|
|
2
|
-
import type {
|
|
2
|
+
import type { TextToSpeechToolProviderConfig } from "./tools-config-normalizer.js";
|
|
3
3
|
import { type SREMathSpeechOptions } from "./tts/math-speech.js";
|
|
4
4
|
export type TTSLayoutMode = "reserved-row" | "expanding-row" | "floating-overlay" | "left-aligned";
|
|
5
5
|
export interface TTSHostToolbarLayout {
|
|
@@ -42,6 +42,12 @@ export interface TTSRuntimeSettings {
|
|
|
42
42
|
endpointMode?: "synthesizePath" | "rootPost";
|
|
43
43
|
endpointValidationMode?: "voices" | "endpoint" | "none";
|
|
44
44
|
includeAuthOnAssetFetch?: boolean;
|
|
45
|
+
/** Origins trusted with the `Authorization` header on asset fetches. */
|
|
46
|
+
assetOrigins?: string[];
|
|
47
|
+
/** Fetch `credentials` mode for requests to the TTS server. */
|
|
48
|
+
credentials?: "omit" | "same-origin" | "include";
|
|
49
|
+
/** Headers sent with every request to the TTS server. */
|
|
50
|
+
headers?: Record<string, string>;
|
|
45
51
|
validateEndpoint?: boolean;
|
|
46
52
|
cache?: boolean;
|
|
47
53
|
speedRate?: "slow" | "medium" | "fast";
|
|
@@ -75,6 +81,11 @@ export interface TTSRuntimeSettings {
|
|
|
75
81
|
* instead of relying on toolkit-specific speech rewrites.
|
|
76
82
|
*/
|
|
77
83
|
mathSpeech?: SREMathSpeechOptions;
|
|
84
|
+
/**
|
|
85
|
+
* Options passed through to the provider. The fields derived from the
|
|
86
|
+
* settings above, such as `locale` and the Polly engine, win over these.
|
|
87
|
+
*/
|
|
88
|
+
providerOptions?: Record<string, unknown>;
|
|
78
89
|
}
|
|
79
90
|
export declare const normalizeTTSLayoutMode: (value: unknown, fallback?: TTSLayoutMode) => TTSLayoutMode;
|
|
80
91
|
/** Legacy numeric helper defaults. Rendered controls add visible Normal separately. */
|
|
@@ -96,10 +107,17 @@ export declare const formatTTSSpeedOptionsAsText: (values: number[]) => string;
|
|
|
96
107
|
* - Non-empty text with no parseable finite numbers → same as invalid-only array config: defaults.
|
|
97
108
|
*/
|
|
98
109
|
export declare const parseTTSSpeedOptionsFromText: (text: string) => number[];
|
|
99
|
-
export declare const resolveTTSRuntimeSettings: (config:
|
|
110
|
+
export declare const resolveTTSRuntimeSettings: (config: TextToSpeechToolProviderConfig | TTSRuntimeSettings | undefined) => TTSRuntimeSettings;
|
|
100
111
|
export declare const resolveTTSBackend: (config: TTSRuntimeSettings) => NonNullable<TTSRuntimeSettings["backend"]>;
|
|
101
112
|
export declare const resolveRuntimeProvider: (config: TTSRuntimeSettings, backend: NonNullable<TTSRuntimeSettings["backend"]>) => TTSRuntimeSettings["serverProvider"];
|
|
102
113
|
export declare const resolveTransportMode: (config: TTSRuntimeSettings, runtimeProvider: TTSRuntimeSettings["serverProvider"]) => NonNullable<TTSRuntimeSettings["transportMode"]>;
|
|
103
|
-
|
|
114
|
+
/**
|
|
115
|
+
* The provider configuration built from host settings: the contract's portable
|
|
116
|
+
* fields plus the server adapter's, under the adapter's names.
|
|
117
|
+
*/
|
|
118
|
+
export type RuntimeTTSConfig = Pick<TTSConfig, "voice" | "rate" | "pitch" | "providerOptions" | "mathTokenHighlighting"> & Pick<TTSRuntimeSettings, "apiEndpoint" | "language" | "transportMode" | "endpointMode" | "endpointValidationMode" | "includeAuthOnAssetFetch" | "assetOrigins" | "credentials" | "headers" | "validateEndpoint"> & {
|
|
119
|
+
provider?: TTSRuntimeSettings["serverProvider"];
|
|
120
|
+
};
|
|
121
|
+
export declare const buildRuntimeTTSConfig: (config: TTSRuntimeSettings) => RuntimeTTSConfig;
|
|
104
122
|
export declare const resolveTTSLayoutMode: (config: TTSRuntimeSettings) => TTSLayoutMode;
|
|
105
123
|
export declare const resolveTTSHostToolbarLayout: (config: TTSRuntimeSettings) => TTSHostToolbarLayout;
|
|
@@ -236,9 +236,12 @@ const applyRuntimeDefaults = (config) => {
|
|
|
236
236
|
export const resolveTTSRuntimeSettings = (config) => {
|
|
237
237
|
const configRecord = toRecord(config);
|
|
238
238
|
const settingsRecord = toRecord(configRecord.settings);
|
|
239
|
+
const { provider, ...merged } = { ...configRecord, ...settingsRecord };
|
|
240
|
+
// A runtime provider object in `provider` is for the tool registration; the
|
|
241
|
+
// runtime settings carry only a server provider id.
|
|
239
242
|
return applyRuntimeDefaults({
|
|
240
|
-
...
|
|
241
|
-
...
|
|
243
|
+
...merged,
|
|
244
|
+
...(typeof provider === "string" ? { provider } : {}),
|
|
242
245
|
});
|
|
243
246
|
};
|
|
244
247
|
export const resolveTTSBackend = (config) => config.backend || "browser";
|
|
@@ -256,11 +259,12 @@ export const buildRuntimeTTSConfig = (config) => {
|
|
|
256
259
|
const runtimeProvider = resolveRuntimeProvider(config, backend);
|
|
257
260
|
const transportMode = resolveTransportMode(config, runtimeProvider);
|
|
258
261
|
const mathSpeech = normalizeSREMathSpeechOptions(config.mathSpeech);
|
|
259
|
-
|
|
262
|
+
const runtimeConfig = {
|
|
260
263
|
voice: config.defaultVoice,
|
|
261
264
|
rate: config.rate,
|
|
262
265
|
pitch: config.pitch,
|
|
263
266
|
providerOptions: {
|
|
267
|
+
...toRecord(config.providerOptions),
|
|
264
268
|
...(config.language ? { locale: config.language } : {}),
|
|
265
269
|
...(backend === "polly" && config.engine
|
|
266
270
|
? { engine: config.engine }
|
|
@@ -296,6 +300,9 @@ export const buildRuntimeTTSConfig = (config) => {
|
|
|
296
300
|
endpointMode: config.endpointMode,
|
|
297
301
|
endpointValidationMode: config.endpointValidationMode,
|
|
298
302
|
includeAuthOnAssetFetch: config.includeAuthOnAssetFetch,
|
|
303
|
+
assetOrigins: config.assetOrigins,
|
|
304
|
+
credentials: config.credentials,
|
|
305
|
+
headers: config.headers,
|
|
299
306
|
validateEndpoint: config.validateEndpoint,
|
|
300
307
|
// Toolkit-level highlight setting carried through the config channel
|
|
301
308
|
// (like apiEndpoint/transportMode); consumed by the highlight pipeline,
|
|
@@ -305,6 +312,7 @@ export const buildRuntimeTTSConfig = (config) => {
|
|
|
305
312
|
? { mathTokenHighlighting: config.mathTokenHighlighting }
|
|
306
313
|
: {}),
|
|
307
314
|
};
|
|
315
|
+
return runtimeConfig;
|
|
308
316
|
};
|
|
309
317
|
export const resolveTTSLayoutMode = (config) => normalizeTTSLayoutMode(config.layoutMode);
|
|
310
318
|
export const resolveTTSHostToolbarLayout = (config) => {
|
package/dist/tools/client.d.ts
CHANGED
|
@@ -2,11 +2,9 @@
|
|
|
2
2
|
* Client-only tool system exports
|
|
3
3
|
*
|
|
4
4
|
* This entry point exports only browser-safe code for use in custom elements.
|
|
5
|
-
* It excludes server-side services like accommodationResolver, variantResolver, etc.
|
|
6
5
|
*
|
|
7
6
|
* Tools should import from '@pie-players/pie-assessment-toolkit/tools/client' instead of
|
|
8
7
|
* '@pie-players/pie-assessment-toolkit' to ensure
|
|
9
8
|
* they don't accidentally pull in server-side dependencies.
|
|
10
9
|
*/
|
|
11
|
-
export {
|
|
12
|
-
export * from "./types.js";
|
|
10
|
+
export type { CalculationHistoryEntry, Calculator, CalculatorProvider, CalculatorProviderCapabilities, CalculatorProviderConfig, CalculatorState, CalculatorType, } from "@pie-players/pie-calculator";
|
package/dist/tools/client.js
CHANGED
|
@@ -2,13 +2,9 @@
|
|
|
2
2
|
* Client-only tool system exports
|
|
3
3
|
*
|
|
4
4
|
* This entry point exports only browser-safe code for use in custom elements.
|
|
5
|
-
* It excludes server-side services like accommodationResolver, variantResolver, etc.
|
|
6
5
|
*
|
|
7
6
|
* Tools should import from '@pie-players/pie-assessment-toolkit/tools/client' instead of
|
|
8
7
|
* '@pie-players/pie-assessment-toolkit' to ensure
|
|
9
8
|
* they don't accidentally pull in server-side dependencies.
|
|
10
9
|
*/
|
|
11
|
-
|
|
12
|
-
export { ResponseDiscoveryServiceImpl, responseDiscovery, } from "./response-discovery.js";
|
|
13
|
-
// Core types (client-safe)
|
|
14
|
-
export * from "./types.js";
|
|
10
|
+
export {};
|
package/dist/tools/internal.d.ts
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* What a package outside this one needs to write a `ToolRegistration`: the
|
|
5
5
|
* registration types, the context predicates a tool answers `isVisibleInContext`
|
|
6
6
|
* with, scoped-id and element-creation helpers, the toolbar button/overlay
|
|
7
|
-
* helpers,
|
|
8
|
-
* provider.
|
|
7
|
+
* helpers, the provider contract a registration's descriptor creates, and the
|
|
8
|
+
* TTS provider.
|
|
9
9
|
*
|
|
10
10
|
* A separate entry point rather than additions to `.` for the same reason
|
|
11
11
|
* `runtime/internal` and `policy/internal` exist: this is a surface for sibling
|
|
@@ -19,7 +19,7 @@
|
|
|
19
19
|
* point — the mechanism is the same one our own registrations use.
|
|
20
20
|
*/
|
|
21
21
|
export type { HostedToolContext, HostedToolSize, ResolvedToolContext, ToolActivation, ToolContentDependency, ToolContentDependencyContext, ToolModuleLoader, ToolProviderDescriptor, ToolRegistration, ToolRenderElement, ToolSingletonScope, ToolSurfaceRenderContext, ToolSurfaceRenderResult, ToolSurfaceServices, ToolToolbarButtonDefinition, ToolToolbarRenderResult, ToolWindowShellConfig, ToolbarContext, } from "../services/ToolRegistry.js";
|
|
22
|
-
export { ToolRegistry } from "../services/ToolRegistry.js";
|
|
22
|
+
export { resolveToolProviderId, ToolRegistry, } from "../services/ToolRegistry.js";
|
|
23
23
|
export { resolveToolRegistrationName } from "../services/ToolRegistry.js";
|
|
24
24
|
export type { CatalogOwnerCard, CatalogOwnerSnapshot, } from "../services/AccessibilityCatalogResolver.js";
|
|
25
25
|
export type { ToolSelectionAction, ToolSelectionContext, } from "../services/selection-action.js";
|
|
@@ -36,8 +36,9 @@ export type { ToolComponentFactory, ToolComponentFactoryMap, ToolComponentOverri
|
|
|
36
36
|
export { createToolElement, resolveToolTag, toToolIdFromTag, } from "./tool-tag-map.js";
|
|
37
37
|
export { applyOverlaySurface, createScopedVisibilityBinding, syncButtonAndOverlayVisibility, } from "./registrations/toolbar-registration-helpers.js";
|
|
38
38
|
export type { ElementToolStateStoreApi, ToolCoordinatorApi, ToolkitCoordinatorApi, TtsServiceApi, } from "../services/interfaces.js";
|
|
39
|
-
export type { ToolPlacementConfig, ToolProviderConfig, } from "../services/tools-config-normalizer.js";
|
|
39
|
+
export type { CalculatorToolProviderConfig, ToolPlacementConfig, ToolProviderConfig, } from "../services/tools-config-normalizer.js";
|
|
40
40
|
export type { ToolConfigDiagnostic } from "../services/tool-config-validation.js";
|
|
41
|
-
export {
|
|
41
|
+
export type { ToolProviderApi, ToolProviderCapabilities, } from "../services/tool-providers/ToolProviderApi.js";
|
|
42
|
+
export { TTSToolProvider } from "../services/tool-providers/index.js";
|
|
42
43
|
export type { NormalizedTTSSpeedOption } from "../services/tts-runtime-config.js";
|
|
43
44
|
export { buildRuntimeTTSConfig, normalizeTTSLayoutMode, normalizeTTSSpeedControlOptions, resolveRuntimeProvider, resolveTTSBackend, resolveTTSHostToolbarLayout, resolveTTSLayoutMode, resolveTTSRuntimeSettings, resolveTransportMode, } from "../services/tts-runtime-config.js";
|
package/dist/tools/internal.js
CHANGED
|
@@ -4,8 +4,8 @@
|
|
|
4
4
|
* What a package outside this one needs to write a `ToolRegistration`: the
|
|
5
5
|
* registration types, the context predicates a tool answers `isVisibleInContext`
|
|
6
6
|
* with, scoped-id and element-creation helpers, the toolbar button/overlay
|
|
7
|
-
* helpers,
|
|
8
|
-
* provider.
|
|
7
|
+
* helpers, the provider contract a registration's descriptor creates, and the
|
|
8
|
+
* TTS provider.
|
|
9
9
|
*
|
|
10
10
|
* A separate entry point rather than additions to `.` for the same reason
|
|
11
11
|
* `runtime/internal` and `policy/internal` exist: this is a surface for sibling
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
* A host writing its own capability package imports from here too, which is the
|
|
19
19
|
* point — the mechanism is the same one our own registrations use.
|
|
20
20
|
*/
|
|
21
|
-
export { ToolRegistry } from "../services/ToolRegistry.js";
|
|
21
|
+
export { resolveToolProviderId, ToolRegistry, } from "../services/ToolRegistry.js";
|
|
22
22
|
// A registration's own display name in the interface locale. A tool window's
|
|
23
23
|
// title is the registration's name, so the shell needs the same `nameKey`-then-
|
|
24
24
|
// `name` precedence the toolbar uses rather than the raw English field.
|
|
@@ -33,9 +33,7 @@ export { createScopedToolId } from "../services/tool-instance-id.js";
|
|
|
33
33
|
export { createToolElement, resolveToolTag, toToolIdFromTag, } from "./tool-tag-map.js";
|
|
34
34
|
// Toolbar button/overlay wiring shared by every toolbar-toggle registration.
|
|
35
35
|
export { applyOverlaySurface, createScopedVisibilityBinding, syncButtonAndOverlayVisibility, } from "./registrations/toolbar-registration-helpers.js";
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
|
|
39
|
-
// toolkit's own `TTSService` and provider registry also depend on.
|
|
40
|
-
export { CortexToolProvider, DesmosToolProvider, GeoGebraToolProvider, TTSToolProvider, } from "../services/tool-providers/index.js";
|
|
36
|
+
// The TTS provider stays here because it is written against the `pie-tts`
|
|
37
|
+
// contract package, which the toolkit's own `TTSService` also depends on.
|
|
38
|
+
export { TTSToolProvider } from "../services/tool-providers/index.js";
|
|
41
39
|
export { buildRuntimeTTSConfig, normalizeTTSLayoutMode, normalizeTTSSpeedControlOptions, resolveRuntimeProvider, resolveTTSBackend, resolveTTSHostToolbarLayout, resolveTTSLayoutMode, resolveTTSRuntimeSettings, resolveTransportMode, } from "../services/tts-runtime-config.js";
|