@pie-players/pie-assessment-toolkit 0.3.72 → 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 +30 -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
package/README.md
CHANGED
|
@@ -4,6 +4,30 @@
|
|
|
4
4
|
|
|
5
5
|
This is not an opinionated framework or monolithic "player" - it's a toolkit that solves specific problems through centralized service management.
|
|
6
6
|
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install @pie-players/pie-assessment-toolkit @pie-players/pie-default-tool-loaders
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
The examples build their tool registry with `createPackagedToolRegistry()` from
|
|
14
|
+
`@pie-players/pie-default-tool-loaders`, so a host that imports it declares it
|
|
15
|
+
in its own dependencies. The section player depends on it too, but strict
|
|
16
|
+
installers such as pnpm expose only the packages a host declares.
|
|
17
|
+
|
|
18
|
+
Server-backed TTS (`backend: "polly"`, `"google"` or `"server"`) loads
|
|
19
|
+
`@pie-players/tts-client-server`, a dependency of
|
|
20
|
+
`@pie-players/pie-default-tool-loaders` whose TTS registration imports it on
|
|
21
|
+
first use. If it fails to load, TTS initialization reports a `provider-init`
|
|
22
|
+
framework error and falls back to browser speech.
|
|
23
|
+
|
|
24
|
+
A `ToolkitCoordinator` registers tool providers only from its `toolRegistry`.
|
|
25
|
+
Built without one, it adopts the registry of the toolkit it is bound to, such as
|
|
26
|
+
the section player's, which then validates its config and registers its
|
|
27
|
+
providers. A registry passed at construction is never replaced. Bound to a
|
|
28
|
+
toolkit that has none, it registers no providers, skips tool-id and placement
|
|
29
|
+
validation, and warns once (`tools.registryUnavailable`).
|
|
30
|
+
|
|
7
31
|
## What's New: ToolkitCoordinator
|
|
8
32
|
|
|
9
33
|
✨ **Centralized Service Management**: The new `ToolkitCoordinator` provides a single entry point for all toolkit services, simplifying initialization and configuration.
|
|
@@ -28,16 +52,21 @@ player.toolCoordinator = toolCoordinator;
|
|
|
28
52
|
|
|
29
53
|
**After** (coordinator orchestrates):
|
|
30
54
|
```typescript
|
|
55
|
+
import { createPackagedToolRegistry } from '@pie-players/pie-default-tool-loaders';
|
|
56
|
+
|
|
31
57
|
// Create one coordinator with configuration
|
|
58
|
+
const toolRegistry = createPackagedToolRegistry();
|
|
32
59
|
const toolkitCoordinator = new ToolkitCoordinator({
|
|
33
60
|
assessmentId: 'my-assessment',
|
|
61
|
+
toolRegistry,
|
|
34
62
|
tools: {
|
|
35
63
|
providers: {
|
|
36
64
|
textToSpeech: { enabled: true, backend: 'browser' },
|
|
65
|
+
// Desmos needs an application key; see "Simple Default" below.
|
|
37
66
|
calculator: { enabled: true }
|
|
38
67
|
},
|
|
39
68
|
placement: {
|
|
40
|
-
section: ['
|
|
69
|
+
section: ['graph', 'periodicTable', 'protractor', 'lineReader', 'ruler'],
|
|
41
70
|
item: ['calculator', 'textToSpeech', 'answerEliminator'],
|
|
42
71
|
passage: ['textToSpeech']
|
|
43
72
|
}
|
|
@@ -84,6 +113,7 @@ provider path is the item-player loader config:
|
|
|
84
113
|
|
|
85
114
|
### Toolkit-Owned Canonical Event Stream
|
|
86
115
|
|
|
116
|
+
- `pie-toolkit-stage-change`
|
|
87
117
|
- `pie-toolkit-runtime-owned`
|
|
88
118
|
- `pie-toolkit-runtime-inherited`
|
|
89
119
|
- `pie-toolkit-ready`
|
|
@@ -141,8 +171,12 @@ tier; the choice is about ergonomics, not capability.
|
|
|
141
171
|
object passed by reference. Example:
|
|
142
172
|
|
|
143
173
|
```ts
|
|
174
|
+
import { createPackagedToolRegistry } from "@pie-players/pie-default-tool-loaders";
|
|
175
|
+
|
|
176
|
+
const toolRegistry = createPackagedToolRegistry();
|
|
144
177
|
const coordinator = new ToolkitCoordinator({
|
|
145
178
|
assessmentId: "my-assessment",
|
|
179
|
+
toolRegistry,
|
|
146
180
|
toolConfigStrictness: "warn",
|
|
147
181
|
tools: {
|
|
148
182
|
providers: { calculator: { enabled: true } },
|
|
@@ -229,17 +263,21 @@ Otherwise expose it through the configuration object only.
|
|
|
229
263
|
|
|
230
264
|
```typescript
|
|
231
265
|
import { ToolkitCoordinator } from '@pie-players/pie-assessment-toolkit';
|
|
266
|
+
import { createPackagedToolRegistry } from '@pie-players/pie-default-tool-loaders';
|
|
232
267
|
|
|
233
268
|
// Create coordinator with configuration
|
|
269
|
+
const toolRegistry = createPackagedToolRegistry();
|
|
234
270
|
const coordinator = new ToolkitCoordinator({
|
|
235
271
|
assessmentId: 'demo-assessment',
|
|
272
|
+
toolRegistry,
|
|
236
273
|
tools: {
|
|
237
274
|
providers: {
|
|
238
275
|
textToSpeech: { enabled: true, backend: 'browser' },
|
|
276
|
+
// Desmos needs an application key; see "Simple Default" below.
|
|
239
277
|
calculator: { enabled: true }
|
|
240
278
|
},
|
|
241
279
|
placement: {
|
|
242
|
-
section: ['
|
|
280
|
+
section: ['graph', 'periodicTable', 'protractor', 'lineReader', 'ruler'],
|
|
243
281
|
item: ['calculator', 'textToSpeech', 'answerEliminator'],
|
|
244
282
|
passage: ['textToSpeech']
|
|
245
283
|
}
|
|
@@ -393,12 +431,78 @@ player.toolCoordinator = toolCoordinator;
|
|
|
393
431
|
// ...
|
|
394
432
|
```
|
|
395
433
|
|
|
434
|
+
### Without a Section Player
|
|
435
|
+
|
|
436
|
+
`<pie-assessment-toolkit>` needs no section. Bind none and it provides tools,
|
|
437
|
+
policy and services to the item toolbars and item players inside it, which is
|
|
438
|
+
how the toolkit accompanies a plain item player:
|
|
439
|
+
|
|
440
|
+
```html
|
|
441
|
+
<pie-assessment-toolkit pnp-enforcement="on">
|
|
442
|
+
<pie-item-toolbar item-id="q1"></pie-item-toolbar>
|
|
443
|
+
<pie-item-player></pie-item-player>
|
|
444
|
+
</pie-assessment-toolkit>
|
|
445
|
+
```
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
import '@pie-players/pie-assessment-toolkit/components/pie-assessment-toolkit-element';
|
|
449
|
+
import '@pie-players/pie-assessment-toolkit/components/item-toolbar-element';
|
|
450
|
+
import '@pie-players/pie-item-player';
|
|
451
|
+
import {
|
|
452
|
+
createPackagedToolRegistry,
|
|
453
|
+
DEFAULT_TOOL_MODULE_LOADERS,
|
|
454
|
+
} from '@pie-players/pie-default-tool-loaders';
|
|
455
|
+
|
|
456
|
+
// With no section player, the registry's loaders are what define the tool elements.
|
|
457
|
+
const toolRegistry = createPackagedToolRegistry({
|
|
458
|
+
toolModuleLoaders: DEFAULT_TOOL_MODULE_LOADERS,
|
|
459
|
+
});
|
|
460
|
+
|
|
461
|
+
toolkit.tools = { placement: { item: ['calculator'] } };
|
|
462
|
+
toolkit.toolRegistry = toolRegistry;
|
|
463
|
+
toolkit.toolContextResolvers = toolContextResolvers;
|
|
464
|
+
toolkit.assessment = { id: 'a1', personalNeedsProfile: { supports: ['calculator'] } };
|
|
465
|
+
|
|
466
|
+
toolbar.item = item;
|
|
467
|
+
toolbar.toolRegistry = toolRegistry; // the toolbar does not read the toolkit's
|
|
468
|
+
toolbar.scopeElement = player; // the content answerEliminator acts on
|
|
469
|
+
```
|
|
470
|
+
|
|
471
|
+
A registry built without `toolModuleLoaders` renders toolbar buttons whose tool
|
|
472
|
+
elements never load. `textToSpeech` reads the region an item shell publishes,
|
|
473
|
+
which only the section player's cards provide, so it has no reading target in
|
|
474
|
+
this composition.
|
|
475
|
+
|
|
476
|
+
A profile change is a new `assessment` value; the toolbars re-derive on the
|
|
477
|
+
policy change it emits. Readiness events are section events: `toolkit-ready`,
|
|
478
|
+
`section-ready` and every stage, `composed` included, wait for a bound section,
|
|
479
|
+
and the toolkit builds its own coordinator only after it mounts. A host that needs a
|
|
480
|
+
readiness point constructs the `ToolkitCoordinator`, passes it as
|
|
481
|
+
`coordinator`, awaits `coordinator.waitUntilReady()`, and changes the profile
|
|
482
|
+
with `coordinator.updateAssessment(...)`, since the toolkit applies its
|
|
483
|
+
`assessment` property to a coordinator it owns. The `calculator-pnp` section
|
|
484
|
+
demo composes the owned-coordinator form.
|
|
485
|
+
|
|
486
|
+
The toolkit builds its own coordinator at mount from `tools`, `enabled-tools`,
|
|
487
|
+
`assessment-id`, `accessibility`, `lazy-init`, `tool-config-strictness` and
|
|
488
|
+
`toolRegistry`. A section that arrives after one of those changed initializes
|
|
489
|
+
with a coordinator rebuilt from the current values, and the toolbars move to
|
|
490
|
+
it. After a section has initialized, a change to them is reported once in the
|
|
491
|
+
console and does not reach the coordinator; `pnp-enforcement`, `assessment`,
|
|
492
|
+
`currentItemRef` and `toolContextResolvers` apply to it at any time. That
|
|
493
|
+
coordinator reports feature policy asked with no assessment bound only while
|
|
494
|
+
`pnp-enforcement` is `on`: a toolkit given no `assessment` and no enforcement
|
|
495
|
+
has asked for no accommodation.
|
|
496
|
+
|
|
396
497
|
## Tool Configuration Model
|
|
397
498
|
|
|
398
499
|
The toolkit uses one canonical `tools` model with three concerns:
|
|
399
500
|
|
|
400
501
|
- `policy`: allow/block constraints (global gates)
|
|
401
|
-
- `placement`: where tools appear (`
|
|
502
|
+
- `placement`: where tools appear (`section`, `item`, `passage`). Each tool
|
|
503
|
+
declares the levels it supports; `calculator` is item-only, and a tool placed
|
|
504
|
+
at a level it does not support fails validation, which throws under the
|
|
505
|
+
default `toolConfigStrictness: "error"`.
|
|
402
506
|
- `providers`: provider/runtime options (calculator, textToSpeech, etc.)
|
|
403
507
|
|
|
404
508
|
Example:
|
|
@@ -410,11 +514,9 @@ tools: {
|
|
|
410
514
|
blocked: ['graph']
|
|
411
515
|
},
|
|
412
516
|
placement: {
|
|
413
|
-
|
|
414
|
-
section: ['calculator', 'graph', 'periodicTable', 'protractor', 'lineReader', 'ruler'],
|
|
517
|
+
section: ['graph', 'periodicTable', 'protractor', 'lineReader', 'ruler'],
|
|
415
518
|
item: ['calculator', 'textToSpeech', 'answerEliminator'],
|
|
416
|
-
passage: ['textToSpeech']
|
|
417
|
-
rubric: []
|
|
519
|
+
passage: ['textToSpeech']
|
|
418
520
|
},
|
|
419
521
|
providers: {
|
|
420
522
|
calculator: {
|
|
@@ -465,7 +567,8 @@ tools: {
|
|
|
465
567
|
**Available Item-Level Tools:**
|
|
466
568
|
- **TTS (Text-to-Speech)**: Reads the specific question/passage text
|
|
467
569
|
- **Answer Eliminator**: Strikes through answer choices for that question
|
|
468
|
-
- **
|
|
570
|
+
- **Calculator**: Basic, scientific or graphing calculator
|
|
571
|
+
- **Highlighter** (`annotationToolbar`): Highlights and annotates selected text; it opens from a text selection, outside the toolbars
|
|
469
572
|
|
|
470
573
|
**Example Use Case:**
|
|
471
574
|
A student uses answer eliminator on Question 3 to cross out choices B and D. When they navigate to Question 4, they see fresh, uneliminated choices. When they return to Question 3, their eliminations are restored.
|
|
@@ -477,38 +580,31 @@ Tools that **float above the entire assessment** and persist across questions:
|
|
|
477
580
|
```typescript
|
|
478
581
|
tools: {
|
|
479
582
|
placement: {
|
|
480
|
-
section: ['
|
|
481
|
-
},
|
|
482
|
-
providers: {
|
|
483
|
-
calculator: {
|
|
484
|
-
enabled: true,
|
|
485
|
-
provider: {
|
|
486
|
-
runtime: { authFetcher: async () => { /* ... */ } }
|
|
487
|
-
}
|
|
488
|
-
}
|
|
583
|
+
section: ['graph', 'periodicTable', 'protractor', 'lineReader', 'ruler', 'theme']
|
|
489
584
|
}
|
|
490
585
|
}
|
|
491
586
|
```
|
|
492
587
|
|
|
588
|
+
The section player renders the section toolbar only when its `show-toolbar`
|
|
589
|
+
attribute is `true`; the attribute defaults to `false`.
|
|
590
|
+
|
|
493
591
|
**Characteristics:**
|
|
494
592
|
- **Scope**: Section-wide, shared across all questions
|
|
495
593
|
- **Lifecycle**: Single instance initialized for entire section
|
|
496
|
-
- **State**: Persistent (
|
|
594
|
+
- **State**: Persistent (a tool stays open and in place as you navigate)
|
|
497
595
|
- **UI Pattern**: Draggable floating panels/overlays with z-index management
|
|
498
596
|
- **State Persistence**: Global state maintained throughout section
|
|
499
597
|
|
|
500
598
|
**Available Floating Tools:**
|
|
501
|
-
- **
|
|
502
|
-
- **Graph**: Graphing tool for plotting functions
|
|
599
|
+
- **Graph**: Coordinate plane
|
|
503
600
|
- **Periodic Table**: Interactive periodic table reference
|
|
504
601
|
- **Protractor**: Angle measurement tool
|
|
505
602
|
- **Ruler**: Linear measurement tool (metric/imperial)
|
|
506
603
|
- **Line Reader**: Reading guide/masking overlay
|
|
507
|
-
- **
|
|
508
|
-
- **Color Scheme**: High-contrast color adjustments
|
|
604
|
+
- **Color Scheme** (`theme`): High-contrast color adjustments
|
|
509
605
|
|
|
510
606
|
**Example Use Case:**
|
|
511
|
-
A student opens the
|
|
607
|
+
A student opens the periodic table on Question 2 and moves it beside the passage. When they navigate to Question 7, it is still open where they left it.
|
|
512
608
|
|
|
513
609
|
### When to Use Each
|
|
514
610
|
|
|
@@ -529,15 +625,19 @@ Use **floating tools** when:
|
|
|
529
625
|
Complete example showing both types:
|
|
530
626
|
|
|
531
627
|
```typescript
|
|
628
|
+
import { createPackagedToolRegistry } from '@pie-players/pie-default-tool-loaders';
|
|
629
|
+
|
|
630
|
+
const toolRegistry = createPackagedToolRegistry();
|
|
532
631
|
const coordinator = new ToolkitCoordinator({
|
|
533
632
|
assessmentId: 'math-exam',
|
|
633
|
+
toolRegistry,
|
|
534
634
|
tools: {
|
|
535
635
|
placement: {
|
|
536
636
|
// Contextual placement
|
|
537
637
|
item: ['calculator', 'textToSpeech', 'answerEliminator'],
|
|
538
638
|
passage: ['textToSpeech'],
|
|
539
639
|
// Section-level utilities
|
|
540
|
-
section: ['
|
|
640
|
+
section: ['graph', 'periodicTable', 'protractor', 'lineReader', 'ruler', 'theme']
|
|
541
641
|
},
|
|
542
642
|
providers: {
|
|
543
643
|
calculator: {
|
|
@@ -566,11 +666,15 @@ const coordinator = new ToolkitCoordinator({
|
|
|
566
666
|
For most use cases, simply enable all available tools:
|
|
567
667
|
|
|
568
668
|
```typescript
|
|
669
|
+
import { createPackagedToolRegistry } from '@pie-players/pie-default-tool-loaders';
|
|
670
|
+
|
|
671
|
+
const toolRegistry = createPackagedToolRegistry();
|
|
569
672
|
const coordinator = new ToolkitCoordinator({
|
|
570
673
|
assessmentId: 'my-assessment',
|
|
674
|
+
toolRegistry,
|
|
571
675
|
tools: {
|
|
572
676
|
placement: {
|
|
573
|
-
section: ['
|
|
677
|
+
section: ['graph', 'periodicTable', 'protractor', 'lineReader', 'ruler'],
|
|
574
678
|
item: ['calculator', 'textToSpeech', 'answerEliminator'],
|
|
575
679
|
passage: ['textToSpeech']
|
|
576
680
|
},
|
|
@@ -588,12 +692,14 @@ const coordinator = new ToolkitCoordinator({
|
|
|
588
692
|
```
|
|
589
693
|
|
|
590
694
|
The ToolkitCoordinator handles service initialization, provider management, and
|
|
591
|
-
state coordination. With no calculator provider configuration, the
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
`
|
|
596
|
-
|
|
695
|
+
state coordination. With no calculator provider configuration, the Desmos
|
|
696
|
+
implementation remains the default. Desmos's CDN rejects a `calculator.js`
|
|
697
|
+
request without an `apiKey` (HTTP 403), so the Desmos calculator opens only when
|
|
698
|
+
the host supplies `provider.init.apiKey` or `provider.runtime.authFetcher`, or
|
|
699
|
+
has already loaded `window.Desmos`; the adapter's keyless request grants no
|
|
700
|
+
Desmos license either. Runtime key delivery avoids committing the key but does
|
|
701
|
+
not hide it from the browser's Desmos script request. The bundled open-source
|
|
702
|
+
implementation below needs no key.
|
|
597
703
|
|
|
598
704
|
Select the separate GeoGebra implementation explicitly without changing the
|
|
599
705
|
calculator capability, placement, or item policy:
|
|
@@ -747,6 +853,18 @@ tools: {
|
|
|
747
853
|
}
|
|
748
854
|
```
|
|
749
855
|
|
|
856
|
+
The fetch completes before the first TTS request, and its result merges over the
|
|
857
|
+
provider config: a returned `authToken` is sent as `Authorization: Bearer <token>`
|
|
858
|
+
and returned `headers` with every synthesis request, and under
|
|
859
|
+
`includeAuthOnAssetFetch` the `Authorization` header also reaches the custom
|
|
860
|
+
transport's speech-mark and audio fetches. A failed fetch falls back to browser
|
|
861
|
+
speech and reports `pie-tool-init-error`.
|
|
862
|
+
|
|
863
|
+
For a server that authenticates by cookie on another origin, set `credentials:
|
|
864
|
+
"include"` in the `textToSpeech` provider settings, beside
|
|
865
|
+
`includeAuthOnAssetFetch`. The cookie reaches speech-mark and audio fetches only
|
|
866
|
+
for origins in `assetOrigins`; unset, every TTS fetch keeps the browser default.
|
|
867
|
+
|
|
750
868
|
### Custom Transport via Server Proxy (SC-style)
|
|
751
869
|
|
|
752
870
|
For custom backends that return URL assets (for example `{ audioContent, word }`),
|
|
@@ -838,9 +956,9 @@ The persistence strategy works with the same `SectionControllerSessionState` sha
|
|
|
838
956
|
### ✅ QTI 3.0 Standard Access Features
|
|
839
957
|
|
|
840
958
|
- **95+ Standardized Features**: Complete QTI 3.0 / IMS AfA 3.0 accessibility features
|
|
841
|
-
- **
|
|
959
|
+
- **8 Feature Categories**: Visual, auditory, motor, cognitive, reading, navigation, linguistic, assessment
|
|
842
960
|
- **Example Configurations**: Illustrative PNP profile examples (low vision, dyslexia, ADHD, etc.)
|
|
843
|
-
- **Tool Mappings**:
|
|
961
|
+
- **Tool Mappings**: Every packaged tool registration maps to standard QTI 3.0 features
|
|
844
962
|
|
|
845
963
|
### ✅ Section Player Integration
|
|
846
964
|
|
|
@@ -865,11 +983,9 @@ export interface ToolkitCoordinatorConfig {
|
|
|
865
983
|
blocked?: string[];
|
|
866
984
|
};
|
|
867
985
|
placement?: {
|
|
868
|
-
assessment?: string[];
|
|
869
986
|
section?: string[];
|
|
870
987
|
item?: string[];
|
|
871
988
|
passage?: string[];
|
|
872
|
-
rubric?: string[];
|
|
873
989
|
};
|
|
874
990
|
providers?: {
|
|
875
991
|
textToSpeech?: {
|
|
@@ -1189,8 +1305,8 @@ that could not parse the markup left the video in the visible content, showing t
|
|
|
1189
1305
|
accommodation to every learner regardless of eligibility.
|
|
1190
1306
|
|
|
1191
1307
|
This package resolves and registers those cards through
|
|
1192
|
-
`AccessibilityCatalogResolver` and the generic media helpers
|
|
1193
|
-
|
|
1308
|
+
`AccessibilityCatalogResolver` and the generic media helpers it re-exports
|
|
1309
|
+
from `@pie-players/pie-players-shared/media`. Which card types mean what belongs to the capability that
|
|
1194
1310
|
needs them — signing's card validators and its resolution rules live in
|
|
1195
1311
|
`@pie-players/pie-tool-sign-language`, behind that capability's
|
|
1196
1312
|
`requiresAuthoredContent`.
|
|
@@ -1232,18 +1348,21 @@ mounted surface elements immediately.
|
|
|
1232
1348
|
The section player provides automatic ToolkitCoordinator integration:
|
|
1233
1349
|
|
|
1234
1350
|
```html
|
|
1235
|
-
<pie-section-player id="player"></pie-section-player>
|
|
1351
|
+
<pie-section-player-splitpane id="player" section-id="section-1"></pie-section-player-splitpane>
|
|
1236
1352
|
|
|
1237
1353
|
<script type="module">
|
|
1238
1354
|
import { ToolkitCoordinator } from '@pie-players/pie-assessment-toolkit';
|
|
1355
|
+
import { createPackagedToolRegistry } from '@pie-players/pie-default-tool-loaders';
|
|
1239
1356
|
|
|
1240
1357
|
// Create coordinator
|
|
1358
|
+
const toolRegistry = createPackagedToolRegistry();
|
|
1241
1359
|
const coordinator = new ToolkitCoordinator({
|
|
1242
1360
|
assessmentId: 'my-assessment',
|
|
1361
|
+
toolRegistry,
|
|
1243
1362
|
tools: {
|
|
1244
1363
|
providers: { textToSpeech: { enabled: true, backend: 'browser' } },
|
|
1245
1364
|
placement: {
|
|
1246
|
-
section: ['
|
|
1365
|
+
section: ['graph', 'periodicTable', 'protractor', 'lineReader', 'ruler'],
|
|
1247
1366
|
item: ['calculator', 'textToSpeech', 'answerEliminator'],
|
|
1248
1367
|
passage: ['textToSpeech']
|
|
1249
1368
|
}
|
|
@@ -1257,7 +1376,7 @@ The section player provides automatic ToolkitCoordinator integration:
|
|
|
1257
1376
|
|
|
1258
1377
|
// Player automatically:
|
|
1259
1378
|
// - Extracts services from coordinator
|
|
1260
|
-
// -
|
|
1379
|
+
// - Scopes its runtime engine to `section-id`
|
|
1261
1380
|
// - Provides runtime context to child components
|
|
1262
1381
|
// - Manages SSML extraction
|
|
1263
1382
|
// - Handles catalog lifecycle
|
|
@@ -1303,15 +1422,9 @@ player.section = mySection;
|
|
|
1303
1422
|
|
|
1304
1423
|
// Internally creates:
|
|
1305
1424
|
// new ToolkitCoordinator({
|
|
1306
|
-
// assessmentId: '
|
|
1307
|
-
//
|
|
1308
|
-
//
|
|
1309
|
-
// placement: {
|
|
1310
|
-
// section: ['calculator', 'graph', 'periodicTable', 'protractor', 'lineReader', 'ruler'],
|
|
1311
|
-
// item: ['calculator', 'textToSpeech', 'answerEliminator'],
|
|
1312
|
-
// passage: ['textToSpeech']
|
|
1313
|
-
// }
|
|
1314
|
-
// }
|
|
1425
|
+
// assessmentId: 'section-demo-direct', // or the assessment-id attribute
|
|
1426
|
+
// toolRegistry, // the player's toolRegistry, else the packaged registry
|
|
1427
|
+
// tools: player.runtime?.tools // no tools are placed when this is unset
|
|
1315
1428
|
// })
|
|
1316
1429
|
```
|
|
1317
1430
|
|
|
@@ -1409,8 +1522,9 @@ pick the stability surface that matches their use case:
|
|
|
1409
1522
|
## Writing a capability package
|
|
1410
1523
|
|
|
1411
1524
|
`@pie-players/pie-assessment-toolkit/tools/internal` is what a capability
|
|
1412
|
-
package imports: the `ToolRegistration` contract, the
|
|
1413
|
-
|
|
1525
|
+
package imports: the `ToolRegistration` contract, the `ToolProviderApi` its
|
|
1526
|
+
provider descriptor creates, the surface and content dependency types,
|
|
1527
|
+
`resolveToolTag` and the toolbar registration helpers. Same
|
|
1414
1528
|
stability contract as the other `*/internal` entry points — symbols may change
|
|
1415
1529
|
between minor versions with a changeset note.
|
|
1416
1530
|
|
|
@@ -1540,8 +1654,9 @@ section-player kernel intercepts the toolkit's bubbled emit at
|
|
|
1540
1654
|
layout host sees only the canonical engine-bridge emit. Direct
|
|
1541
1655
|
listeners on `<pie-assessment-toolkit>` itself still see the toolkit's
|
|
1542
1656
|
own emit (the toolkit dispatch reaches them before the kernel listener
|
|
1543
|
-
runs).
|
|
1544
|
-
`packages/section-player/tests/section-player-
|
|
1657
|
+
runs). A coordinator the host passes in reports through the same
|
|
1658
|
+
surfaces. `packages/section-player/tests/section-player-event-delivery.spec.ts`
|
|
1659
|
+
pins these counts.
|
|
1545
1660
|
The layout host emits one `framework-error` DOM event per framework error.
|
|
1546
1661
|
|
|
1547
1662
|
Hosts should listen to `pie-stage-change` (with the readiness detail also
|
|
@@ -1608,8 +1723,8 @@ Full TypeScript definitions included:
|
|
|
1608
1723
|
|
|
1609
1724
|
```typescript
|
|
1610
1725
|
import type {
|
|
1611
|
-
|
|
1612
|
-
|
|
1726
|
+
ToolkitCoordinatorApi,
|
|
1727
|
+
ElementToolStateStoreApi,
|
|
1613
1728
|
ToolkitCoordinatorConfig,
|
|
1614
1729
|
ToolkitServiceBundle
|
|
1615
1730
|
} from '@pie-players/pie-assessment-toolkit';
|
|
@@ -1623,7 +1738,7 @@ from tool configuration. Two sanitization layers apply:
|
|
|
1623
1738
|
|
|
1624
1739
|
- **Item / passage markup** - sanitized by default in
|
|
1625
1740
|
`pie-item-player`. See
|
|
1626
|
-
[pie-item-player README](
|
|
1741
|
+
[pie-item-player README](../item-player/README.md#content-trust-boundary)
|
|
1627
1742
|
for the `trust-markup` opt-out and the `sanitizeMarkup` override.
|
|
1628
1743
|
As a post-sanitization step, every authored `<img>` outside a `pie-*`
|
|
1629
1744
|
custom element is wrapped in `<span class="pie-image-scroll">` so
|
|
@@ -1,14 +1,10 @@
|
|
|
1
1
|
import type { AssessmentSession, AssessmentSectionSessionState, AssessmentSessionNavigationState, AssessmentSessionRealization, SectionControllerSessionState } from "@pie-players/pie-players-shared/types";
|
|
2
|
-
import type { StorageLike } from "./TestSession.js";
|
|
3
2
|
/**
|
|
4
3
|
* Re-exported so every existing import site keeps its specifier. These shapes are
|
|
5
4
|
* canonical in `@pie-players/pie-players-shared/types`; this module owns the
|
|
6
|
-
*
|
|
5
|
+
* helpers over them, not the shapes.
|
|
7
6
|
*/
|
|
8
7
|
export type { AssessmentSession, AssessmentSectionSessionState, AssessmentSessionNavigationState, AssessmentSessionRealization, };
|
|
9
|
-
export declare function getAssessmentSessionStorageKey(assessmentAttemptSessionIdentifier: string): string;
|
|
10
|
-
export declare function loadAssessmentSession(storage: StorageLike, assessmentAttemptSessionIdentifier: string): AssessmentSession | null;
|
|
11
|
-
export declare function saveAssessmentSession(storage: StorageLike, session: AssessmentSession): void;
|
|
12
8
|
export declare function createNewAssessmentSession(args: {
|
|
13
9
|
assessmentAttemptSessionIdentifier: string;
|
|
14
10
|
assessmentId: string;
|
|
@@ -1,36 +1,7 @@
|
|
|
1
1
|
const ASSESSMENT_SESSION_VERSION = 1;
|
|
2
|
-
const STORAGE_PREFIX = "pie:assessment-session:v1:";
|
|
3
2
|
function nowIso() {
|
|
4
3
|
return new Date().toISOString();
|
|
5
4
|
}
|
|
6
|
-
export function getAssessmentSessionStorageKey(assessmentAttemptSessionIdentifier) {
|
|
7
|
-
return `${STORAGE_PREFIX}${assessmentAttemptSessionIdentifier}`;
|
|
8
|
-
}
|
|
9
|
-
export function loadAssessmentSession(storage, assessmentAttemptSessionIdentifier) {
|
|
10
|
-
const raw = storage.getItem(getAssessmentSessionStorageKey(assessmentAttemptSessionIdentifier));
|
|
11
|
-
if (!raw)
|
|
12
|
-
return null;
|
|
13
|
-
try {
|
|
14
|
-
const parsed = JSON.parse(raw);
|
|
15
|
-
if (!parsed || parsed.version !== ASSESSMENT_SESSION_VERSION)
|
|
16
|
-
return null;
|
|
17
|
-
if (parsed.assessmentAttemptSessionIdentifier !==
|
|
18
|
-
assessmentAttemptSessionIdentifier) {
|
|
19
|
-
return null;
|
|
20
|
-
}
|
|
21
|
-
return parsed;
|
|
22
|
-
}
|
|
23
|
-
catch {
|
|
24
|
-
return null;
|
|
25
|
-
}
|
|
26
|
-
}
|
|
27
|
-
export function saveAssessmentSession(storage, session) {
|
|
28
|
-
const updated = {
|
|
29
|
-
...session,
|
|
30
|
-
updatedAt: nowIso(),
|
|
31
|
-
};
|
|
32
|
-
storage.setItem(getAssessmentSessionStorageKey(session.assessmentAttemptSessionIdentifier), JSON.stringify(updated));
|
|
33
|
-
}
|
|
34
5
|
export function createNewAssessmentSession(args) {
|
|
35
6
|
const startedAt = nowIso();
|
|
36
7
|
const initialSectionIdentifier = args.sectionIdentifiers[0];
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
import{a}from"./chunks/ItemToolBar-
|
|
1
|
+
import{a}from"./chunks/ItemToolBar-b9dz5jvd.js";import"./chunks/ItemToolBar-h4xap0t0.js";import"./chunks/ItemToolBar-gmrryv2v.js";export{a as default};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|