@pie-players/pie-assessment-toolkit 0.2.7 → 0.2.10

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.
Files changed (249) hide show
  1. package/README.md +200 -67
  2. package/dist/attempt/TestSession.d.ts +23 -21
  3. package/dist/attempt/TestSession.d.ts.map +1 -1
  4. package/dist/attempt/TestSession.js +17 -15
  5. package/dist/attempt/TestSession.js.map +1 -1
  6. package/dist/attempt/adapters/activity-to-test-attempt-session.d.ts +50 -0
  7. package/dist/attempt/adapters/activity-to-test-attempt-session.d.ts.map +1 -0
  8. package/dist/attempt/adapters/activity-to-test-attempt-session.js +135 -0
  9. package/dist/attempt/adapters/activity-to-test-attempt-session.js.map +1 -0
  10. package/dist/components/ItemToolBar.custom-element.js +953 -0
  11. package/dist/components/PieAssessmentToolkit.custom-element.js +757 -0
  12. package/dist/components/SectionToolBar.custom-element.js +162 -0
  13. package/dist/components/item-toolbar-element.d.ts +3 -0
  14. package/dist/components/item-toolbar-element.d.ts.map +1 -0
  15. package/dist/components/item-toolbar-element.js +2 -0
  16. package/dist/components/item-toolbar-element.js.map +1 -0
  17. package/dist/components/pie-assessment-toolkit-element.d.ts +3 -0
  18. package/dist/components/pie-assessment-toolkit-element.d.ts.map +1 -0
  19. package/dist/components/pie-assessment-toolkit-element.js +2 -0
  20. package/dist/components/pie-assessment-toolkit-element.js.map +1 -0
  21. package/dist/components/section-toolbar-element.d.ts +3 -0
  22. package/dist/components/section-toolbar-element.d.ts.map +1 -0
  23. package/dist/components/section-toolbar-element.js +2 -0
  24. package/dist/components/section-toolbar-element.js.map +1 -0
  25. package/dist/context/assessment-toolkit-context.d.ts +52 -0
  26. package/dist/context/assessment-toolkit-context.d.ts.map +1 -0
  27. package/dist/context/assessment-toolkit-context.js +6 -0
  28. package/dist/context/assessment-toolkit-context.js.map +1 -0
  29. package/dist/context/runtime-context-consumer.d.ts +14 -0
  30. package/dist/context/runtime-context-consumer.d.ts.map +1 -0
  31. package/dist/context/runtime-context-consumer.js +52 -0
  32. package/dist/context/runtime-context-consumer.js.map +1 -0
  33. package/dist/index.d.ts +19 -6
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +14 -11
  36. package/dist/index.js.map +1 -1
  37. package/dist/runtime/RuntimeRegistry.d.ts +13 -0
  38. package/dist/runtime/RuntimeRegistry.d.ts.map +1 -0
  39. package/dist/runtime/RuntimeRegistry.js +50 -0
  40. package/dist/runtime/RuntimeRegistry.js.map +1 -0
  41. package/dist/runtime/SectionRuntimeEngine.d.ts +45 -0
  42. package/dist/runtime/SectionRuntimeEngine.d.ts.map +1 -0
  43. package/dist/runtime/SectionRuntimeEngine.js +81 -0
  44. package/dist/runtime/SectionRuntimeEngine.js.map +1 -0
  45. package/dist/runtime/registration-events.d.ts +19 -0
  46. package/dist/runtime/registration-events.d.ts.map +1 -0
  47. package/dist/runtime/registration-events.js +4 -0
  48. package/dist/runtime/registration-events.js.map +1 -0
  49. package/dist/runtime/runtime-event-guards.d.ts +3 -0
  50. package/dist/runtime/runtime-event-guards.d.ts.map +1 -0
  51. package/dist/runtime/runtime-event-guards.js +9 -0
  52. package/dist/runtime/runtime-event-guards.js.map +1 -0
  53. package/dist/runtime/tool-host-contract.d.ts +30 -0
  54. package/dist/runtime/tool-host-contract.d.ts.map +1 -0
  55. package/dist/runtime/tool-host-contract.js +48 -0
  56. package/dist/runtime/tool-host-contract.js.map +1 -0
  57. package/dist/services/HighlightCoordinator.d.ts +9 -0
  58. package/dist/services/HighlightCoordinator.d.ts.map +1 -1
  59. package/dist/services/HighlightCoordinator.js +196 -55
  60. package/dist/services/HighlightCoordinator.js.map +1 -1
  61. package/dist/services/TTSService.d.ts +21 -1
  62. package/dist/services/TTSService.d.ts.map +1 -1
  63. package/dist/services/TTSService.js +356 -117
  64. package/dist/services/TTSService.js.map +1 -1
  65. package/dist/services/ThemeProvider.d.ts +1 -0
  66. package/dist/services/ThemeProvider.d.ts.map +1 -1
  67. package/dist/services/ThemeProvider.js +82 -46
  68. package/dist/services/ThemeProvider.js.map +1 -1
  69. package/dist/services/ToolConfigResolver.d.ts +1 -1
  70. package/dist/services/ToolConfigResolver.js +1 -1
  71. package/dist/services/ToolCoordinator.d.ts +1 -1
  72. package/dist/services/ToolCoordinator.d.ts.map +1 -1
  73. package/dist/services/ToolRegistry.d.ts +76 -67
  74. package/dist/services/ToolRegistry.d.ts.map +1 -1
  75. package/dist/services/ToolRegistry.js +73 -22
  76. package/dist/services/ToolRegistry.js.map +1 -1
  77. package/dist/services/ToolkitCoordinator.d.ts +126 -8
  78. package/dist/services/ToolkitCoordinator.d.ts.map +1 -1
  79. package/dist/services/ToolkitCoordinator.js +607 -72
  80. package/dist/services/ToolkitCoordinator.js.map +1 -1
  81. package/dist/services/createDefaultToolRegistry.d.ts +11 -12
  82. package/dist/services/createDefaultToolRegistry.d.ts.map +1 -1
  83. package/dist/services/createDefaultToolRegistry.js +9 -56
  84. package/dist/services/createDefaultToolRegistry.js.map +1 -1
  85. package/dist/services/defaultPersonalNeedsProfile.d.ts +4 -0
  86. package/dist/services/defaultPersonalNeedsProfile.d.ts.map +1 -0
  87. package/dist/services/defaultPersonalNeedsProfile.js +25 -0
  88. package/dist/services/defaultPersonalNeedsProfile.js.map +1 -0
  89. package/dist/services/interfaces.d.ts +62 -2
  90. package/dist/services/interfaces.d.ts.map +1 -1
  91. package/dist/services/interfaces.js.map +1 -1
  92. package/dist/services/pnp-standard-features.d.ts +3 -4
  93. package/dist/services/pnp-standard-features.d.ts.map +1 -1
  94. package/dist/services/pnp-standard-features.js +0 -3
  95. package/dist/services/pnp-standard-features.js.map +1 -1
  96. package/dist/services/section-controller-types.d.ts +37 -0
  97. package/dist/services/section-controller-types.d.ts.map +1 -0
  98. package/dist/services/section-controller-types.js +2 -0
  99. package/dist/services/section-controller-types.js.map +1 -0
  100. package/dist/services/tool-config-defaults.d.ts +14 -0
  101. package/dist/services/tool-config-defaults.d.ts.map +1 -0
  102. package/dist/services/tool-config-defaults.js +23 -0
  103. package/dist/services/tool-config-defaults.js.map +1 -0
  104. package/dist/services/tool-context.d.ts +4 -4
  105. package/dist/services/tool-context.d.ts.map +1 -1
  106. package/dist/services/tool-context.js +156 -20
  107. package/dist/services/tool-context.js.map +1 -1
  108. package/dist/services/tool-instance-id.d.ts +15 -0
  109. package/dist/services/tool-instance-id.d.ts.map +1 -0
  110. package/dist/services/tool-instance-id.js +55 -0
  111. package/dist/services/tool-instance-id.js.map +1 -0
  112. package/dist/services/tool-providers/IToolProvider.d.ts +2 -3
  113. package/dist/services/tool-providers/IToolProvider.d.ts.map +1 -1
  114. package/dist/services/tool-providers/IToolProvider.js +1 -2
  115. package/dist/services/tool-providers/IToolProvider.js.map +1 -1
  116. package/dist/services/tool-providers/MathJsToolProvider.d.ts +25 -0
  117. package/dist/services/tool-providers/MathJsToolProvider.d.ts.map +1 -0
  118. package/dist/services/tool-providers/MathJsToolProvider.js +53 -0
  119. package/dist/services/tool-providers/MathJsToolProvider.js.map +1 -0
  120. package/dist/services/tool-providers/index.d.ts +2 -0
  121. package/dist/services/tool-providers/index.d.ts.map +1 -1
  122. package/dist/services/tool-providers/index.js +1 -0
  123. package/dist/services/tool-providers/index.js.map +1 -1
  124. package/dist/services/toolbar-items.d.ts +26 -0
  125. package/dist/services/toolbar-items.d.ts.map +1 -0
  126. package/dist/services/toolbar-items.js +10 -0
  127. package/dist/services/toolbar-items.js.map +1 -0
  128. package/dist/services/tools-config-normalizer.d.ts +26 -0
  129. package/dist/services/tools-config-normalizer.d.ts.map +1 -0
  130. package/dist/services/tools-config-normalizer.js +62 -0
  131. package/dist/services/tools-config-normalizer.js.map +1 -0
  132. package/dist/services/tts/browser-provider.d.ts.map +1 -1
  133. package/dist/services/tts/browser-provider.js +201 -34
  134. package/dist/services/tts/browser-provider.js.map +1 -1
  135. package/dist/services/tts/text-processing.d.ts +17 -0
  136. package/dist/services/tts/text-processing.d.ts.map +1 -0
  137. package/dist/services/tts/text-processing.js +144 -0
  138. package/dist/services/tts/text-processing.js.map +1 -0
  139. package/dist/tools/calculators/ti-provider.d.ts.map +1 -1
  140. package/dist/tools/calculators/ti-provider.js +127 -4
  141. package/dist/tools/calculators/ti-provider.js.map +1 -1
  142. package/dist/tools/client.d.ts +2 -1
  143. package/dist/tools/client.d.ts.map +1 -1
  144. package/dist/tools/client.js +2 -1
  145. package/dist/tools/client.js.map +1 -1
  146. package/dist/tools/default-tool-module-loaders.d.ts +9 -0
  147. package/dist/tools/default-tool-module-loaders.d.ts.map +1 -0
  148. package/dist/tools/default-tool-module-loaders.js +11 -0
  149. package/dist/tools/default-tool-module-loaders.js.map +1 -0
  150. package/dist/tools/index.d.ts +2 -1
  151. package/dist/tools/index.d.ts.map +1 -1
  152. package/dist/tools/index.js +2 -1
  153. package/dist/tools/index.js.map +1 -1
  154. package/dist/tools/library-loader.d.ts +1 -1
  155. package/dist/tools/library-loader.d.ts.map +1 -1
  156. package/dist/tools/library-loader.js +7 -2
  157. package/dist/tools/library-loader.js.map +1 -1
  158. package/dist/tools/registrations/accessibility-tools.d.ts +8 -11
  159. package/dist/tools/registrations/accessibility-tools.d.ts.map +1 -1
  160. package/dist/tools/registrations/accessibility-tools.js +108 -120
  161. package/dist/tools/registrations/accessibility-tools.js.map +1 -1
  162. package/dist/tools/registrations/calculator.d.ts +2 -2
  163. package/dist/tools/registrations/calculator.d.ts.map +1 -1
  164. package/dist/tools/registrations/calculator.js +42 -55
  165. package/dist/tools/registrations/calculator.js.map +1 -1
  166. package/dist/tools/registrations/interaction-tools.d.ts.map +1 -1
  167. package/dist/tools/registrations/interaction-tools.js +77 -52
  168. package/dist/tools/registrations/interaction-tools.js.map +1 -1
  169. package/dist/tools/registrations/measurement-tools.d.ts.map +1 -1
  170. package/dist/tools/registrations/measurement-tools.js +63 -38
  171. package/dist/tools/registrations/measurement-tools.js.map +1 -1
  172. package/dist/tools/registrations/subject-specific-tools.d.ts.map +1 -1
  173. package/dist/tools/registrations/subject-specific-tools.js +63 -38
  174. package/dist/tools/registrations/subject-specific-tools.js.map +1 -1
  175. package/dist/tools/registrations/tts.d.ts +1 -1
  176. package/dist/tools/registrations/tts.d.ts.map +1 -1
  177. package/dist/tools/registrations/tts.js +171 -41
  178. package/dist/tools/registrations/tts.js.map +1 -1
  179. package/dist/tools/response-discovery.d.ts +12 -14
  180. package/dist/tools/response-discovery.d.ts.map +1 -1
  181. package/dist/tools/response-discovery.js +23 -80
  182. package/dist/tools/response-discovery.js.map +1 -1
  183. package/dist/tools/tool-tag-map.d.ts +3 -3
  184. package/dist/tools/tool-tag-map.d.ts.map +1 -1
  185. package/dist/tools/tool-tag-map.js +4 -4
  186. package/dist/tools/tool-tag-map.js.map +1 -1
  187. package/dist/tools/types.d.ts +3 -1
  188. package/dist/tools/types.d.ts.map +1 -1
  189. package/package.json +28 -27
  190. package/src/README.md +16 -32
  191. package/src/components/ItemToolBar.svelte +701 -0
  192. package/src/components/PieAssessmentToolkit.svelte +610 -0
  193. package/src/components/SectionToolBar.svelte +58 -0
  194. package/src/components/ToolButton.svelte +11 -11
  195. package/src/components/ToolButtonGroup.svelte +27 -11
  196. package/src/tools/README.md +6 -5
  197. package/src/tools/calculators/README.md +4 -4
  198. package/dist/player/AssessmentPlayer.d.ts +0 -397
  199. package/dist/player/AssessmentPlayer.d.ts.map +0 -1
  200. package/dist/player/AssessmentPlayer.js +0 -974
  201. package/dist/player/AssessmentPlayer.js.map +0 -1
  202. package/dist/player/index.d.ts +0 -17
  203. package/dist/player/index.d.ts.map +0 -1
  204. package/dist/player/index.js +0 -15
  205. package/dist/player/index.js.map +0 -1
  206. package/dist/player/navigation-types.d.ts +0 -63
  207. package/dist/player/navigation-types.d.ts.map +0 -1
  208. package/dist/player/navigation-types.js +0 -7
  209. package/dist/player/navigation-types.js.map +0 -1
  210. package/dist/player/qti-navigation.d.ts +0 -29
  211. package/dist/player/qti-navigation.d.ts.map +0 -1
  212. package/dist/player/qti-navigation.js +0 -160
  213. package/dist/player/qti-navigation.js.map +0 -1
  214. package/dist/reference-layout/index.d.ts +0 -19
  215. package/dist/reference-layout/index.d.ts.map +0 -1
  216. package/dist/reference-layout/index.js +0 -20
  217. package/dist/reference-layout/index.js.map +0 -1
  218. package/dist/services/AnnotationToolbarConfig.d.ts +0 -134
  219. package/dist/services/AnnotationToolbarConfig.d.ts.map +0 -1
  220. package/dist/services/AnnotationToolbarConfig.js +0 -100
  221. package/dist/services/AnnotationToolbarConfig.js.map +0 -1
  222. package/dist/services/AssessmentAuthoringService.d.ts +0 -60
  223. package/dist/services/AssessmentAuthoringService.d.ts.map +0 -1
  224. package/dist/services/AssessmentAuthoringService.js +0 -183
  225. package/dist/services/AssessmentAuthoringService.js.map +0 -1
  226. package/dist/services/PNPMapper.d.ts +0 -81
  227. package/dist/services/PNPMapper.d.ts.map +0 -1
  228. package/dist/services/PNPMapper.js +0 -108
  229. package/dist/services/PNPMapper.js.map +0 -1
  230. package/dist/services/tts/provider-interface.d.ts +0 -131
  231. package/dist/services/tts/provider-interface.d.ts.map +0 -1
  232. package/dist/services/tts/provider-interface.js +0 -10
  233. package/dist/services/tts/provider-interface.js.map +0 -1
  234. package/src/components/PNPProfileTester.example.svelte +0 -188
  235. package/src/components/PNPProfileTester.svelte +0 -397
  236. package/src/components/PNPProvenanceViewer.svelte +0 -260
  237. package/src/components/QuestionToolBar.svelte +0 -483
  238. package/src/player/AssessmentLayout.svelte +0 -68
  239. package/src/player/README.md +0 -154
  240. package/src/reference-layout/README.md +0 -135
  241. package/src/reference-layout/ReferenceLayout.svelte +0 -201
  242. package/src/reference-layout/components/AssessmentContent.svelte +0 -259
  243. package/src/reference-layout/components/AssessmentFooter.svelte +0 -89
  244. package/src/reference-layout/components/AssessmentHeader.svelte +0 -250
  245. package/src/reference-layout/components/AssessmentNavigation.svelte +0 -134
  246. package/src/reference-layout/components/AssessmentToolsBar.svelte +0 -176
  247. package/src/reference-layout/components/ItemPanel.svelte +0 -200
  248. package/src/reference-layout/components/NotesPanel.svelte +0 -179
  249. package/src/reference-layout/components/PassagePanel.svelte +0 -76
@@ -13,13 +13,14 @@
13
13
  *
14
14
  * Part of PIE Assessment Toolkit.
15
15
  */
16
+ import { normalizeToolsConfig, resolveToolsForLevel, } from "./tools-config-normalizer.js";
16
17
  import { AccessibilityCatalogResolver } from "./AccessibilityCatalogResolver.js";
17
18
  import { ElementToolStateStore } from "./ElementToolStateStore.js";
18
19
  import { HighlightCoordinator } from "./HighlightCoordinator.js";
19
20
  import { ToolCoordinator } from "./ToolCoordinator.js";
20
21
  import { TTSService } from "./TTSService.js";
21
22
  import { BrowserTTSProvider } from "./tts/browser-provider.js";
22
- import { ToolProviderRegistry, DesmosToolProvider, TIToolProvider, TTSToolProvider, } from "./tool-providers/index.js";
23
+ import { ToolProviderRegistry, DesmosToolProvider, MathJsToolProvider, TIToolProvider, TTSToolProvider, } from "./tool-providers/index.js";
23
24
  /**
24
25
  * ToolkitCoordinator - Orchestrates all assessment toolkit services
25
26
  *
@@ -54,106 +55,535 @@ export class ToolkitCoordinator {
54
55
  elementToolStateStore;
55
56
  catalogResolver;
56
57
  toolProviderRegistry;
58
+ hooks;
59
+ lazyInit;
57
60
  /** Track TTS initialization state */
58
61
  ttsInitialized = false;
62
+ ttsInitPromise;
63
+ stateLoaded = false;
64
+ stateLoadPromise;
65
+ coordinatorReadyPromise;
66
+ coordinatorReadyNotified = false;
67
+ providerInitPromises = new Map();
68
+ sectionControllers = new Map();
69
+ sectionControllerInitPromises = new Map();
70
+ sectionPersistenceStrategies = new Map();
71
+ sectionControllerLifecycleListeners = new Set();
59
72
  /** Callback for floating tools changes */
60
73
  floatingToolsChangeCallback = null;
74
+ static resolveConfig(config) {
75
+ const normalized = normalizeToolsConfig(config.tools);
76
+ const defaultProviders = {
77
+ tts: {
78
+ enabled: true,
79
+ backend: "browser",
80
+ },
81
+ calculator: {
82
+ enabled: true,
83
+ provider: "desmos",
84
+ },
85
+ };
86
+ return {
87
+ ...config,
88
+ tools: {
89
+ ...normalized,
90
+ providers: {
91
+ ...defaultProviders,
92
+ ...normalized.providers,
93
+ },
94
+ },
95
+ accessibility: {
96
+ language: "en-US",
97
+ ...(config.accessibility ?? {}),
98
+ catalogs: config.accessibility?.catalogs ?? [],
99
+ },
100
+ };
101
+ }
61
102
  constructor(config) {
62
103
  if (!config.assessmentId) {
63
104
  throw new Error("ToolkitCoordinator requires assessmentId in config");
64
105
  }
65
- this.assessmentId = config.assessmentId;
66
- this.config = config;
106
+ const resolvedConfig = ToolkitCoordinator.resolveConfig(config);
107
+ this.assessmentId = resolvedConfig.assessmentId;
108
+ this.config = resolvedConfig;
109
+ this.hooks = resolvedConfig.hooks ?? {};
110
+ this.lazyInit = config.lazyInit === true;
67
111
  // Initialize all services
68
112
  this.toolCoordinator = new ToolCoordinator();
69
113
  this.highlightCoordinator = new HighlightCoordinator();
70
114
  this.elementToolStateStore = new ElementToolStateStore();
71
- this.catalogResolver = new AccessibilityCatalogResolver(config.accessibility?.catalogs || [], config.accessibility?.language || "en-US");
115
+ this.catalogResolver = new AccessibilityCatalogResolver(resolvedConfig.accessibility?.catalogs || [], resolvedConfig.accessibility?.language || "en-US");
72
116
  // Initialize tool provider registry
73
117
  this.toolProviderRegistry = new ToolProviderRegistry();
74
118
  this._registerToolProviders();
75
119
  // Initialize TTS service based on config
76
120
  this.ttsService = new TTSService();
77
- const ttsConfig = config.tools?.tts;
78
- if (ttsConfig?.enabled !== false) {
79
- // Initialize async (fire and forget - service will become available when ready)
80
- this._initializeTTS(ttsConfig).catch((err) => {
81
- console.error("[ToolkitCoordinator] Failed to initialize TTS:", err);
121
+ this.setupStatePersistenceHooks();
122
+ if (!this.lazyInit) {
123
+ void this.waitUntilReady().catch((err) => {
124
+ console.error("[ToolkitCoordinator] Failed eager initialization:", err);
125
+ this.handleError(err, { phase: "coordinator-ready" });
82
126
  });
83
127
  }
84
128
  }
129
+ async emitTelemetry(eventName, payload) {
130
+ try {
131
+ await this.hooks.onTelemetry?.(eventName, payload);
132
+ }
133
+ catch (err) {
134
+ console.warn("[ToolkitCoordinator] telemetry hook failed:", err);
135
+ }
136
+ }
137
+ emitSectionControllerLifecycle(event) {
138
+ for (const listener of this.sectionControllerLifecycleListeners) {
139
+ try {
140
+ listener(event);
141
+ }
142
+ catch (error) {
143
+ console.warn("[ToolkitCoordinator] section controller lifecycle listener failed:", error);
144
+ }
145
+ }
146
+ }
147
+ handleError(error, context) {
148
+ const normalized = error instanceof Error ? error : new Error(String(error));
149
+ try {
150
+ this.hooks.onError?.(normalized, context);
151
+ }
152
+ catch (hookError) {
153
+ console.warn("[ToolkitCoordinator] onError hook failed:", hookError);
154
+ }
155
+ }
156
+ getSectionControllerMapKey(key) {
157
+ return `${key.assessmentId}::${key.sectionId}::${key.attemptId || ""}`;
158
+ }
159
+ createDefaultSectionPersistence() {
160
+ const storage = (() => {
161
+ try {
162
+ if (typeof window === "undefined")
163
+ return null;
164
+ return window.localStorage;
165
+ }
166
+ catch {
167
+ return null;
168
+ }
169
+ })();
170
+ const getStorageKey = (context) => {
171
+ const { assessmentId, sectionId, attemptId } = context.key;
172
+ return `pie:section-controller:v1:${assessmentId}:${sectionId}:${attemptId || "default"}`;
173
+ };
174
+ return {
175
+ async load(context) {
176
+ if (!storage)
177
+ return null;
178
+ const value = storage.getItem(getStorageKey(context));
179
+ if (!value)
180
+ return null;
181
+ try {
182
+ return JSON.parse(value);
183
+ }
184
+ catch {
185
+ return null;
186
+ }
187
+ },
188
+ async save(context, snapshot) {
189
+ if (!storage)
190
+ return;
191
+ storage.setItem(getStorageKey(context), JSON.stringify(snapshot));
192
+ },
193
+ async clear(context) {
194
+ if (!storage)
195
+ return;
196
+ storage.removeItem(getStorageKey(context));
197
+ },
198
+ };
199
+ }
200
+ async resolveSectionPersistence(context) {
201
+ const cacheKey = this.getSectionControllerMapKey(context.key);
202
+ const existing = this.sectionPersistenceStrategies.get(cacheKey);
203
+ if (existing)
204
+ return existing;
205
+ const defaults = {
206
+ createDefaultPersistence: () => this.createDefaultSectionPersistence(),
207
+ };
208
+ const strategy = (await this.hooks.createSectionPersistence?.(context, defaults)) ??
209
+ (await defaults.createDefaultPersistence());
210
+ this.sectionPersistenceStrategies.set(cacheKey, strategy);
211
+ return strategy;
212
+ }
213
+ setupStatePersistenceHooks() {
214
+ this.elementToolStateStore.setOnStateChange((state) => {
215
+ if (!this.hooks.saveToolState)
216
+ return;
217
+ void Promise.resolve(this.hooks.saveToolState(state)).catch((err) => {
218
+ this.handleError(err, { phase: "state-save" });
219
+ });
220
+ });
221
+ }
222
+ async ensureStateLoaded() {
223
+ if (this.stateLoaded)
224
+ return;
225
+ if (this.stateLoadPromise)
226
+ return this.stateLoadPromise;
227
+ this.stateLoadPromise = (async () => {
228
+ const loader = this.hooks.loadToolState;
229
+ if (!loader) {
230
+ return;
231
+ }
232
+ try {
233
+ const state = await loader();
234
+ if (state && typeof state === "object") {
235
+ this.elementToolStateStore.loadState(state);
236
+ }
237
+ this.stateLoaded = true;
238
+ await this.emitTelemetry("tool-state-loaded", {
239
+ hasState: Boolean(state),
240
+ });
241
+ }
242
+ catch (err) {
243
+ this.handleError(err, { phase: "state-load" });
244
+ }
245
+ })().finally(() => {
246
+ this.stateLoadPromise = undefined;
247
+ });
248
+ return this.stateLoadPromise;
249
+ }
85
250
  /**
86
251
  * Register tool providers in the registry
87
252
  */
88
253
  _registerToolProviders() {
89
254
  // Register TTS provider
90
- const ttsConfig = this.config.tools?.tts;
255
+ const ttsConfig = this.config.tools?.providers?.tts;
91
256
  if (ttsConfig?.enabled !== false) {
92
257
  const backend = ttsConfig?.backend || "browser";
93
- try {
94
- this.toolProviderRegistry.register("tts", {
95
- provider: new TTSToolProvider(backend),
96
- config: {
97
- backend,
98
- apiEndpoint: ttsConfig?.apiEndpoint,
99
- voice: ttsConfig?.defaultVoice,
100
- rate: ttsConfig?.rate,
101
- pitch: ttsConfig?.pitch,
102
- },
103
- lazy: true,
104
- authFetcher: ttsConfig?.authFetcher,
105
- });
106
- }
107
- catch (error) {
108
- console.warn("[ToolkitCoordinator] Failed to register TTS provider:", error);
109
- }
258
+ const serverProvider = ttsConfig?.serverProvider ||
259
+ ttsConfig?.provider ||
260
+ (backend === "polly" || backend === "google" ? backend : undefined);
261
+ void this.registerProvider("tts", {
262
+ provider: new TTSToolProvider(backend),
263
+ config: {
264
+ backend,
265
+ apiEndpoint: ttsConfig?.apiEndpoint,
266
+ serverProvider,
267
+ providerOptions: backend === "polly"
268
+ ? {
269
+ ...(ttsConfig?.engine ? { engine: ttsConfig.engine } : {}),
270
+ ...(typeof ttsConfig?.sampleRate === "number"
271
+ ? { sampleRate: ttsConfig.sampleRate }
272
+ : {}),
273
+ ...(ttsConfig?.format ? { format: ttsConfig.format } : {}),
274
+ speechMarkTypes: ttsConfig?.speechMarksMode === "word+sentence"
275
+ ? ["word", "sentence"]
276
+ : ["word"],
277
+ }
278
+ : undefined,
279
+ voice: ttsConfig?.defaultVoice,
280
+ rate: ttsConfig?.rate,
281
+ pitch: ttsConfig?.pitch,
282
+ },
283
+ lazy: true,
284
+ authFetcher: ttsConfig?.authFetcher,
285
+ });
110
286
  }
111
287
  // Register calculator providers
112
- const floatingTools = this.config.tools?.floatingTools;
113
- const calculatorConfig = floatingTools?.calculator;
288
+ const calculatorConfig = this.config.tools?.providers?.calculator;
114
289
  if (calculatorConfig?.enabled !== false) {
115
290
  const provider = calculatorConfig?.provider || "desmos";
116
291
  if (provider === "desmos") {
117
- try {
118
- this.toolProviderRegistry.register("calculator-desmos", {
119
- provider: new DesmosToolProvider(),
120
- config: {},
121
- lazy: true,
122
- authFetcher: calculatorConfig?.authFetcher,
123
- });
124
- }
125
- catch (error) {
126
- console.warn("[ToolkitCoordinator] Failed to register Desmos calculator provider:", error);
127
- }
292
+ void this.registerProvider("calculator-desmos", {
293
+ provider: new DesmosToolProvider(),
294
+ config: {},
295
+ lazy: true,
296
+ authFetcher: calculatorConfig?.authFetcher,
297
+ });
128
298
  }
129
299
  else if (provider === "ti") {
130
- try {
131
- this.toolProviderRegistry.register("calculator-ti", {
132
- provider: new TIToolProvider(),
133
- config: {},
134
- lazy: true,
135
- });
136
- }
137
- catch (error) {
138
- console.warn("[ToolkitCoordinator] Failed to register TI calculator provider:", error);
139
- }
300
+ void this.registerProvider("calculator-ti", {
301
+ provider: new TIToolProvider(),
302
+ config: {},
303
+ lazy: true,
304
+ });
305
+ }
306
+ else if (provider === "mathjs") {
307
+ void this.registerProvider("calculator-mathjs", {
308
+ provider: new MathJsToolProvider(),
309
+ config: {},
310
+ lazy: true,
311
+ });
140
312
  }
141
313
  }
142
314
  }
315
+ async registerProvider(providerId, config) {
316
+ try {
317
+ this.toolProviderRegistry.register(providerId, config);
318
+ const meta = {
319
+ providerId,
320
+ providerName: config.provider.providerName,
321
+ };
322
+ await this.hooks.onProviderRegistered?.(providerId, meta);
323
+ await this.emitTelemetry("provider-registered", {
324
+ providerId,
325
+ providerName: config.provider.providerName,
326
+ });
327
+ }
328
+ catch (err) {
329
+ console.warn(`[ToolkitCoordinator] Failed to register provider "${providerId}":`, err);
330
+ this.handleError(err, { phase: "provider-register", providerId });
331
+ this.hooks.onProviderError?.(providerId, err, {
332
+ phase: "provider-register",
333
+ providerId,
334
+ });
335
+ }
336
+ }
337
+ async ensureProviderReady(providerId) {
338
+ const existing = this.providerInitPromises.get(providerId);
339
+ if (existing)
340
+ return existing;
341
+ const promise = (async () => {
342
+ const provider = await this.toolProviderRegistry.getProvider(providerId, false);
343
+ const meta = {
344
+ providerId,
345
+ providerName: provider.providerName,
346
+ };
347
+ try {
348
+ await this.hooks.onProviderInitStart?.(providerId, meta);
349
+ await this.toolProviderRegistry.initialize(providerId);
350
+ await this.hooks.onProviderReady?.(providerId, meta);
351
+ await this.emitTelemetry("provider-ready", { providerId });
352
+ return provider;
353
+ }
354
+ catch (err) {
355
+ const error = err instanceof Error ? err : new Error(String(err));
356
+ this.hooks.onProviderError?.(providerId, error, {
357
+ phase: "provider-init",
358
+ providerId,
359
+ });
360
+ this.handleError(error, { phase: "provider-init", providerId });
361
+ throw error;
362
+ }
363
+ })().finally(() => {
364
+ this.providerInitPromises.delete(providerId);
365
+ });
366
+ this.providerInitPromises.set(providerId, promise);
367
+ return promise;
368
+ }
369
+ setHooks(hooks) {
370
+ Object.assign(this.hooks, hooks);
371
+ this.setupStatePersistenceHooks();
372
+ if (hooks.onCoordinatorReady && this.isReady()) {
373
+ void Promise.resolve(hooks.onCoordinatorReady(this)).catch((err) => {
374
+ this.handleError(err, { phase: "coordinator-ready" });
375
+ });
376
+ }
377
+ }
378
+ getSectionController(args) {
379
+ const key = {
380
+ assessmentId: this.assessmentId,
381
+ sectionId: args.sectionId,
382
+ attemptId: args.attemptId,
383
+ };
384
+ return this.sectionControllers.get(this.getSectionControllerMapKey(key));
385
+ }
386
+ onSectionControllerLifecycle(listener) {
387
+ this.sectionControllerLifecycleListeners.add(listener);
388
+ return () => {
389
+ this.sectionControllerLifecycleListeners.delete(listener);
390
+ };
391
+ }
392
+ async getOrCreateSectionController(args) {
393
+ const key = {
394
+ assessmentId: this.assessmentId,
395
+ sectionId: args.sectionId,
396
+ attemptId: args.attemptId,
397
+ };
398
+ const mapKey = this.getSectionControllerMapKey(key);
399
+ const existingController = this.sectionControllers.get(mapKey);
400
+ if (existingController) {
401
+ if (args.updateExisting !== false) {
402
+ await existingController.updateInput?.(args.input);
403
+ }
404
+ return existingController;
405
+ }
406
+ const existingPromise = this.sectionControllerInitPromises.get(mapKey);
407
+ if (existingPromise)
408
+ return existingPromise;
409
+ const initPromise = (async () => {
410
+ const context = {
411
+ key,
412
+ coordinator: this,
413
+ input: args.input,
414
+ };
415
+ const persistence = await this.resolveSectionPersistence(context);
416
+ const defaults = {
417
+ createDefaultController: args.createDefaultController,
418
+ };
419
+ const controller = (await this.hooks.createSectionController?.(context, defaults)) ??
420
+ (await defaults.createDefaultController());
421
+ await controller.setPersistenceStrategy?.(persistence);
422
+ await controller.setPersistenceContext?.(context);
423
+ await controller.initialize?.(args.input);
424
+ await controller.hydrate?.();
425
+ this.sectionControllers.set(mapKey, controller);
426
+ this.emitSectionControllerLifecycle({
427
+ type: "ready",
428
+ key,
429
+ controller,
430
+ });
431
+ await this.hooks.onSectionControllerReady?.(context, controller);
432
+ await this.emitTelemetry("section-controller-ready", {
433
+ assessmentId: key.assessmentId,
434
+ sectionId: key.sectionId,
435
+ attemptId: key.attemptId,
436
+ });
437
+ return controller;
438
+ })().catch((err) => {
439
+ this.handleError(err, {
440
+ phase: "section-controller-init",
441
+ details: {
442
+ sectionId: args.sectionId,
443
+ attemptId: args.attemptId,
444
+ },
445
+ });
446
+ throw err;
447
+ }).finally(() => {
448
+ this.sectionControllerInitPromises.delete(mapKey);
449
+ });
450
+ this.sectionControllerInitPromises.set(mapKey, initPromise);
451
+ return initPromise;
452
+ }
453
+ async disposeSectionController(args) {
454
+ const key = {
455
+ assessmentId: this.assessmentId,
456
+ sectionId: args.sectionId,
457
+ attemptId: args.attemptId,
458
+ };
459
+ const mapKey = this.getSectionControllerMapKey(key);
460
+ const controller = this.sectionControllers.get(mapKey);
461
+ if (!controller)
462
+ return;
463
+ const context = {
464
+ key,
465
+ coordinator: this,
466
+ };
467
+ try {
468
+ if (args.persistBeforeDispose !== false) {
469
+ await controller.persist?.();
470
+ }
471
+ await controller.dispose?.();
472
+ await this.hooks.onSectionControllerDispose?.(context, controller);
473
+ await this.emitTelemetry("section-controller-disposed", {
474
+ assessmentId: key.assessmentId,
475
+ sectionId: key.sectionId,
476
+ attemptId: key.attemptId,
477
+ });
478
+ }
479
+ catch (err) {
480
+ this.handleError(err, {
481
+ phase: "section-controller-dispose",
482
+ details: {
483
+ sectionId: args.sectionId,
484
+ attemptId: args.attemptId,
485
+ },
486
+ });
487
+ }
488
+ finally {
489
+ this.sectionControllers.delete(mapKey);
490
+ this.emitSectionControllerLifecycle({
491
+ type: "disposed",
492
+ key,
493
+ });
494
+ if (args.clearPersistence) {
495
+ const strategy = this.sectionPersistenceStrategies.get(mapKey);
496
+ await strategy?.clear?.(context);
497
+ }
498
+ this.sectionPersistenceStrategies.delete(mapKey);
499
+ }
500
+ }
143
501
  /**
144
502
  * Initialize TTS service with provider
145
503
  */
504
+ async ensureTTSReady(config) {
505
+ if (this.ttsInitialized)
506
+ return;
507
+ if (this.ttsInitPromise)
508
+ return this.ttsInitPromise;
509
+ this.ttsInitPromise = this._initializeTTS(config).finally(() => {
510
+ this.ttsInitPromise = undefined;
511
+ });
512
+ return this.ttsInitPromise;
513
+ }
146
514
  async _initializeTTS(config) {
147
515
  if (this.ttsInitialized)
148
516
  return;
517
+ await this.hooks.onBeforeTTSInit?.({
518
+ phase: "tts-init",
519
+ details: {
520
+ backend: config?.backend,
521
+ },
522
+ });
523
+ await this.emitTelemetry("tts-init-start", {
524
+ backend: config?.backend ??
525
+ this.config.tools?.providers?.tts
526
+ ?.backend ??
527
+ "browser",
528
+ });
529
+ const resolvedToolConfig = config ||
530
+ (this.config.tools?.providers?.tts || {});
531
+ const resolvedBackend = resolvedToolConfig.backend || "browser";
532
+ const runtimeProvider = resolvedToolConfig.serverProvider ||
533
+ resolvedToolConfig.provider ||
534
+ (resolvedBackend === "polly" || resolvedBackend === "google"
535
+ ? resolvedBackend
536
+ : undefined);
537
+ const runtimeTTSConfig = {
538
+ voice: resolvedToolConfig.defaultVoice,
539
+ rate: resolvedToolConfig.rate,
540
+ pitch: resolvedToolConfig.pitch,
541
+ providerOptions: {
542
+ ...(resolvedToolConfig.language
543
+ ? {
544
+ locale: resolvedToolConfig.language,
545
+ }
546
+ : {}),
547
+ ...(resolvedBackend === "polly" && resolvedToolConfig.engine
548
+ ? {
549
+ engine: resolvedToolConfig.engine,
550
+ }
551
+ : {}),
552
+ ...(resolvedBackend === "polly" &&
553
+ typeof resolvedToolConfig.sampleRate === "number"
554
+ ? {
555
+ sampleRate: resolvedToolConfig.sampleRate,
556
+ }
557
+ : {}),
558
+ ...(resolvedBackend === "polly" && resolvedToolConfig.format
559
+ ? {
560
+ format: resolvedToolConfig.format,
561
+ }
562
+ : {}),
563
+ ...(resolvedBackend === "polly"
564
+ ? {
565
+ speechMarkTypes: resolvedToolConfig.speechMarksMode === "word+sentence"
566
+ ? ["word", "sentence"]
567
+ : ["word"],
568
+ }
569
+ : {}),
570
+ },
571
+ apiEndpoint: resolvedToolConfig.apiEndpoint,
572
+ provider: runtimeProvider,
573
+ language: resolvedToolConfig.language,
574
+ };
149
575
  // Try to use TTS provider from registry if available
150
576
  if (this.toolProviderRegistry.has("tts")) {
151
577
  try {
152
- const ttsProvider = await this.toolProviderRegistry.getProvider("tts");
578
+ const ttsProvider = await this.ensureProviderReady("tts");
153
579
  const providerInstance = await ttsProvider.createInstance();
154
- await this.ttsService.initialize(providerInstance);
580
+ await this.ttsService.initialize(providerInstance, runtimeTTSConfig);
155
581
  this.ttsService.setCatalogResolver(this.catalogResolver);
156
582
  this.ttsInitialized = true;
583
+ await this.hooks.onTTSReady?.();
584
+ await this.emitTelemetry("tts-init-success", {
585
+ provider: "registry",
586
+ });
157
587
  console.log("[ToolkitCoordinator] TTS initialized via ToolProviderRegistry");
158
588
  return;
159
589
  }
@@ -163,14 +593,24 @@ export class ToolkitCoordinator {
163
593
  }
164
594
  // Fallback to browser provider
165
595
  const provider = new BrowserTTSProvider();
166
- await this.ttsService.initialize(provider);
167
- this.ttsService.setCatalogResolver(this.catalogResolver);
168
- // Apply TTS-specific configuration
169
- if (config) {
170
- // Future: Apply voice, rate, pitch settings to provider
171
- // For now, these are hints for UI (voice picker, rate slider)
596
+ try {
597
+ await this.ttsService.initialize(provider, runtimeTTSConfig);
598
+ this.ttsService.setCatalogResolver(this.catalogResolver);
599
+ this.ttsInitialized = true;
600
+ await this.hooks.onTTSReady?.();
601
+ await this.emitTelemetry("tts-init-success", {
602
+ provider: "browser-fallback",
603
+ });
604
+ }
605
+ catch (error) {
606
+ const normalized = error instanceof Error ? error : new Error(String(error));
607
+ this.hooks.onTTSError?.(normalized, { phase: "tts-init" });
608
+ this.handleError(normalized, { phase: "tts-init" });
609
+ await this.emitTelemetry("tts-init-error", {
610
+ message: normalized.message,
611
+ });
612
+ throw normalized;
172
613
  }
173
- this.ttsInitialized = true;
174
614
  }
175
615
  /**
176
616
  * Get all services as a bundle for section player convenience.
@@ -193,7 +633,48 @@ export class ToolkitCoordinator {
193
633
  * @returns Tool provider instance
194
634
  */
195
635
  async getToolProvider(providerId) {
196
- return this.toolProviderRegistry.getProvider(providerId);
636
+ return this.ensureProviderReady(providerId);
637
+ }
638
+ async waitUntilReady() {
639
+ if (this.isReady())
640
+ return;
641
+ if (this.coordinatorReadyPromise)
642
+ return this.coordinatorReadyPromise;
643
+ this.coordinatorReadyPromise = (async () => {
644
+ await this.ensureStateLoaded();
645
+ const ttsConfig = this.config.tools?.providers?.tts;
646
+ if (ttsConfig?.enabled !== false) {
647
+ await this.ensureTTSReady(ttsConfig);
648
+ }
649
+ if (!this.coordinatorReadyNotified) {
650
+ this.coordinatorReadyNotified = true;
651
+ await this.hooks.onCoordinatorReady?.(this);
652
+ await this.emitTelemetry("coordinator-ready", {
653
+ assessmentId: this.assessmentId,
654
+ });
655
+ }
656
+ })().finally(() => {
657
+ this.coordinatorReadyPromise = undefined;
658
+ });
659
+ return this.coordinatorReadyPromise;
660
+ }
661
+ isReady() {
662
+ return this.getInitStatus().coordinator;
663
+ }
664
+ getInitStatus() {
665
+ const providers = {};
666
+ for (const providerId of this.toolProviderRegistry.getProviderIds()) {
667
+ providers[providerId] = this.toolProviderRegistry.isInitialized(providerId);
668
+ }
669
+ return {
670
+ tts: this.ttsInitialized,
671
+ stateLoaded: this.stateLoaded || !this.hooks.loadToolState,
672
+ coordinator: (this.stateLoaded || !this.hooks.loadToolState) &&
673
+ (this.ttsInitialized ||
674
+ this.config.tools?.providers?.tts
675
+ ?.enabled === false),
676
+ providers,
677
+ };
197
678
  }
198
679
  /**
199
680
  * Check if a tool is enabled.
@@ -203,7 +684,7 @@ export class ToolkitCoordinator {
203
684
  * @returns True if tool is enabled
204
685
  */
205
686
  isToolEnabled(toolId) {
206
- const toolConfig = this.config.tools?.[toolId];
687
+ const toolConfig = this.config.tools?.providers?.[toolId];
207
688
  // Enabled by default unless explicitly set to false
208
689
  return toolConfig?.enabled !== false;
209
690
  }
@@ -214,7 +695,7 @@ export class ToolkitCoordinator {
214
695
  * @returns Tool configuration or null if not configured
215
696
  */
216
697
  getToolConfig(toolId) {
217
- return this.config.tools?.[toolId] || null;
698
+ return this.config.tools?.providers?.[toolId] || null;
218
699
  }
219
700
  /**
220
701
  * Update tool configuration.
@@ -227,9 +708,12 @@ export class ToolkitCoordinator {
227
708
  // Update config
228
709
  const current = this.getToolConfig(toolId) || {};
229
710
  if (!this.config.tools) {
230
- this.config.tools = {};
711
+ this.config.tools = normalizeToolsConfig();
712
+ }
713
+ if (!this.config.tools.providers) {
714
+ this.config.tools.providers = {};
231
715
  }
232
- this.config.tools[toolId] = { ...current, ...updates };
716
+ this.config.tools.providers[toolId] = { ...current, ...updates };
233
717
  // Apply configuration changes to services
234
718
  this._applyToolConfigChange(toolId, updates);
235
719
  }
@@ -241,12 +725,12 @@ export class ToolkitCoordinator {
241
725
  */
242
726
  updateFloatingTools(toolIds) {
243
727
  if (!this.config.tools) {
244
- this.config.tools = {};
728
+ this.config.tools = normalizeToolsConfig();
245
729
  }
246
- if (!this.config.tools.floatingTools) {
247
- this.config.tools.floatingTools = {};
730
+ if (!this.config.tools.placement) {
731
+ this.config.tools.placement = normalizeToolsConfig().placement;
248
732
  }
249
- this.config.tools.floatingTools.enabledTools = toolIds;
733
+ this.config.tools.placement.section = [...toolIds];
250
734
  // Notify listener of change
251
735
  if (this.floatingToolsChangeCallback) {
252
736
  this.floatingToolsChangeCallback(toolIds);
@@ -258,7 +742,9 @@ export class ToolkitCoordinator {
258
742
  * @returns Array of enabled tool IDs
259
743
  */
260
744
  getFloatingTools() {
261
- return this.config.tools?.floatingTools?.enabledTools || [];
745
+ if (!this.config.tools)
746
+ return [];
747
+ return resolveToolsForLevel(this.config.tools, "section");
262
748
  }
263
749
  /**
264
750
  * Set a callback to be notified when floating tools change.
@@ -279,12 +765,16 @@ export class ToolkitCoordinator {
279
765
  * Apply tool configuration changes to underlying services.
280
766
  * Called after updateToolConfig().
281
767
  */
282
- _applyToolConfigChange(toolId, updates) {
768
+ _applyToolConfigChange(toolId, _updates) {
283
769
  // Apply configuration changes based on tool
284
770
  switch (toolId) {
285
771
  case "tts":
286
- // Future: Update TTSService with voice/rate/pitch changes
287
- // For now, config is used by UI widgets to show current settings
772
+ void this._reconfigureTTSProvider().then(async () => {
773
+ const ttsConfig = this.config.tools?.providers?.tts;
774
+ if (!this.lazyInit && ttsConfig?.enabled !== false) {
775
+ await this.ensureTTSReady(ttsConfig);
776
+ }
777
+ });
288
778
  break;
289
779
  case "answerEliminator":
290
780
  // Future: Could notify answer eliminator tools of strategy change
@@ -292,5 +782,50 @@ export class ToolkitCoordinator {
292
782
  // Add cases for other tools as needed
293
783
  }
294
784
  }
785
+ async _reconfigureTTSProvider() {
786
+ this.ttsInitialized = false;
787
+ this.ttsInitPromise = undefined;
788
+ try {
789
+ this.ttsService.stop();
790
+ }
791
+ catch {
792
+ // noop: stop best effort
793
+ }
794
+ if (this.toolProviderRegistry.has("tts")) {
795
+ await this.toolProviderRegistry.unregister("tts");
796
+ }
797
+ const ttsConfig = this.config.tools?.providers?.tts;
798
+ if (ttsConfig?.enabled === false)
799
+ return;
800
+ const backend = ttsConfig?.backend || "browser";
801
+ const serverProvider = ttsConfig?.serverProvider ||
802
+ ttsConfig?.provider ||
803
+ (backend === "polly" || backend === "google" ? backend : undefined);
804
+ await this.registerProvider("tts", {
805
+ provider: new TTSToolProvider(backend),
806
+ config: {
807
+ backend,
808
+ apiEndpoint: ttsConfig?.apiEndpoint,
809
+ serverProvider,
810
+ providerOptions: backend === "polly"
811
+ ? {
812
+ ...(ttsConfig?.engine ? { engine: ttsConfig.engine } : {}),
813
+ ...(typeof ttsConfig?.sampleRate === "number"
814
+ ? { sampleRate: ttsConfig.sampleRate }
815
+ : {}),
816
+ ...(ttsConfig?.format ? { format: ttsConfig.format } : {}),
817
+ speechMarkTypes: ttsConfig?.speechMarksMode === "word+sentence"
818
+ ? ["word", "sentence"]
819
+ : ["word"],
820
+ }
821
+ : undefined,
822
+ voice: ttsConfig?.defaultVoice,
823
+ rate: ttsConfig?.rate,
824
+ pitch: ttsConfig?.pitch,
825
+ },
826
+ lazy: true,
827
+ authFetcher: ttsConfig?.authFetcher,
828
+ });
829
+ }
295
830
  }
296
831
  //# sourceMappingURL=ToolkitCoordinator.js.map