@pie-players/pie-assessment-toolkit 0.3.64 → 0.3.65
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 +45 -17
- package/dist/components/ItemToolBar.custom-element.js +1 -1
- package/dist/components/PieAssessmentToolkit.custom-element.js +6 -6
- package/dist/components/SectionToolBar.custom-element.js +1 -1
- package/dist/components/chunks/ItemToolBar-cckwpz6c.js +51 -0
- package/dist/components/chunks/ItemToolBar-pryf0rtz.js +22 -0
- package/dist/index.d.ts +5 -6
- package/dist/index.js +9 -4
- package/dist/runtime/composition-emit-scheduler.d.ts +78 -0
- package/dist/runtime/composition-emit-scheduler.js +154 -0
- package/dist/runtime/core/engine-resolver.d.ts +1 -1
- package/dist/services/ToolRegistry.d.ts +218 -8
- package/dist/services/ToolRegistry.js +124 -8
- package/dist/services/ToolkitCoordinator.d.ts +2 -1
- package/dist/services/ToolkitCoordinator.js +23 -6
- package/dist/services/createDefaultToolRegistry.d.ts +25 -58
- package/dist/services/createDefaultToolRegistry.js +24 -104
- package/dist/services/defaultPersonalNeedsProfile.d.ts +16 -14
- package/dist/services/defaultPersonalNeedsProfile.js +17 -38
- package/dist/services/pnp-standard-features.d.ts +1 -1
- package/dist/services/tool-config-defaults.d.ts +7 -23
- package/dist/services/tool-config-defaults.js +7 -46
- package/dist/services/tool-config-validation.d.ts +1 -1
- package/dist/services/tool-config-validation.js +44 -4
- package/dist/services/tts/browser-provider.js +2 -1
- package/dist/services/tts-runtime-config.js +7 -2
- package/dist/tools/internal.d.ts +34 -0
- package/dist/tools/internal.js +33 -0
- package/dist/tools/tool-tag-map.d.ts +15 -3
- package/dist/tools/tool-tag-map.js +21 -18
- package/package.json +14 -10
- package/dist/components/chunks/ItemToolBar-3cppre9r.js +0 -51
- package/dist/components/chunks/ItemToolBar-7rq2gj8b.js +0 -22
- package/dist/services/sign-language-cards.d.ts +0 -82
- package/dist/services/sign-language-cards.js +0 -133
- package/dist/tools/registrations/accessibility-tools.d.ts +0 -34
- package/dist/tools/registrations/accessibility-tools.js +0 -217
- package/dist/tools/registrations/calculator.d.ts +0 -20
- package/dist/tools/registrations/calculator.js +0 -228
- package/dist/tools/registrations/interaction-tools.d.ts +0 -27
- package/dist/tools/registrations/interaction-tools.js +0 -143
- package/dist/tools/registrations/measurement-tools.d.ts +0 -24
- package/dist/tools/registrations/measurement-tools.js +0 -130
- package/dist/tools/registrations/subject-specific-tools.d.ts +0 -27
- package/dist/tools/registrations/subject-specific-tools.js +0 -158
- package/dist/tools/registrations/tts.d.ts +0 -21
- package/dist/tools/registrations/tts.js +0 -184
|
@@ -25,7 +25,7 @@ import { TTSService } from "./TTSService.js";
|
|
|
25
25
|
import { BrowserTTSProvider } from "./tts/browser-provider.js";
|
|
26
26
|
import { buildRuntimeTTSConfig, resolveTTSBackend, resolveTTSRuntimeSettings, } from "./tts-runtime-config.js";
|
|
27
27
|
import { ToolProviderRegistry } from "./tool-providers/index.js";
|
|
28
|
-
import {
|
|
28
|
+
import { ToolRegistry } from "./ToolRegistry.js";
|
|
29
29
|
import { ToolPolicyEngine, } from "../policy/engine.js";
|
|
30
30
|
import { resolveDefaultPnpEnforcement } from "../policy/internal.js";
|
|
31
31
|
const isPlainRecord = (value) => !!value && typeof value === "object" && !Array.isArray(value);
|
|
@@ -190,7 +190,13 @@ export class ToolkitCoordinator {
|
|
|
190
190
|
boundCurrentItemRef = null;
|
|
191
191
|
static resolveConfig(config) {
|
|
192
192
|
const strictness = normalizeToolConfigStrictness(config.toolConfigStrictness);
|
|
193
|
-
|
|
193
|
+
// An empty registry when the host supplies none. This package no longer
|
|
194
|
+
// holds the packaged capability set, so there is nothing to fall back to —
|
|
195
|
+
// a host that wants stock tools passes a registry from
|
|
196
|
+
// `@pie-players/pie-default-tool-loaders`. Tool-id validation is skipped
|
|
197
|
+
// against an empty registry (with a diagnostic saying so) rather than
|
|
198
|
+
// rejecting every configured id.
|
|
199
|
+
const toolRegistry = config.toolRegistry ?? new ToolRegistry();
|
|
194
200
|
const normalized = config.deferToolConfigValidation === true
|
|
195
201
|
? normalizeToolsConfig(config.tools)
|
|
196
202
|
: normalizeAndValidateToolsConfig(config.tools, {
|
|
@@ -232,8 +238,7 @@ export class ToolkitCoordinator {
|
|
|
232
238
|
const resolvedConfig = ToolkitCoordinator.resolveConfig(config);
|
|
233
239
|
this.assessmentId = resolvedConfig.assessmentId;
|
|
234
240
|
this.config = resolvedConfig;
|
|
235
|
-
this.toolRegistry =
|
|
236
|
-
resolvedConfig.toolRegistry ?? createPackagedToolRegistry();
|
|
241
|
+
this.toolRegistry = resolvedConfig.toolRegistry ?? new ToolRegistry();
|
|
237
242
|
this.installToolContextResolvers(resolvedConfig.toolContextResolvers);
|
|
238
243
|
this.hooks = resolvedConfig.hooks ?? {};
|
|
239
244
|
this.lazyInit = config.lazyInit === true;
|
|
@@ -1268,13 +1273,16 @@ export class ToolkitCoordinator {
|
|
|
1268
1273
|
if (canUseEventTarget) {
|
|
1269
1274
|
synth.removeEventListener("voiceschanged", onVoicesChanged);
|
|
1270
1275
|
}
|
|
1271
|
-
else if (assignedHandler &&
|
|
1276
|
+
else if (assignedHandler &&
|
|
1277
|
+
synth.onvoiceschanged === onVoicesChanged) {
|
|
1272
1278
|
synth.onvoiceschanged = previousHandler;
|
|
1273
1279
|
}
|
|
1274
1280
|
resolve();
|
|
1275
1281
|
};
|
|
1276
1282
|
const onVoicesChanged = (event) => {
|
|
1277
|
-
if (!canUseEventTarget &&
|
|
1283
|
+
if (!canUseEventTarget &&
|
|
1284
|
+
typeof previousHandler === "function" &&
|
|
1285
|
+
event) {
|
|
1278
1286
|
previousHandler.call(synth, event);
|
|
1279
1287
|
}
|
|
1280
1288
|
finish();
|
|
@@ -1371,6 +1379,15 @@ export class ToolkitCoordinator {
|
|
|
1371
1379
|
if (toolId === "tts") {
|
|
1372
1380
|
throw new Error(`Tool id "tts" is no longer supported. Use "textToSpeech".`);
|
|
1373
1381
|
}
|
|
1382
|
+
// An empty registry means the host supplied none, not that every id is
|
|
1383
|
+
// wrong. There is nothing to check an id against, and throwing turns a
|
|
1384
|
+
// host's every tool-config call into an exception — including the calls
|
|
1385
|
+
// this coordinator's own default-provider block provokes, which is how a
|
|
1386
|
+
// host that passes no registry ended up unable to read its own config.
|
|
1387
|
+
// `normalizeAndValidateToolsConfig` already reports the missing registry
|
|
1388
|
+
// once, as `tools.registryUnavailable`; a second report per call is noise.
|
|
1389
|
+
if (this.toolRegistry.getAllToolIds().length === 0)
|
|
1390
|
+
return;
|
|
1374
1391
|
if (!this.toolRegistry.get(toolId)) {
|
|
1375
1392
|
throw new Error(`Unknown tool id "${toolId}".`);
|
|
1376
1393
|
}
|
|
@@ -1,86 +1,53 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Tool Registry Factory
|
|
3
3
|
*
|
|
4
|
-
* Creates
|
|
5
|
-
*
|
|
4
|
+
* Creates an empty `ToolRegistry` and installs whatever component overrides and
|
|
5
|
+
* lazy module loaders the caller supplies.
|
|
6
|
+
*
|
|
7
|
+
* It registers nothing by itself, deliberately. Eleven concrete registrations
|
|
8
|
+
* used to live in this package, which made the policy and registry core know
|
|
9
|
+
* every capability by name and left a host unable to contribute one without a PR
|
|
10
|
+
* against this package. The packaged set now lives in the composition layer:
|
|
11
|
+
* `createPackagedToolRegistry` from `@pie-players/pie-default-tool-loaders`.
|
|
6
12
|
*/
|
|
13
|
+
import type { ToolRegistration, ToolModuleLoader } from "./ToolRegistry.js";
|
|
7
14
|
import { ToolRegistry } from "./ToolRegistry.js";
|
|
8
|
-
import type {
|
|
9
|
-
import
|
|
10
|
-
import { type ToolComponentFactory, type ToolComponentFactoryMap, type ToolTagMap } from "../tools/tool-tag-map.js";
|
|
11
|
-
import { DEFAULT_TOOL_PLACEMENT, PACKAGED_TOOL_PLACEMENT, SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT } from "./tool-config-defaults.js";
|
|
15
|
+
import type { ToolComponentFactory, ToolComponentFactoryMap, ToolTagMap } from "../tools/tool-tag-map.js";
|
|
16
|
+
import { DEFAULT_TOOL_PLACEMENT } from "./tool-config-defaults.js";
|
|
12
17
|
export interface DefaultToolRegistryOptions {
|
|
13
18
|
/**
|
|
14
|
-
*
|
|
15
|
-
*
|
|
19
|
+
* Registrations to register, keyed by toolId. Nothing is registered when this
|
|
20
|
+
* is absent.
|
|
16
21
|
*/
|
|
17
|
-
|
|
22
|
+
registrations?: Partial<Record<string, ToolRegistration>>;
|
|
18
23
|
/**
|
|
19
|
-
*
|
|
24
|
+
* Element tag mapping for the registrations being installed. There is no
|
|
25
|
+
* built-in default: a tag map names capabilities, so it belongs to whoever
|
|
26
|
+
* decides which capabilities exist.
|
|
20
27
|
*/
|
|
21
28
|
toolTagMap?: Partial<ToolTagMap>;
|
|
22
29
|
/**
|
|
23
|
-
* Override component
|
|
30
|
+
* Override component creation globally (all tools) or per tool.
|
|
24
31
|
*/
|
|
25
32
|
toolComponentFactory?: ToolComponentFactory;
|
|
26
33
|
toolComponentFactories?: Partial<ToolComponentFactoryMap>;
|
|
27
34
|
/**
|
|
28
35
|
* Optional lazy module loaders keyed by toolId.
|
|
29
|
-
* Hosts can inject default loaders from an external package.
|
|
30
36
|
*/
|
|
31
37
|
toolModuleLoaders?: Partial<Record<string, ToolModuleLoader>>;
|
|
32
|
-
/**
|
|
33
|
-
* Register packaged PIE tools by default.
|
|
34
|
-
*
|
|
35
|
-
* @default false
|
|
36
|
-
*/
|
|
37
|
-
includePackagedTools?: boolean;
|
|
38
|
-
/**
|
|
39
|
-
* Restrict registration to specific packaged tool IDs.
|
|
40
|
-
* Ignored when includePackagedTools is false.
|
|
41
|
-
*/
|
|
42
|
-
toolIds?: string[];
|
|
43
38
|
}
|
|
44
39
|
/**
|
|
45
40
|
* Create a tool registry.
|
|
46
41
|
*
|
|
47
|
-
*
|
|
48
|
-
* For convenience, pass { includePackagedTools: true } to register all packaged tools,
|
|
49
|
-
* or use createPackagedToolRegistry().
|
|
50
|
-
*
|
|
51
|
-
* @returns ToolRegistry with all default tools
|
|
42
|
+
* @returns an empty `ToolRegistry` unless `registrations` is supplied
|
|
52
43
|
*/
|
|
53
44
|
export declare function createDefaultToolRegistry(options?: DefaultToolRegistryOptions): ToolRegistry;
|
|
54
|
-
export interface RegisterPackagedToolsOptions {
|
|
55
|
-
toolIds?: string[];
|
|
56
|
-
applyOverrides?: (registration: ToolRegistration) => ToolRegistration;
|
|
57
|
-
}
|
|
58
45
|
/**
|
|
59
|
-
*
|
|
60
|
-
*/
|
|
61
|
-
export declare function registerPackagedTools(registry: ToolRegistry, options?: RegisterPackagedToolsOptions): void;
|
|
62
|
-
/**
|
|
63
|
-
* Convenience factory that registers all packaged PIE tools.
|
|
64
|
-
*/
|
|
65
|
-
export declare function createPackagedToolRegistry(options?: Omit<DefaultToolRegistryOptions, "includePackagedTools">): ToolRegistry;
|
|
66
|
-
/**
|
|
67
|
-
* Default tool placement configuration
|
|
46
|
+
* Placement configuration with every level empty.
|
|
68
47
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
* - Global tools: theme (assessment/section level)
|
|
74
|
-
* - Context-smart: calculator, graph, periodicTable (item/element, auto-detect)
|
|
75
|
-
* - Reading aids: textToSpeech, lineReader, annotationToolbar (where text exists)
|
|
76
|
-
* - Interaction-specific: answerEliminator (choice questions), highlighter (text)
|
|
77
|
-
* - Measurement: ruler, protractor (element level, diagram/geometry)
|
|
48
|
+
* The only placement default this package can hold: a populated one would name
|
|
49
|
+
* capabilities. `PACKAGED_TOOL_PLACEMENT` and
|
|
50
|
+
* `SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT` are in
|
|
51
|
+
* `@pie-players/pie-default-tool-loaders`.
|
|
78
52
|
*/
|
|
79
53
|
export { DEFAULT_TOOL_PLACEMENT };
|
|
80
|
-
export { PACKAGED_TOOL_PLACEMENT };
|
|
81
|
-
export { SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT };
|
|
82
|
-
/**
|
|
83
|
-
* Tool priority order for rendering
|
|
84
|
-
* Tools will be rendered in this order when multiple tools are visible
|
|
85
|
-
*/
|
|
86
|
-
export declare const DEFAULT_TOOL_ORDER: readonly ["theme", "calculator", "textToSpeech", "lineReader", "annotationToolbar", "highlighter", "answerEliminator", "ruler", "protractor", "graph", "periodicTable"];
|
|
@@ -1,125 +1,45 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Tool Registry Factory
|
|
3
3
|
*
|
|
4
|
-
* Creates
|
|
5
|
-
*
|
|
4
|
+
* Creates an empty `ToolRegistry` and installs whatever component overrides and
|
|
5
|
+
* lazy module loaders the caller supplies.
|
|
6
|
+
*
|
|
7
|
+
* It registers nothing by itself, deliberately. Eleven concrete registrations
|
|
8
|
+
* used to live in this package, which made the policy and registry core know
|
|
9
|
+
* every capability by name and left a host unable to contribute one without a PR
|
|
10
|
+
* against this package. The packaged set now lives in the composition layer:
|
|
11
|
+
* `createPackagedToolRegistry` from `@pie-players/pie-default-tool-loaders`.
|
|
6
12
|
*/
|
|
7
13
|
import { ToolRegistry } from "./ToolRegistry.js";
|
|
8
|
-
import {
|
|
9
|
-
import { ttsToolRegistration } from "../tools/registrations/tts.js";
|
|
10
|
-
import { rulerToolRegistration, protractorToolRegistration, } from "../tools/registrations/measurement-tools.js";
|
|
11
|
-
import { answerEliminatorToolRegistration, highlighterToolRegistration, } from "../tools/registrations/interaction-tools.js";
|
|
12
|
-
import { lineReaderToolRegistration, themeToolRegistration, annotationToolbarRegistration, } from "../tools/registrations/accessibility-tools.js";
|
|
13
|
-
import { graphToolRegistration, periodicTableToolRegistration, } from "../tools/registrations/subject-specific-tools.js";
|
|
14
|
-
import { DEFAULT_TOOL_TAG_MAP, } from "../tools/tool-tag-map.js";
|
|
15
|
-
import { DEFAULT_TOOL_PLACEMENT, PACKAGED_TOOL_PLACEMENT, SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT, } from "./tool-config-defaults.js";
|
|
16
|
-
const PACKAGED_TOOL_REGISTRATIONS = [
|
|
17
|
-
calculatorToolRegistration,
|
|
18
|
-
ttsToolRegistration,
|
|
19
|
-
rulerToolRegistration,
|
|
20
|
-
protractorToolRegistration,
|
|
21
|
-
answerEliminatorToolRegistration,
|
|
22
|
-
highlighterToolRegistration,
|
|
23
|
-
lineReaderToolRegistration,
|
|
24
|
-
themeToolRegistration,
|
|
25
|
-
annotationToolbarRegistration,
|
|
26
|
-
graphToolRegistration,
|
|
27
|
-
periodicTableToolRegistration,
|
|
28
|
-
];
|
|
14
|
+
import { DEFAULT_TOOL_PLACEMENT } from "./tool-config-defaults.js";
|
|
29
15
|
/**
|
|
30
16
|
* Create a tool registry.
|
|
31
17
|
*
|
|
32
|
-
*
|
|
33
|
-
* For convenience, pass { includePackagedTools: true } to register all packaged tools,
|
|
34
|
-
* or use createPackagedToolRegistry().
|
|
35
|
-
*
|
|
36
|
-
* @returns ToolRegistry with all default tools
|
|
18
|
+
* @returns an empty `ToolRegistry` unless `registrations` is supplied
|
|
37
19
|
*/
|
|
38
20
|
export function createDefaultToolRegistry(options = {}) {
|
|
39
21
|
const registry = new ToolRegistry();
|
|
40
|
-
const
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
...(options.toolTagMap || {}),
|
|
44
|
-
},
|
|
45
|
-
toolComponentFactory: options.toolComponentFactory,
|
|
46
|
-
toolComponentFactories: options.toolComponentFactories,
|
|
47
|
-
};
|
|
48
|
-
const applyOverrides = (registration) => options.overrides?.[registration.toolId] || registration;
|
|
49
|
-
if (options.includePackagedTools) {
|
|
50
|
-
registerPackagedTools(registry, {
|
|
51
|
-
toolIds: options.toolIds,
|
|
52
|
-
applyOverrides,
|
|
53
|
-
});
|
|
22
|
+
for (const registration of Object.values(options.registrations ?? {})) {
|
|
23
|
+
if (registration)
|
|
24
|
+
registry.register(registration);
|
|
54
25
|
}
|
|
55
26
|
if (options.toolModuleLoaders &&
|
|
56
27
|
Object.keys(options.toolModuleLoaders).length > 0) {
|
|
57
28
|
registry.setToolModuleLoaders(options.toolModuleLoaders);
|
|
58
29
|
}
|
|
59
|
-
registry.setComponentOverrides(
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
* Register packaged PIE tools onto an existing registry.
|
|
64
|
-
*/
|
|
65
|
-
export function registerPackagedTools(registry, options = {}) {
|
|
66
|
-
const selectedToolIds = options.toolIds && options.toolIds.length > 0
|
|
67
|
-
? new Set(options.toolIds)
|
|
68
|
-
: null;
|
|
69
|
-
const applyOverrides = options.applyOverrides ||
|
|
70
|
-
((registration) => registration);
|
|
71
|
-
for (const registration of PACKAGED_TOOL_REGISTRATIONS) {
|
|
72
|
-
if (selectedToolIds && !selectedToolIds.has(registration.toolId)) {
|
|
73
|
-
continue;
|
|
74
|
-
}
|
|
75
|
-
registry.register(applyOverrides(registration));
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
/**
|
|
79
|
-
* Convenience factory that registers all packaged PIE tools.
|
|
80
|
-
*/
|
|
81
|
-
export function createPackagedToolRegistry(options = {}) {
|
|
82
|
-
return createDefaultToolRegistry({
|
|
83
|
-
...options,
|
|
84
|
-
includePackagedTools: true,
|
|
30
|
+
registry.setComponentOverrides({
|
|
31
|
+
toolTagMap: options.toolTagMap,
|
|
32
|
+
toolComponentFactory: options.toolComponentFactory,
|
|
33
|
+
toolComponentFactories: options.toolComponentFactories,
|
|
85
34
|
});
|
|
35
|
+
return registry;
|
|
86
36
|
}
|
|
87
37
|
/**
|
|
88
|
-
*
|
|
89
|
-
*
|
|
90
|
-
* Defines which tools appear at which levels by default.
|
|
91
|
-
* Integrators can override this configuration.
|
|
38
|
+
* Placement configuration with every level empty.
|
|
92
39
|
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
96
|
-
* -
|
|
97
|
-
* - Interaction-specific: answerEliminator (choice questions), highlighter (text)
|
|
98
|
-
* - Measurement: ruler, protractor (element level, diagram/geometry)
|
|
40
|
+
* The only placement default this package can hold: a populated one would name
|
|
41
|
+
* capabilities. `PACKAGED_TOOL_PLACEMENT` and
|
|
42
|
+
* `SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT` are in
|
|
43
|
+
* `@pie-players/pie-default-tool-loaders`.
|
|
99
44
|
*/
|
|
100
45
|
export { DEFAULT_TOOL_PLACEMENT };
|
|
101
|
-
export { PACKAGED_TOOL_PLACEMENT };
|
|
102
|
-
export { SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT };
|
|
103
|
-
/**
|
|
104
|
-
* Tool priority order for rendering
|
|
105
|
-
* Tools will be rendered in this order when multiple tools are visible
|
|
106
|
-
*/
|
|
107
|
-
export const DEFAULT_TOOL_ORDER = [
|
|
108
|
-
// Global accessibility first
|
|
109
|
-
"theme",
|
|
110
|
-
// Common tools
|
|
111
|
-
"calculator",
|
|
112
|
-
"textToSpeech",
|
|
113
|
-
// Reading aids
|
|
114
|
-
"lineReader",
|
|
115
|
-
"annotationToolbar",
|
|
116
|
-
"highlighter",
|
|
117
|
-
// Interaction tools
|
|
118
|
-
"answerEliminator",
|
|
119
|
-
// Measurement tools
|
|
120
|
-
"ruler",
|
|
121
|
-
"protractor",
|
|
122
|
-
// Subject-specific
|
|
123
|
-
"graph",
|
|
124
|
-
"periodicTable",
|
|
125
|
-
];
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import type { PersonalNeedsProfile } from "@pie-players/pie-players-shared/types";
|
|
2
2
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
3
|
+
* An empty personal-needs profile: nothing granted, nothing prohibited, nothing
|
|
4
|
+
* activated at init.
|
|
5
5
|
*
|
|
6
|
-
*
|
|
7
|
-
* tool's `pnpSupportIds`, which
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
6
|
+
* The core ships no populated default on purpose. It once derived one from every
|
|
7
|
+
* registered tool's `pnpSupportIds`, which read *registry membership* as
|
|
8
|
+
* *eligibility tier* — registration means "policy-addressable", not "universal,
|
|
9
|
+
* on by default" — so an accommodation-tier capability was granted to every
|
|
10
|
+
* student of every host that supplied no profile. The remedy at the time was a
|
|
11
|
+
* compile-time list of ids to exclude, which a host could not extend for its own
|
|
12
|
+
* accommodation.
|
|
13
13
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
14
|
+
* Which capabilities a deployment grants by default is a property of the
|
|
15
|
+
* program, not of this package: TTS is a universal feature in one program and a
|
|
16
|
+
* documented accommodation in another. That belongs in policy configuration
|
|
17
|
+
* alongside the district and test-administration levels. A named preset of
|
|
18
|
+
* today's universal set ships as data from
|
|
19
|
+
* `@pie-players/pie-default-tool-loaders`, for hosts that want it.
|
|
16
20
|
*/
|
|
17
|
-
export declare
|
|
18
|
-
export declare const DEFAULT_PERSONAL_NEEDS_PROFILE: PersonalNeedsProfile;
|
|
19
|
-
export declare function createDefaultPersonalNeedsProfile(): PersonalNeedsProfile;
|
|
21
|
+
export declare function createEmptyPersonalNeedsProfile(): PersonalNeedsProfile;
|
|
@@ -1,46 +1,25 @@
|
|
|
1
|
-
import { createPackagedToolRegistry } from "./createDefaultToolRegistry.js";
|
|
2
1
|
/**
|
|
3
|
-
*
|
|
4
|
-
*
|
|
2
|
+
* An empty personal-needs profile: nothing granted, nothing prohibited, nothing
|
|
3
|
+
* activated at init.
|
|
5
4
|
*
|
|
6
|
-
*
|
|
7
|
-
* tool's `pnpSupportIds`, which
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
5
|
+
* The core ships no populated default on purpose. It once derived one from every
|
|
6
|
+
* registered tool's `pnpSupportIds`, which read *registry membership* as
|
|
7
|
+
* *eligibility tier* — registration means "policy-addressable", not "universal,
|
|
8
|
+
* on by default" — so an accommodation-tier capability was granted to every
|
|
9
|
+
* student of every host that supplied no profile. The remedy at the time was a
|
|
10
|
+
* compile-time list of ids to exclude, which a host could not extend for its own
|
|
11
|
+
* accommodation.
|
|
13
12
|
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* Which capabilities a deployment grants by default is a property of the
|
|
14
|
+
* program, not of this package: TTS is a universal feature in one program and a
|
|
15
|
+
* documented accommodation in another. That belongs in policy configuration
|
|
16
|
+
* alongside the district and test-administration levels. A named preset of
|
|
17
|
+
* today's universal set ships as data from
|
|
18
|
+
* `@pie-players/pie-default-tool-loaders`, for hosts that want it.
|
|
16
19
|
*/
|
|
17
|
-
export
|
|
18
|
-
// QTI 3.0 / AfA `signLanguage`. Signed alternates are rendered by
|
|
19
|
-
// section-player's per-item media region, gated on this id.
|
|
20
|
-
"signLanguage",
|
|
21
|
-
];
|
|
22
|
-
function computeDefaultSupports() {
|
|
23
|
-
const registry = createPackagedToolRegistry();
|
|
24
|
-
const supports = new Set();
|
|
25
|
-
const excluded = new Set(ACCOMMODATION_ONLY_SUPPORT_IDS);
|
|
26
|
-
for (const tool of registry.getAllTools()) {
|
|
27
|
-
for (const supportId of tool.pnpSupportIds || []) {
|
|
28
|
-
if (excluded.has(supportId))
|
|
29
|
-
continue;
|
|
30
|
-
supports.add(supportId);
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return [...supports].sort();
|
|
34
|
-
}
|
|
35
|
-
const DEFAULT_SUPPORTS = computeDefaultSupports();
|
|
36
|
-
export const DEFAULT_PERSONAL_NEEDS_PROFILE = {
|
|
37
|
-
supports: [...DEFAULT_SUPPORTS],
|
|
38
|
-
prohibitedSupports: [],
|
|
39
|
-
activateAtInit: [],
|
|
40
|
-
};
|
|
41
|
-
export function createDefaultPersonalNeedsProfile() {
|
|
20
|
+
export function createEmptyPersonalNeedsProfile() {
|
|
42
21
|
return {
|
|
43
|
-
supports: [
|
|
22
|
+
supports: [],
|
|
44
23
|
prohibitedSupports: [],
|
|
45
24
|
activateAtInit: [],
|
|
46
25
|
};
|
|
@@ -167,7 +167,7 @@ export declare const QTI_STANDARD_ACCESS_FEATURES: {
|
|
|
167
167
|
/**
|
|
168
168
|
* Flat list of all standard access features for validation
|
|
169
169
|
*/
|
|
170
|
-
export declare const ALL_STANDARD_ACCESS_FEATURES: ("transcript" | "braille" | "textToSpeech" | "
|
|
170
|
+
export declare const ALL_STANDARD_ACCESS_FEATURES: ("transcript" | "braille" | "textToSpeech" | "calculator" | "strikethrough" | "answerEliminator" | "magnification" | "screenMagnifier" | "zoomable" | "highContrastDisplay" | "highContrastAudio" | "colorContrast" | "invertColors" | "displayTransformability" | "largePrint" | "fontEnlargement" | "resizeText" | "alternativeText" | "longDescription" | "describedMath" | "tactileGraphic" | "tactileObject" | "audioDescription" | "readAloud" | "humanVoice" | "syntheticVoice" | "speechRate" | "speechVolume" | "voicePitch" | "captions" | "closedCaptions" | "openCaptions" | "signLanguage" | "subtitles" | "audioControl" | "noBackgroundAudio" | "keyboardControl" | "mouseControl" | "touchControl" | "voiceControl" | "switchControl" | "eyeGazeControl" | "singleSwitchAccess" | "stickyKeys" | "keyboardShortcuts" | "timingControl" | "unlimitedTime" | "extendedTime" | "pauseControl" | "simplifiedLanguage" | "reducedComplexity" | "structuralNavigation" | "tableOfContents" | "reducedDistraction" | "noFlashing" | "pauseAnimation" | "annotations" | "bookmarking" | "highlighting" | "guidedNavigation" | "thesaurus" | "spellingAssistance" | "grammarAssistance" | "lineSpacing" | "wordSpacing" | "letterSpacing" | "fontFamily" | "readingMask" | "readingGuide" | "readingRuler" | "wordHighlighting" | "lineHighlighting" | "focusIndicator" | "printableResource" | "nemeth" | "refreshableBraille" | "index" | "pageNavigation" | "skipContent" | "breadcrumbs" | "searchable" | "fullTextSearch" | "multilingualText" | "translatedText" | "glossary" | "signLanguageInterpretation" | "visualLanguage" | "protractor" | "ruler" | "graph" | "graphingCalculator" | "periodicTable" | "formulaSheet" | "answerMasking" | "itemGlossary" | "tutorialAvailable")[];
|
|
171
171
|
/**
|
|
172
172
|
* Example PNP configurations for common accessibility needs
|
|
173
173
|
* These are NOT official profiles but illustrative examples showing
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placement defaults this package can hold.
|
|
3
|
+
*
|
|
4
|
+
* Only the empty one. `PACKAGED_TOOL_PLACEMENT` and
|
|
5
|
+
* `SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT` name capabilities, so they moved to
|
|
6
|
+
* the composition layer (`@pie-players/pie-default-tool-loaders`).
|
|
7
|
+
*/
|
|
1
8
|
export declare const DEFAULT_TOOL_PLACEMENT: {
|
|
2
9
|
readonly assessment: readonly [];
|
|
3
10
|
readonly section: readonly [];
|
|
@@ -6,26 +13,3 @@ export declare const DEFAULT_TOOL_PLACEMENT: {
|
|
|
6
13
|
readonly rubric: readonly [];
|
|
7
14
|
readonly element: readonly [];
|
|
8
15
|
};
|
|
9
|
-
/**
|
|
10
|
-
* Complete placement preset for hosts that want to enable all packaged tools.
|
|
11
|
-
* Prefer explicit host configuration over implicit defaults.
|
|
12
|
-
*/
|
|
13
|
-
export declare const PACKAGED_TOOL_PLACEMENT: {
|
|
14
|
-
readonly assessment: readonly ["theme"];
|
|
15
|
-
readonly section: readonly ["theme"];
|
|
16
|
-
readonly item: readonly ["textToSpeech", "highlighter", "annotationToolbar", "graph", "periodicTable"];
|
|
17
|
-
readonly passage: readonly ["textToSpeech", "highlighter", "annotationToolbar", "lineReader"];
|
|
18
|
-
readonly rubric: readonly ["textToSpeech", "highlighter", "annotationToolbar", "lineReader"];
|
|
19
|
-
readonly element: readonly ["calculator", "answerEliminator", "textToSpeech", "ruler", "protractor", "highlighter", "annotationToolbar", "graph", "periodicTable"];
|
|
20
|
-
};
|
|
21
|
-
/**
|
|
22
|
-
* Opt-in section-player placement preset for hosts that want to expose every
|
|
23
|
-
* packaged tool once at its normal assessment surface. This is not exhaustive:
|
|
24
|
-
* `supportedLevels` still defines where tools can run, and hosts can still
|
|
25
|
-
* choose different placement for custom UX.
|
|
26
|
-
*/
|
|
27
|
-
export declare const SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT: {
|
|
28
|
-
section: string[];
|
|
29
|
-
item: string[];
|
|
30
|
-
passage: string[];
|
|
31
|
-
};
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Placement defaults this package can hold.
|
|
3
|
+
*
|
|
4
|
+
* Only the empty one. `PACKAGED_TOOL_PLACEMENT` and
|
|
5
|
+
* `SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT` name capabilities, so they moved to
|
|
6
|
+
* the composition layer (`@pie-players/pie-default-tool-loaders`).
|
|
7
|
+
*/
|
|
1
8
|
export const DEFAULT_TOOL_PLACEMENT = {
|
|
2
9
|
assessment: [],
|
|
3
10
|
section: [],
|
|
@@ -6,49 +13,3 @@ export const DEFAULT_TOOL_PLACEMENT = {
|
|
|
6
13
|
rubric: [],
|
|
7
14
|
element: [],
|
|
8
15
|
};
|
|
9
|
-
/**
|
|
10
|
-
* Complete placement preset for hosts that want to enable all packaged tools.
|
|
11
|
-
* Prefer explicit host configuration over implicit defaults.
|
|
12
|
-
*/
|
|
13
|
-
export const PACKAGED_TOOL_PLACEMENT = {
|
|
14
|
-
assessment: ["theme"],
|
|
15
|
-
section: ["theme"],
|
|
16
|
-
item: [
|
|
17
|
-
"textToSpeech",
|
|
18
|
-
"highlighter",
|
|
19
|
-
"annotationToolbar",
|
|
20
|
-
"graph",
|
|
21
|
-
"periodicTable",
|
|
22
|
-
],
|
|
23
|
-
passage: ["textToSpeech", "highlighter", "annotationToolbar", "lineReader"],
|
|
24
|
-
rubric: ["textToSpeech", "highlighter", "annotationToolbar", "lineReader"],
|
|
25
|
-
element: [
|
|
26
|
-
"calculator",
|
|
27
|
-
"answerEliminator",
|
|
28
|
-
"textToSpeech",
|
|
29
|
-
"ruler",
|
|
30
|
-
"protractor",
|
|
31
|
-
"highlighter",
|
|
32
|
-
"annotationToolbar",
|
|
33
|
-
"graph",
|
|
34
|
-
"periodicTable",
|
|
35
|
-
],
|
|
36
|
-
};
|
|
37
|
-
/**
|
|
38
|
-
* Opt-in section-player placement preset for hosts that want to expose every
|
|
39
|
-
* packaged tool once at its normal assessment surface. This is not exhaustive:
|
|
40
|
-
* `supportedLevels` still defines where tools can run, and hosts can still
|
|
41
|
-
* choose different placement for custom UX.
|
|
42
|
-
*/
|
|
43
|
-
export const SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT = {
|
|
44
|
-
section: [
|
|
45
|
-
"theme",
|
|
46
|
-
"graph",
|
|
47
|
-
"periodicTable",
|
|
48
|
-
"lineReader",
|
|
49
|
-
"ruler",
|
|
50
|
-
"protractor",
|
|
51
|
-
],
|
|
52
|
-
item: ["calculator", "textToSpeech", "answerEliminator", "annotationToolbar"],
|
|
53
|
-
passage: ["textToSpeech", "annotationToolbar"],
|
|
54
|
-
};
|
|
@@ -4,7 +4,7 @@ import type { ToolRegistry } from "./ToolRegistry.js";
|
|
|
4
4
|
export type ToolConfigStrictness = "off" | "warn" | "error";
|
|
5
5
|
export type ToolConfigDiagnosticSeverity = "warning" | "error";
|
|
6
6
|
export interface ToolConfigDiagnostic {
|
|
7
|
-
code: "tools.unknownToolId" | "tools.unsupportedLevel" | "tools.unknownProviderKey" | "tools.removedProviderKey" | "tools.providerSanitizeFailed" | "tools.providerValidateFailed" | "tools.invalidProviderValidation";
|
|
7
|
+
code: "tools.unknownToolId" | "tools.unsupportedLevel" | "tools.unplaceableActivation" | "tools.registryUnavailable" | "tools.unknownProviderKey" | "tools.removedProviderKey" | "tools.providerSanitizeFailed" | "tools.providerValidateFailed" | "tools.invalidProviderValidation";
|
|
8
8
|
severity: ToolConfigDiagnosticSeverity;
|
|
9
9
|
path: string;
|
|
10
10
|
message: string;
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { normalizeToolsConfig, } from "./tools-config-normalizer.js";
|
|
2
2
|
import { frameworkErrorFromToolConfigDiagnostics, frameworkErrorFromUnknown, } from "./framework-error.js";
|
|
3
|
-
import { createPackagedToolRegistry } from "./createDefaultToolRegistry.js";
|
|
4
3
|
export function frameworkErrorFromToolConfigValidation(args) {
|
|
5
4
|
if (Array.isArray(args.diagnostics) && args.diagnostics.length > 0) {
|
|
6
5
|
return frameworkErrorFromToolConfigDiagnostics({
|
|
@@ -120,6 +119,20 @@ function collectPlacementDiagnostics(config, toolMap, diagnostics) {
|
|
|
120
119
|
}));
|
|
121
120
|
continue;
|
|
122
121
|
}
|
|
122
|
+
if (tool.activation === "region") {
|
|
123
|
+
// A region capability has no toolbar button, so placing it names a
|
|
124
|
+
// surface that will never render it. Reported at the placement rather
|
|
125
|
+
// than at render time, where the symptom is an absent accommodation and
|
|
126
|
+
// no error.
|
|
127
|
+
diagnostics.push(createDiagnostic({
|
|
128
|
+
code: "tools.unplaceableActivation",
|
|
129
|
+
severity: "error",
|
|
130
|
+
path: `placement.${level}`,
|
|
131
|
+
message: `Tool "${toolId}" renders into a host surface (activation "region") and cannot be placed on the ${level} toolbar. Remove it from placement.${level}; its availability comes from policy plus its content dependency.`,
|
|
132
|
+
toolId,
|
|
133
|
+
}));
|
|
134
|
+
continue;
|
|
135
|
+
}
|
|
123
136
|
const supportsLevel = tool.supportedLevels.includes(level);
|
|
124
137
|
// Leniency policy: section-capable tools are tolerated in item placement.
|
|
125
138
|
// This avoids strict failures for common host config patterns while still
|
|
@@ -204,9 +217,27 @@ function throwValidationError(diagnostics, source) {
|
|
|
204
217
|
export function normalizeAndValidateToolsConfig(input, options = {}) {
|
|
205
218
|
const strictness = normalizeToolConfigStrictness(options.strictness);
|
|
206
219
|
const source = options.source ?? "tools";
|
|
207
|
-
const registryTools = getRegistryToolMap(options.toolRegistry
|
|
220
|
+
const registryTools = getRegistryToolMap(options.toolRegistry);
|
|
208
221
|
const normalized = normalizeToolsConfig(input);
|
|
209
222
|
const diagnostics = [];
|
|
223
|
+
// Tool-id and provider checks need a registry to check against, and every
|
|
224
|
+
// collector below returns early without one. Say so: this package no longer
|
|
225
|
+
// falls back to a packaged registry, so a caller that used to get id
|
|
226
|
+
// validation for free now gets none, and a silent downgrade from "your ids are
|
|
227
|
+
// valid" to "nobody looked" is the kind of change that surfaces as a typo
|
|
228
|
+
// reaching a learner.
|
|
229
|
+
const hasConfiguredTools = Object.values(normalized.placement).some((ids) => ids.length > 0) ||
|
|
230
|
+
Object.keys(normalized.providers).length > 0 ||
|
|
231
|
+
(normalized.policy.allowed?.length ?? 0) > 0 ||
|
|
232
|
+
(normalized.policy.blocked?.length ?? 0) > 0;
|
|
233
|
+
if (registryTools.size === 0 && hasConfiguredTools) {
|
|
234
|
+
diagnostics.push(createDiagnostic({
|
|
235
|
+
code: "tools.registryUnavailable",
|
|
236
|
+
severity: "warning",
|
|
237
|
+
path: "tools",
|
|
238
|
+
message: 'No tool registry was supplied, so tool ids, placement levels and provider config were not validated. Pass `toolRegistry` — for the packaged capability set, `createPackagedToolRegistry()` from "@pie-players/pie-default-tool-loaders".',
|
|
239
|
+
}));
|
|
240
|
+
}
|
|
210
241
|
const hasRemovedTtsKey = Object.hasOwn(normalized.providers, "tts");
|
|
211
242
|
const nextProviders = {
|
|
212
243
|
...(normalized.providers || {}),
|
|
@@ -233,8 +264,17 @@ export function normalizeAndValidateToolsConfig(input, options = {}) {
|
|
|
233
264
|
if (strictness === "warn") {
|
|
234
265
|
emitWarnings(diagnostics, source);
|
|
235
266
|
}
|
|
236
|
-
|
|
237
|
-
|
|
267
|
+
// Severity decides what `strictness: "error"` rejects. Every diagnostic this
|
|
268
|
+
// function raised was `"error"` until `tools.registryUnavailable`, which
|
|
269
|
+
// reports that validation could not run rather than that the config is wrong —
|
|
270
|
+
// throwing on it would turn "no registry supplied" from a host's existing,
|
|
271
|
+
// working setup into a construction failure.
|
|
272
|
+
const blocking = diagnostics.filter((entry) => entry.severity === "error");
|
|
273
|
+
if (strictness === "error" && blocking.length > 0) {
|
|
274
|
+
throwValidationError(blocking, source);
|
|
275
|
+
}
|
|
276
|
+
if (strictness === "error" && blocking.length === 0) {
|
|
277
|
+
emitWarnings(diagnostics, source);
|
|
238
278
|
}
|
|
239
279
|
return {
|
|
240
280
|
config: nextConfig,
|