@pie-players/pie-assessment-toolkit 0.3.74 → 1.0.0-beta.0
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 +658 -714
- package/custom-elements.json +1315 -0
- package/dist/attempt/TestSession.d.ts +1 -21
- package/dist/attempt/TestSession.js +16 -102
- package/dist/components/ItemScope.custom-element.d.ts +1 -0
- package/dist/components/ItemScope.custom-element.js +1 -0
- package/dist/components/ItemToolBar.custom-element.js +1 -1
- package/dist/components/PieAssessmentToolkit.custom-element.js +14 -14
- package/dist/components/SectionToolBar.custom-element.js +1 -1
- package/dist/components/chunks/ItemToolBar-3zrc4p3d.js +4 -0
- package/dist/components/chunks/ItemToolBar-66hcwmfw.js +2 -0
- package/dist/components/chunks/ItemToolBar-9gqhfxtn.js +40 -0
- package/dist/components/chunks/ItemToolBar-hzc5wyjp.js +2 -0
- package/dist/components/chunks/{ItemToolBar-gmrryv2v.js → ItemToolBar-kkj69ptr.js} +1 -1
- package/dist/components/chunks/ItemToolBar-vdkyn9f3.js +2 -0
- package/dist/components/chunks/sre-engine-bj997w4b.js +1 -0
- package/dist/components/item-scope-element.d.ts +2 -0
- package/dist/components/item-scope-element.js +2 -0
- package/dist/context/assessment-toolkit-context.d.ts +33 -6
- package/dist/index.d.ts +25 -50
- package/dist/index.js +15 -45
- package/dist/policy/core/PolicySource.d.ts +2 -2
- package/dist/policy/core/ToolPolicyEngine.d.ts +118 -34
- package/dist/policy/core/ToolPolicyEngine.js +203 -56
- package/dist/policy/core/compose-decision.d.ts +28 -7
- package/dist/policy/core/compose-decision.js +95 -74
- package/dist/policy/core/decision-types.d.ts +98 -55
- package/dist/policy/core/feature-decision.d.ts +28 -19
- package/dist/policy/core/feature-decision.js +15 -11
- package/dist/policy/core/pnp-policy-inputs.d.ts +29 -35
- package/dist/policy/core/pnp-policy-inputs.js +40 -88
- package/dist/policy/core/provenance.d.ts +10 -5
- package/dist/policy/core/provenance.js +1 -1
- package/dist/policy/core/tool-parameters.d.ts +11 -0
- package/dist/policy/core/tool-parameters.js +15 -0
- package/dist/policy/engine.d.ts +7 -23
- package/dist/policy/engine.js +5 -20
- package/dist/policy/sources/PnpPolicySource.d.ts +43 -68
- package/dist/policy/sources/PnpPolicySource.js +133 -132
- package/dist/runtime/SectionControllerBinding.d.ts +283 -0
- package/dist/runtime/SectionControllerBinding.js +456 -0
- package/dist/runtime/SectionRuntimeEngine.d.ts +26 -289
- package/dist/runtime/SectionRuntimeEngine.js +30 -372
- package/dist/runtime/adapter/SectionEngineAdapter.d.ts +19 -80
- package/dist/runtime/adapter/SectionEngineAdapter.js +19 -92
- package/dist/runtime/adapter/dom-event-bridge.d.ts +15 -30
- package/dist/runtime/adapter/dom-event-bridge.js +17 -44
- package/dist/runtime/adapter/subscriber-fanout.d.ts +1 -3
- package/dist/runtime/adapter/subscriber-fanout.js +2 -6
- package/dist/runtime/catalog-context.d.ts +19 -0
- package/dist/runtime/catalog-context.js +28 -0
- package/dist/runtime/composition-emit-scheduler.d.ts +12 -18
- package/dist/runtime/composition-emit-scheduler.js +10 -16
- package/dist/runtime/content-language.d.ts +32 -0
- package/dist/runtime/content-language.js +46 -0
- package/dist/runtime/content-region.d.ts +13 -0
- package/dist/runtime/content-region.js +29 -0
- package/dist/runtime/content-registration.d.ts +13 -0
- package/dist/runtime/content-registration.js +25 -0
- package/dist/runtime/core/SectionEngineCore.d.ts +2 -4
- package/dist/runtime/core/SectionEngineCore.js +2 -6
- package/dist/runtime/core/cohort.d.ts +1 -6
- package/dist/runtime/core/cohort.js +1 -10
- package/dist/runtime/core/engine-input.d.ts +18 -30
- package/dist/runtime/core/engine-input.js +11 -12
- package/dist/runtime/core/engine-output.d.ts +17 -40
- package/dist/runtime/core/engine-output.js +9 -21
- package/dist/runtime/core/engine-readiness.d.ts +5 -37
- package/dist/runtime/core/engine-readiness.js +8 -41
- package/dist/runtime/core/engine-resolver.d.ts +46 -74
- package/dist/runtime/core/engine-resolver.js +18 -43
- package/dist/runtime/core/engine-state.d.ts +28 -36
- package/dist/runtime/core/engine-state.js +18 -21
- package/dist/runtime/core/engine-transition.d.ts +14 -19
- package/dist/runtime/core/engine-transition.js +74 -53
- package/dist/runtime/engine.d.ts +16 -19
- package/dist/runtime/engine.js +12 -19
- package/dist/runtime/page-warnings.d.ts +13 -0
- package/dist/runtime/page-warnings.js +22 -0
- package/dist/runtime/policy-input-forwarding.d.ts +25 -0
- package/dist/runtime/policy-input-forwarding.js +25 -0
- package/dist/runtime/registration-events.d.ts +22 -14
- package/dist/runtime/runtime-event-claim.d.ts +8 -0
- package/dist/runtime/runtime-event-claim.js +15 -0
- package/dist/runtime/runtime-id.d.ts +1 -1
- package/dist/runtime/runtime-id.js +1 -1
- package/dist/runtime/shell-event-bridge.d.ts +45 -0
- package/dist/runtime/shell-event-bridge.js +127 -0
- package/dist/runtime/shell-registration.d.ts +73 -0
- package/dist/runtime/shell-registration.js +95 -0
- package/dist/runtime/shell-scope.d.ts +68 -0
- package/dist/runtime/shell-scope.js +194 -0
- package/dist/runtime/tool-host-contract.d.ts +8 -14
- package/dist/runtime/tool-host-contract.js +12 -12
- package/dist/runtime/unclaimed-registration-watch.d.ts +7 -0
- package/dist/runtime/unclaimed-registration-watch.js +23 -0
- package/dist/services/AccessibilityCatalogResolver.d.ts +21 -31
- package/dist/services/AccessibilityCatalogResolver.js +29 -42
- package/dist/services/ElementToolStateStore.d.ts +42 -67
- package/dist/services/ElementToolStateStore.js +65 -71
- package/dist/services/HighlightCoordinator.d.ts +28 -40
- package/dist/services/HighlightCoordinator.js +459 -381
- package/dist/services/RangeSerializer.d.ts +11 -33
- package/dist/services/RangeSerializer.js +88 -59
- package/dist/services/SSMLExtractor.d.ts +8 -31
- package/dist/services/SSMLExtractor.js +18 -40
- package/dist/services/TTSService.d.ts +159 -119
- package/dist/services/TTSService.js +937 -822
- package/dist/services/ToolCoordinator.d.ts +42 -102
- package/dist/services/ToolCoordinator.js +178 -256
- package/dist/services/ToolRegistry.d.ts +152 -133
- package/dist/services/ToolRegistry.js +192 -178
- package/dist/services/ToolkitCoordinator.d.ts +233 -237
- package/dist/services/ToolkitCoordinator.js +615 -557
- package/dist/services/audio-handoff.d.ts +6 -7
- package/dist/services/audio-handoff.js +20 -14
- package/dist/services/catalog-owner.d.ts +0 -1
- package/dist/services/framework-error-bus.d.ts +3 -6
- package/dist/services/framework-error-bus.js +3 -6
- package/dist/services/framework-error.d.ts +51 -13
- package/dist/services/framework-error.js +19 -20
- package/dist/services/interfaces.d.ts +189 -184
- package/dist/services/section-controller-types.d.ts +7 -7
- package/dist/services/section-session-assignment.d.ts +21 -0
- package/dist/services/section-session-assignment.js +80 -0
- package/dist/services/spoken-audio-cards.d.ts +2 -6
- package/dist/services/spoken-audio-cards.js +2 -6
- package/dist/services/tool-config-defaults.d.ts +3 -3
- package/dist/services/tool-config-defaults.js +3 -3
- package/dist/services/tool-config-validation.d.ts +9 -12
- package/dist/services/tool-config-validation.js +47 -87
- package/dist/services/tool-context.d.ts +7 -31
- package/dist/services/tool-context.js +99 -65
- package/dist/services/tool-failure.d.ts +30 -0
- package/dist/services/tool-failure.js +11 -0
- package/dist/services/tool-icons.d.ts +5 -5
- package/dist/services/tool-icons.js +6 -5
- package/dist/services/tool-instance-id.d.ts +8 -7
- package/dist/services/tool-instance-id.js +12 -24
- package/dist/services/tool-providers/TTSToolProvider.d.ts +20 -58
- package/dist/services/tool-providers/TTSToolProvider.js +32 -85
- package/dist/services/tool-providers/ToolProviderApi.d.ts +10 -11
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts +29 -60
- package/dist/services/tool-providers/ToolProviderRegistry.js +128 -144
- package/dist/services/tool-request.d.ts +31 -12
- package/dist/services/tool-request.js +31 -16
- package/dist/services/toolbar-decided-tools.d.ts +16 -0
- package/dist/services/toolbar-decided-tools.js +29 -0
- package/dist/services/toolbar-items.js +2 -5
- package/dist/services/tools-config-normalizer.d.ts +33 -29
- package/dist/services/tools-config-normalizer.js +26 -28
- package/dist/services/tts/browser-provider.d.ts +39 -6
- package/dist/services/tts/browser-provider.js +280 -160
- package/dist/services/tts/catalog-span-alignment.js +14 -7
- package/dist/services/tts/flat-tree.d.ts +64 -0
- package/dist/services/tts/flat-tree.js +269 -0
- package/dist/services/tts/generated-speech/assemble-plan.d.ts +3 -1
- package/dist/services/tts/generated-speech/assemble-plan.js +3 -1
- package/dist/services/tts/generated-speech/dom/build-dom-plan.d.ts +2 -0
- package/dist/services/tts/generated-speech/dom/build-dom-plan.js +1 -1
- package/dist/services/tts/generated-speech/dom/to-chunk-inputs.d.ts +2 -2
- package/dist/services/tts/generated-speech/index.d.ts +1 -1
- package/dist/services/tts/generated-speech/index.js +1 -1
- package/dist/services/tts/generated-speech/math-speech-cache.d.ts +3 -1
- package/dist/services/tts/generated-speech/math-speech-cache.js +5 -1
- package/dist/services/tts/generated-speech/types.d.ts +1 -1
- package/dist/services/tts/generated-speech/types.js +1 -1
- package/dist/services/tts/highlight-pipeline/create-highlight-plan.js +22 -16
- package/dist/services/tts/highlight-pipeline/prose-boundary-resolver.js +6 -4
- package/dist/services/tts/highlight-pipeline/readable-region.js +3 -2
- package/dist/services/tts/highlight-pipeline/types.d.ts +5 -0
- package/dist/services/tts/highlight-pipeline/visible-map-range.d.ts +12 -0
- package/dist/services/tts/highlight-pipeline/visible-map-range.js +73 -7
- package/dist/services/tts/highlight-target-resolver.d.ts +12 -0
- package/dist/services/tts/math-aware-text-processing.d.ts +5 -1
- package/dist/services/tts/math-aware-text-processing.js +42 -47
- package/dist/services/tts/math-control-names.d.ts +21 -0
- package/dist/services/tts/math-control-names.js +142 -0
- package/dist/services/tts/math-speech.d.ts +12 -1
- package/dist/services/tts/math-speech.js +54 -18
- package/dist/services/tts/mathml-sanitization.d.ts +7 -0
- package/dist/services/tts/mathml-sanitization.js +9 -1
- package/dist/services/tts/provider-options.d.ts +52 -0
- package/dist/services/tts/provider-options.js +1 -0
- package/dist/services/tts/ssml/spoken-text.d.ts +2 -26
- package/dist/services/tts/ssml/spoken-text.js +29 -0
- package/dist/services/tts/start-failure.d.ts +4 -0
- package/dist/services/tts/start-failure.js +19 -0
- package/dist/services/tts/text-processing.d.ts +9 -0
- package/dist/services/tts/text-processing.js +46 -33
- package/dist/services/tts/text-segmentation.d.ts +12 -0
- package/dist/services/tts/text-segmentation.js +60 -10
- package/dist/services/tts-runtime-config.d.ts +54 -26
- package/dist/services/tts-runtime-config.js +27 -112
- package/dist/tools/content-capability-resolution.d.ts +9 -11
- package/dist/tools/content-capability-resolution.js +8 -45
- package/dist/tools/registration.d.ts +59 -0
- package/dist/tools/registration.js +55 -0
- package/dist/tools/registrations/toolbar-registration-helpers.d.ts +6 -0
- package/dist/tools/registrations/toolbar-registration-helpers.js +8 -2
- package/dist/tools/tool-surface-host.d.ts +6 -10
- package/dist/tools/tool-surface-host.js +45 -50
- package/dist/tools/tool-tag-map.d.ts +5 -15
- package/dist/tools/tool-tag-map.js +6 -20
- package/dist/utils/structural-equality.d.ts +11 -0
- package/dist/utils/structural-equality.js +47 -0
- package/package.json +15 -29
- package/dist/attempt/adapters/activity-to-test-attempt-session.d.ts +0 -49
- package/dist/attempt/adapters/activity-to-test-attempt-session.js +0 -138
- package/dist/components/chunks/ItemToolBar-b9dz5jvd.js +0 -40
- package/dist/components/chunks/ItemToolBar-h4xap0t0.js +0 -4
- package/dist/components/chunks/ItemToolBar-wr2myaah.js +0 -2
- package/dist/components/chunks/sre-engine-wf9s43gg.js +0 -1
- package/dist/context/runtime-context-consumer.d.ts +0 -13
- package/dist/context/runtime-context-consumer.js +0 -18
- package/dist/item-loader.d.ts +0 -44
- package/dist/item-loader.js +0 -61
- package/dist/policy/core/engine-context.d.ts +0 -29
- package/dist/policy/core/engine-context.js +0 -27
- package/dist/policy/core/policy-source-tag.d.ts +0 -31
- package/dist/policy/core/policy-source-tag.js +0 -28
- package/dist/policy/internal.d.ts +0 -25
- package/dist/policy/internal.js +0 -25
- package/dist/runtime/adapter/coordinator-bridge.d.ts +0 -92
- package/dist/runtime/adapter/coordinator-bridge.js +0 -126
- package/dist/runtime/adapter/framework-error-bridge.d.ts +0 -36
- package/dist/runtime/adapter/framework-error-bridge.js +0 -46
- package/dist/runtime/adapter/instrumentation-bridge.d.ts +0 -31
- package/dist/runtime/adapter/instrumentation-bridge.js +0 -38
- package/dist/runtime/core/engine-stage-derivation.d.ts +0 -18
- package/dist/runtime/core/engine-stage-derivation.js +0 -29
- package/dist/runtime/engine-context.d.ts +0 -39
- package/dist/runtime/engine-context.js +0 -31
- package/dist/runtime/internal.d.ts +0 -43
- package/dist/runtime/internal.js +0 -45
- package/dist/runtime/section-runtime-engine-host-context.d.ts +0 -74
- package/dist/runtime/section-runtime-engine-host-context.js +0 -57
- package/dist/runtime/stage-emit-gate.d.ts +0 -92
- package/dist/runtime/stage-emit-gate.js +0 -82
- package/dist/services/ContextVariableStore.d.ts +0 -113
- package/dist/services/ContextVariableStore.js +0 -206
- package/dist/services/I18nService.d.ts +0 -47
- package/dist/services/I18nService.js +0 -84
- package/dist/services/ThemeProvider.d.ts +0 -95
- package/dist/services/ThemeProvider.js +0 -334
- package/dist/services/defaultPersonalNeedsProfile.d.ts +0 -21
- package/dist/services/defaultPersonalNeedsProfile.js +0 -26
- package/dist/services/pnp-standard-features.d.ts +0 -238
- package/dist/services/pnp-standard-features.js +0 -338
- package/dist/services/tts-control-events.d.ts +0 -13
- package/dist/services/tts-control-events.js +0 -7
- package/dist/tools/client.d.ts +0 -10
- package/dist/tools/client.js +0 -10
- package/dist/tools/internal.d.ts +0 -44
- package/dist/tools/internal.js +0 -39
- package/dist/utils/logger.d.ts +0 -6
- package/dist/utils/logger.js +0 -10
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A host-assigned section session, resolved against the session a live
|
|
3
|
+
* controller already holds.
|
|
4
|
+
*
|
|
5
|
+
* The rules are the ones `ItemController.setSession` applies to one item:
|
|
6
|
+
* - a value whose content equals the current session is a no-op, so echoing a
|
|
7
|
+
* snapshot back into the `session` property applies nothing;
|
|
8
|
+
* - an item session with neither a response value nor a response field leaves
|
|
9
|
+
* an item session that holds responses in place. The embedded item player
|
|
10
|
+
* applies the same rule when the section hands the session down, so applying
|
|
11
|
+
* it at section level keeps the controller and its item players from
|
|
12
|
+
* diverging.
|
|
13
|
+
*
|
|
14
|
+
* A controller that holds no session yet takes the value as assigned.
|
|
15
|
+
*/
|
|
16
|
+
import { hasResponseField, hasResponseValue, } from "@pie-players/pie-players-shared/pie";
|
|
17
|
+
import { structurallyEqual } from "../utils/structural-equality.js";
|
|
18
|
+
import { isPlainRecord } from "@pie-players/pie-players-shared/object";
|
|
19
|
+
/** An entry is canonical (`{ itemIdentifier, session, ... }`) or the raw item session. */
|
|
20
|
+
function itemSessionOf(entry) {
|
|
21
|
+
return isPlainRecord(entry) && isPlainRecord(entry.session) ? entry.session : entry;
|
|
22
|
+
}
|
|
23
|
+
function sameItemSessions(next, current) {
|
|
24
|
+
const nextSessions = isPlainRecord(next) ? next : {};
|
|
25
|
+
const currentSessions = isPlainRecord(current) ? current : {};
|
|
26
|
+
const itemIds = new Set([
|
|
27
|
+
...Object.keys(nextSessions),
|
|
28
|
+
...Object.keys(currentSessions),
|
|
29
|
+
]);
|
|
30
|
+
for (const itemId of itemIds) {
|
|
31
|
+
if (!structurallyEqual(itemSessionOf(nextSessions[itemId]), itemSessionOf(currentSessions[itemId]))) {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return true;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Whether applying `next` would leave `current` as it is. A field `next` leaves
|
|
39
|
+
* out is unchanged, and item sessions compare by their session payload, so a
|
|
40
|
+
* raw `{ id, data }` matches the canonical entry the controller stored for it.
|
|
41
|
+
*/
|
|
42
|
+
function sameSessionContent(next, current) {
|
|
43
|
+
for (const [key, value] of Object.entries(next)) {
|
|
44
|
+
if (value === undefined)
|
|
45
|
+
continue;
|
|
46
|
+
if (key === "itemSessions") {
|
|
47
|
+
if (!sameItemSessions(value, current.itemSessions))
|
|
48
|
+
return false;
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
if (!structurallyEqual(value, current[key])) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
return true;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* The session to apply in replace mode, or `null` when applying `next` would
|
|
59
|
+
* change nothing.
|
|
60
|
+
*/
|
|
61
|
+
export function resolveSectionSessionAssignment(current, next) {
|
|
62
|
+
if (!current)
|
|
63
|
+
return next;
|
|
64
|
+
const itemSessions = isPlainRecord(next.itemSessions)
|
|
65
|
+
? { ...next.itemSessions }
|
|
66
|
+
: {};
|
|
67
|
+
const currentItemSessions = isPlainRecord(current.itemSessions)
|
|
68
|
+
? current.itemSessions
|
|
69
|
+
: {};
|
|
70
|
+
for (const [itemId, currentEntry] of Object.entries(currentItemSessions)) {
|
|
71
|
+
if (!hasResponseValue(itemSessionOf(currentEntry)))
|
|
72
|
+
continue;
|
|
73
|
+
const assigned = itemSessionOf(itemSessions[itemId]);
|
|
74
|
+
if (hasResponseValue(assigned) || hasResponseField(assigned))
|
|
75
|
+
continue;
|
|
76
|
+
itemSessions[itemId] = currentEntry;
|
|
77
|
+
}
|
|
78
|
+
const resolved = { ...next, itemSessions };
|
|
79
|
+
return sameSessionContent(resolved, current) ? null : resolved;
|
|
80
|
+
}
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* QTI 3 treats a recording and synthesized speech as the *same* support — both
|
|
5
5
|
* are `spoken`, and a card carries recorded audio through `qti-file-href` plus a
|
|
6
|
-
* MIME type — so
|
|
7
|
-
*
|
|
6
|
+
* MIME type — so a recording is the other form the existing support takes.
|
|
7
|
+
* Some programs prefer a human voice to synthesis; PIE's `spoken`
|
|
8
8
|
* card was string-only, so it had no way to say "play this file for this node".
|
|
9
9
|
*
|
|
10
10
|
* A node commonly carries both forms in the same language: the reading script
|
|
@@ -17,12 +17,8 @@
|
|
|
17
17
|
* Validation posture matches sign-language cards: "treat as absent, never as
|
|
18
18
|
* partially valid". A malformed payload must not produce a silent player that
|
|
19
19
|
* looks like read-aloud is working.
|
|
20
|
-
*
|
|
21
|
-
* Part of PIE Assessment Toolkit.
|
|
22
20
|
*/
|
|
23
21
|
import type { CatalogCardPayload, MediaFragmentRange, MediaSource } from "@pie-players/pie-players-shared/types";
|
|
24
|
-
/** Catalog type token for spoken alternates. Matches QTI 3's `support` value. */
|
|
25
|
-
export declare const SPOKEN_CATALOG_TYPE = "spoken";
|
|
26
22
|
/** A validated recorded spoken alternate, flattened for playback. */
|
|
27
23
|
export interface SpokenAudioMedia {
|
|
28
24
|
/**
|
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
*
|
|
4
4
|
* QTI 3 treats a recording and synthesized speech as the *same* support — both
|
|
5
5
|
* are `spoken`, and a card carries recorded audio through `qti-file-href` plus a
|
|
6
|
-
* MIME type — so
|
|
7
|
-
*
|
|
6
|
+
* MIME type — so a recording is the other form the existing support takes.
|
|
7
|
+
* Some programs prefer a human voice to synthesis; PIE's `spoken`
|
|
8
8
|
* card was string-only, so it had no way to say "play this file for this node".
|
|
9
9
|
*
|
|
10
10
|
* A node commonly carries both forms in the same language: the reading script
|
|
@@ -17,12 +17,8 @@
|
|
|
17
17
|
* Validation posture matches sign-language cards: "treat as absent, never as
|
|
18
18
|
* partially valid". A malformed payload must not produce a silent player that
|
|
19
19
|
* looks like read-aloud is working.
|
|
20
|
-
*
|
|
21
|
-
* Part of PIE Assessment Toolkit.
|
|
22
20
|
*/
|
|
23
21
|
import { isUnsupportedMediaAssetVersion, normalizeMediaFragment, normalizeMediaSources, trimmedOrUndefined, } from "@pie-players/pie-players-shared/media";
|
|
24
|
-
/** Catalog type token for spoken alternates. Matches QTI 3's `support` value. */
|
|
25
|
-
export const SPOKEN_CATALOG_TYPE = "spoken";
|
|
26
22
|
/**
|
|
27
23
|
* Validate a `spoken` card's payload into something playable, or `null`.
|
|
28
24
|
*
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Placement defaults this package can hold.
|
|
3
3
|
*
|
|
4
|
-
* Only the empty one. `
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Only the empty one. `SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT` names
|
|
5
|
+
* capabilities, so it lives in the composition layer
|
|
6
|
+
* (`@pie-players/pie-default-tool-loaders`).
|
|
7
7
|
*/
|
|
8
8
|
export declare const DEFAULT_TOOL_PLACEMENT: {
|
|
9
9
|
readonly assessment: readonly [];
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Placement defaults this package can hold.
|
|
3
3
|
*
|
|
4
|
-
* Only the empty one. `
|
|
5
|
-
*
|
|
6
|
-
*
|
|
4
|
+
* Only the empty one. `SECTION_PLAYER_PREFERRED_TOOL_PLACEMENT` names
|
|
5
|
+
* capabilities, so it lives in the composition layer
|
|
6
|
+
* (`@pie-players/pie-default-tool-loaders`).
|
|
7
7
|
*/
|
|
8
8
|
export const DEFAULT_TOOL_PLACEMENT = {
|
|
9
9
|
assessment: [],
|
|
@@ -1,15 +1,13 @@
|
|
|
1
1
|
import { type CanonicalToolsConfig, type ToolsConfigInput } from "./tools-config-normalizer.js";
|
|
2
|
-
import { type FrameworkErrorModel } from "./framework-error.js";
|
|
3
2
|
import type { ToolRegistry } from "./ToolRegistry.js";
|
|
4
3
|
export type ToolConfigStrictness = "off" | "warn" | "error";
|
|
5
4
|
export type ToolConfigDiagnosticSeverity = "warning" | "error";
|
|
6
5
|
export interface ToolConfigDiagnostic {
|
|
7
|
-
code: "tools.unknownToolId" | "tools.unsupportedLevel" | "tools.unplaceableActivation" | "tools.registryUnavailable" | "tools.unknownProviderKey" | "tools.
|
|
6
|
+
code: "tools.unknownToolId" | "tools.unsupportedLevel" | "tools.unplaceableActivation" | "tools.registryUnavailable" | "tools.unknownProviderKey" | "tools.providerSanitizeFailed" | "tools.providerValidateFailed" | "tools.invalidProviderValidation";
|
|
8
7
|
severity: ToolConfigDiagnosticSeverity;
|
|
9
8
|
path: string;
|
|
10
9
|
message: string;
|
|
11
10
|
toolId?: string;
|
|
12
|
-
providerId?: string;
|
|
13
11
|
}
|
|
14
12
|
export interface ToolConfigValidationOptions {
|
|
15
13
|
strictness?: ToolConfigStrictness;
|
|
@@ -20,13 +18,12 @@ export interface ToolConfigValidationResult {
|
|
|
20
18
|
config: CanonicalToolsConfig;
|
|
21
19
|
diagnostics: ToolConfigDiagnostic[];
|
|
22
20
|
}
|
|
23
|
-
export declare function frameworkErrorFromToolConfigValidation(args: {
|
|
24
|
-
source: string;
|
|
25
|
-
diagnostics?: ToolConfigDiagnostic[] | null;
|
|
26
|
-
error?: unknown;
|
|
27
|
-
recoverable?: boolean;
|
|
28
|
-
}): FrameworkErrorModel;
|
|
29
21
|
export declare function normalizeToolConfigStrictness(value: unknown): ToolConfigStrictness;
|
|
22
|
+
/**
|
|
23
|
+
* Normalize a tools config, sanitize and validate each provider entry with its
|
|
24
|
+
* registration's hooks, check ids and levels against `options.toolRegistry`,
|
|
25
|
+
* and report the diagnostics by `options.strictness` (default `"error"`).
|
|
26
|
+
*/
|
|
30
27
|
export declare function normalizeAndValidateToolsConfig(input?: ToolsConfigInput | null, options?: ToolConfigValidationOptions): ToolConfigValidationResult;
|
|
31
28
|
/**
|
|
32
29
|
* The normalization and diagnostics of {@link normalizeAndValidateToolsConfig},
|
|
@@ -34,8 +31,8 @@ export declare function normalizeAndValidateToolsConfig(input?: ToolsConfigInput
|
|
|
34
31
|
*/
|
|
35
32
|
export declare function collectToolConfigDiagnostics(input: ToolsConfigInput | null | undefined, toolRegistry: ToolRegistry | null | undefined): ToolConfigValidationResult;
|
|
36
33
|
/**
|
|
37
|
-
* Report diagnostics as {@link normalizeAndValidateToolsConfig} does:
|
|
38
|
-
*
|
|
39
|
-
*
|
|
34
|
+
* Report diagnostics as {@link normalizeAndValidateToolsConfig} does: `"warn"`
|
|
35
|
+
* prints every diagnostic, and `"error"` throws the blocking ones or, when there
|
|
36
|
+
* are none, prints the rest.
|
|
40
37
|
*/
|
|
41
38
|
export declare function reportToolConfigDiagnostics(diagnostics: ToolConfigDiagnostic[], options?: Pick<ToolConfigValidationOptions, "strictness" | "source">): void;
|
|
@@ -1,20 +1,4 @@
|
|
|
1
1
|
import { normalizeToolsConfig, } from "./tools-config-normalizer.js";
|
|
2
|
-
import { frameworkErrorFromToolConfigDiagnostics, frameworkErrorFromUnknown, } from "./framework-error.js";
|
|
3
|
-
export function frameworkErrorFromToolConfigValidation(args) {
|
|
4
|
-
if (Array.isArray(args.diagnostics) && args.diagnostics.length > 0) {
|
|
5
|
-
return frameworkErrorFromToolConfigDiagnostics({
|
|
6
|
-
source: args.source,
|
|
7
|
-
diagnostics: args.diagnostics,
|
|
8
|
-
recoverable: args.recoverable,
|
|
9
|
-
});
|
|
10
|
-
}
|
|
11
|
-
return frameworkErrorFromUnknown({
|
|
12
|
-
kind: "tool-config",
|
|
13
|
-
source: args.source,
|
|
14
|
-
error: args.error ?? new Error("Invalid tools config"),
|
|
15
|
-
recoverable: args.recoverable,
|
|
16
|
-
});
|
|
17
|
-
}
|
|
18
2
|
const DEFAULT_STRICTNESS = "error";
|
|
19
3
|
export function normalizeToolConfigStrictness(value) {
|
|
20
4
|
if (value === "off" || value === "warn" || value === "error") {
|
|
@@ -34,21 +18,20 @@ function getRegistryToolMap(toolRegistry) {
|
|
|
34
18
|
.sort((left, right) => left.toolId.localeCompare(right.toolId))
|
|
35
19
|
.map((tool) => [tool.toolId, tool]));
|
|
36
20
|
}
|
|
37
|
-
function
|
|
38
|
-
if (!providerConfig || !tool?.
|
|
21
|
+
function sanitizeToolConfig(toolId, providerConfig, tool, diagnostics) {
|
|
22
|
+
if (!providerConfig || !tool?.sanitizeConfig)
|
|
39
23
|
return providerConfig;
|
|
40
24
|
try {
|
|
41
|
-
const sanitized = tool.
|
|
25
|
+
const sanitized = tool.sanitizeConfig(providerConfig);
|
|
42
26
|
if (!sanitized ||
|
|
43
27
|
typeof sanitized !== "object" ||
|
|
44
28
|
Array.isArray(sanitized)) {
|
|
45
29
|
diagnostics.push(createDiagnostic({
|
|
46
30
|
code: "tools.providerSanitizeFailed",
|
|
47
31
|
severity: "error",
|
|
48
|
-
path: `providers.${
|
|
49
|
-
message: `
|
|
50
|
-
|
|
51
|
-
toolId: providerId,
|
|
32
|
+
path: `providers.${toolId}`,
|
|
33
|
+
message: `Config sanitizer of tool "${toolId}" must return an object.`,
|
|
34
|
+
toolId,
|
|
52
35
|
}));
|
|
53
36
|
return providerConfig;
|
|
54
37
|
}
|
|
@@ -58,36 +41,33 @@ function sanitizeProviderConfig(providerId, providerConfig, tool, diagnostics) {
|
|
|
58
41
|
diagnostics.push(createDiagnostic({
|
|
59
42
|
code: "tools.providerSanitizeFailed",
|
|
60
43
|
severity: "error",
|
|
61
|
-
path: `providers.${
|
|
62
|
-
message: `
|
|
63
|
-
|
|
64
|
-
toolId: providerId,
|
|
44
|
+
path: `providers.${toolId}`,
|
|
45
|
+
message: `Config sanitizer of tool "${toolId}" failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
46
|
+
toolId,
|
|
65
47
|
}));
|
|
66
48
|
return providerConfig;
|
|
67
49
|
}
|
|
68
50
|
}
|
|
69
|
-
function
|
|
70
|
-
if (!providerConfig || !tool?.
|
|
51
|
+
function validateToolConfig(toolId, providerConfig, tool, diagnostics) {
|
|
52
|
+
if (!providerConfig || !tool?.validateConfig)
|
|
71
53
|
return;
|
|
72
54
|
try {
|
|
73
|
-
const
|
|
74
|
-
if (!Array.isArray(
|
|
55
|
+
const toolDiagnostics = tool.validateConfig(providerConfig);
|
|
56
|
+
if (!Array.isArray(toolDiagnostics)) {
|
|
75
57
|
diagnostics.push(createDiagnostic({
|
|
76
58
|
code: "tools.invalidProviderValidation",
|
|
77
59
|
severity: "error",
|
|
78
|
-
path: `providers.${
|
|
79
|
-
message: `
|
|
80
|
-
|
|
81
|
-
toolId: providerId,
|
|
60
|
+
path: `providers.${toolId}`,
|
|
61
|
+
message: `Config validator of tool "${toolId}" must return an array.`,
|
|
62
|
+
toolId,
|
|
82
63
|
}));
|
|
83
64
|
return;
|
|
84
65
|
}
|
|
85
|
-
for (const diagnostic of
|
|
66
|
+
for (const diagnostic of toolDiagnostics) {
|
|
86
67
|
diagnostics.push({
|
|
87
68
|
...diagnostic,
|
|
88
|
-
path: diagnostic.path || `providers.${
|
|
89
|
-
|
|
90
|
-
toolId: diagnostic.toolId || providerId,
|
|
69
|
+
path: diagnostic.path || `providers.${toolId}`,
|
|
70
|
+
toolId: diagnostic.toolId || toolId,
|
|
91
71
|
});
|
|
92
72
|
}
|
|
93
73
|
}
|
|
@@ -95,10 +75,9 @@ function validateProviderConfig(providerId, providerConfig, tool, diagnostics) {
|
|
|
95
75
|
diagnostics.push(createDiagnostic({
|
|
96
76
|
code: "tools.providerValidateFailed",
|
|
97
77
|
severity: "error",
|
|
98
|
-
path: `providers.${
|
|
99
|
-
message: `
|
|
100
|
-
|
|
101
|
-
toolId: providerId,
|
|
78
|
+
path: `providers.${toolId}`,
|
|
79
|
+
message: `Config validator of tool "${toolId}" failed: ${error instanceof Error ? error.message : String(error)}`,
|
|
80
|
+
toolId,
|
|
102
81
|
}));
|
|
103
82
|
}
|
|
104
83
|
}
|
|
@@ -176,27 +155,16 @@ function collectPolicyDiagnostics(config, toolMap, diagnostics) {
|
|
|
176
155
|
}));
|
|
177
156
|
}
|
|
178
157
|
}
|
|
179
|
-
function collectProviderKeyDiagnostics(config, toolMap,
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
code: "tools.removedProviderKey",
|
|
183
|
-
severity: "error",
|
|
184
|
-
path: "providers.tts",
|
|
185
|
-
message: `Provider key "tts" is no longer supported. Use "providers.textToSpeech".`,
|
|
186
|
-
providerId: "tts",
|
|
187
|
-
toolId: "textToSpeech",
|
|
188
|
-
}));
|
|
189
|
-
}
|
|
190
|
-
for (const providerId of Object.keys(config.providers).sort()) {
|
|
191
|
-
if (toolMap.size === 0 || toolMap.has(providerId))
|
|
158
|
+
function collectProviderKeyDiagnostics(config, toolMap, diagnostics) {
|
|
159
|
+
for (const key of Object.keys(config.providers).sort()) {
|
|
160
|
+
if (toolMap.size === 0 || toolMap.has(key))
|
|
192
161
|
continue;
|
|
193
162
|
diagnostics.push(createDiagnostic({
|
|
194
163
|
code: "tools.unknownProviderKey",
|
|
195
164
|
severity: "error",
|
|
196
|
-
path: `providers.${
|
|
197
|
-
message: `Unknown provider key "${
|
|
198
|
-
|
|
199
|
-
toolId: providerId,
|
|
165
|
+
path: `providers.${key}`,
|
|
166
|
+
message: `Unknown provider key "${key}".`,
|
|
167
|
+
toolId: key,
|
|
200
168
|
}));
|
|
201
169
|
}
|
|
202
170
|
}
|
|
@@ -214,6 +182,11 @@ function throwValidationError(diagnostics, source) {
|
|
|
214
182
|
.join("\n");
|
|
215
183
|
throw new Error(`[tool-config-validation:${source}] Invalid tools config:\n${formatted}`);
|
|
216
184
|
}
|
|
185
|
+
/**
|
|
186
|
+
* Normalize a tools config, sanitize and validate each provider entry with its
|
|
187
|
+
* registration's hooks, check ids and levels against `options.toolRegistry`,
|
|
188
|
+
* and report the diagnostics by `options.strictness` (default `"error"`).
|
|
189
|
+
*/
|
|
217
190
|
export function normalizeAndValidateToolsConfig(input, options = {}) {
|
|
218
191
|
const result = collectToolConfigDiagnostics(input, options.toolRegistry);
|
|
219
192
|
reportToolConfigDiagnostics(result.diagnostics, options);
|
|
@@ -228,11 +201,9 @@ export function collectToolConfigDiagnostics(input, toolRegistry) {
|
|
|
228
201
|
const normalized = normalizeToolsConfig(input);
|
|
229
202
|
const diagnostics = [];
|
|
230
203
|
// Tool-id and provider checks need a registry to check against, and every
|
|
231
|
-
// collector below returns early without one. Say so
|
|
232
|
-
//
|
|
233
|
-
//
|
|
234
|
-
// valid" to "nobody looked" is the kind of change that surfaces as a typo
|
|
235
|
-
// reaching a learner.
|
|
204
|
+
// collector below returns early without one. Say so, since there is no
|
|
205
|
+
// packaged fallback registry: silence would read as "your ids are valid" when
|
|
206
|
+
// nobody looked, and a typo would reach a learner.
|
|
236
207
|
const hasConfiguredTools = Object.values(normalized.placement).some((ids) => ids.length > 0) ||
|
|
237
208
|
Object.keys(normalized.providers).length > 0 ||
|
|
238
209
|
(normalized.policy.allowed?.length ?? 0) > 0 ||
|
|
@@ -245,18 +216,13 @@ export function collectToolConfigDiagnostics(input, toolRegistry) {
|
|
|
245
216
|
message: 'No tool registry was supplied, so tool ids, placement levels and provider config were not validated, and a coordinator without one registers no tool providers. Pass `toolRegistry` to the coordinator or the toolkit it is bound to — for the packaged capability set, `createPackagedToolRegistry()` from "@pie-players/pie-default-tool-loaders".',
|
|
246
217
|
}));
|
|
247
218
|
}
|
|
248
|
-
const hasRemovedTtsKey = Object.hasOwn(normalized.providers, "tts");
|
|
249
219
|
const nextProviders = {
|
|
250
220
|
...(normalized.providers || {}),
|
|
251
221
|
};
|
|
252
|
-
for (const
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
}
|
|
257
|
-
const tool = registryTools.get(providerId);
|
|
258
|
-
nextProviders[providerId] = sanitizeProviderConfig(providerId, nextProviders[providerId], tool, diagnostics);
|
|
259
|
-
validateProviderConfig(providerId, nextProviders[providerId], tool, diagnostics);
|
|
222
|
+
for (const toolId of Object.keys(nextProviders).sort()) {
|
|
223
|
+
const tool = registryTools.get(toolId);
|
|
224
|
+
nextProviders[toolId] = sanitizeToolConfig(toolId, nextProviders[toolId], tool, diagnostics);
|
|
225
|
+
validateToolConfig(toolId, nextProviders[toolId], tool, diagnostics);
|
|
260
226
|
}
|
|
261
227
|
const nextConfig = {
|
|
262
228
|
...normalized,
|
|
@@ -264,32 +230,26 @@ export function collectToolConfigDiagnostics(input, toolRegistry) {
|
|
|
264
230
|
};
|
|
265
231
|
collectPlacementDiagnostics(nextConfig, registryTools, diagnostics);
|
|
266
232
|
collectPolicyDiagnostics(nextConfig, registryTools, diagnostics);
|
|
267
|
-
collectProviderKeyDiagnostics(nextConfig, registryTools,
|
|
233
|
+
collectProviderKeyDiagnostics(nextConfig, registryTools, diagnostics);
|
|
268
234
|
return {
|
|
269
235
|
config: nextConfig,
|
|
270
236
|
diagnostics,
|
|
271
237
|
};
|
|
272
238
|
}
|
|
273
239
|
/**
|
|
274
|
-
* Report diagnostics as {@link normalizeAndValidateToolsConfig} does:
|
|
275
|
-
*
|
|
276
|
-
*
|
|
240
|
+
* Report diagnostics as {@link normalizeAndValidateToolsConfig} does: `"warn"`
|
|
241
|
+
* prints every diagnostic, and `"error"` throws the blocking ones or, when there
|
|
242
|
+
* are none, prints the rest.
|
|
277
243
|
*/
|
|
278
244
|
export function reportToolConfigDiagnostics(diagnostics, options = {}) {
|
|
279
245
|
const strictness = normalizeToolConfigStrictness(options.strictness);
|
|
280
246
|
const source = options.source ?? "tools";
|
|
281
|
-
const removedKeys = diagnostics.filter((entry) => entry.code === "tools.removedProviderKey");
|
|
282
|
-
if (removedKeys.length > 0) {
|
|
283
|
-
throwValidationError(removedKeys, source);
|
|
284
|
-
}
|
|
285
247
|
if (strictness === "warn") {
|
|
286
248
|
emitWarnings(diagnostics, source);
|
|
287
249
|
}
|
|
288
|
-
// Severity decides what `strictness: "error"` rejects.
|
|
289
|
-
//
|
|
290
|
-
//
|
|
291
|
-
// turn "no registry supplied" from a host's existing, working setup into a
|
|
292
|
-
// construction failure.
|
|
250
|
+
// Severity decides what `strictness: "error"` rejects. `tools.registryUnavailable`
|
|
251
|
+
// is a warning: it reports that validation could not run, and throwing on it
|
|
252
|
+
// would fail construction for a host whose setup works without a registry.
|
|
293
253
|
const blocking = diagnostics.filter((entry) => entry.severity === "error");
|
|
294
254
|
if (strictness === "error" && blocking.length > 0) {
|
|
295
255
|
throwValidationError(blocking, source);
|
|
@@ -102,38 +102,9 @@ export interface ElementToolContext extends BaseToolContext {
|
|
|
102
102
|
*/
|
|
103
103
|
export type ToolContext = AssessmentToolContext | SectionToolContext | ItemToolContext | PassageToolContext | RubricToolContext | ElementToolContext;
|
|
104
104
|
/**
|
|
105
|
-
*
|
|
106
|
-
|
|
107
|
-
export declare function isAssessmentContext(context: ToolContext): context is AssessmentToolContext;
|
|
108
|
-
/**
|
|
109
|
-
* Type guard to check if context is at section level
|
|
110
|
-
*/
|
|
111
|
-
export declare function isSectionContext(context: ToolContext): context is SectionToolContext;
|
|
112
|
-
/**
|
|
113
|
-
* Type guard to check if context is at item level
|
|
114
|
-
*/
|
|
115
|
-
export declare function isItemContext(context: ToolContext): context is ItemToolContext;
|
|
116
|
-
/**
|
|
117
|
-
* Type guard to check if context is at passage level
|
|
118
|
-
*/
|
|
119
|
-
export declare function isPassageContext(context: ToolContext): context is PassageToolContext;
|
|
120
|
-
/**
|
|
121
|
-
* Type guard to check if context is at rubric level
|
|
122
|
-
*/
|
|
123
|
-
export declare function isRubricContext(context: ToolContext): context is RubricToolContext;
|
|
124
|
-
/**
|
|
125
|
-
* Type guard to check if context is at element level
|
|
126
|
-
*/
|
|
127
|
-
export declare function isElementContext(context: ToolContext): context is ElementToolContext;
|
|
128
|
-
/** The plain text a context carries, tags removed. */
|
|
129
|
-
export declare function extractTextContent(context: ToolContext): string;
|
|
130
|
-
/**
|
|
131
|
-
* The authored markup a context carries, tags intact.
|
|
132
|
-
*
|
|
133
|
-
* For indicators that live in the markup rather than in the prose — `<math>`
|
|
134
|
-
* above all, whose whole signal is the element name.
|
|
105
|
+
* Helper to check if context contains mathematical content
|
|
106
|
+
* (Basic heuristic - can be overridden by tools)
|
|
135
107
|
*/
|
|
136
|
-
export declare function extractMarkupContent(context: ToolContext): string;
|
|
137
108
|
export declare function hasMathContent(context: ToolContext): boolean;
|
|
138
109
|
/**
|
|
139
110
|
* Helper to check if context contains choice-based interactions
|
|
@@ -143,6 +114,11 @@ export declare function hasChoiceInteraction(context: ToolContext): boolean;
|
|
|
143
114
|
* Helper to check if context contains text that can be read aloud
|
|
144
115
|
*/
|
|
145
116
|
export declare function hasReadableText(context: ToolContext): boolean;
|
|
117
|
+
/**
|
|
118
|
+
* Whether read-aloud has something to read: readable text, or markup carrying
|
|
119
|
+
* a catalog idref, whose spoken card reads for content with no text.
|
|
120
|
+
*/
|
|
121
|
+
export declare function hasSpokenContent(context: ToolContext): boolean;
|
|
146
122
|
/**
|
|
147
123
|
* Helper to check if context contains science content
|
|
148
124
|
* (Basic heuristic - can be overridden by tools)
|