@pie-players/pie-assessment-toolkit 0.3.75 → 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 +449 -541
- package/custom-elements.json +1315 -0
- package/dist/attempt/TestSession.d.ts +0 -1
- package/dist/attempt/TestSession.js +10 -5
- package/dist/components/ItemScope.custom-element.js +1 -1
- package/dist/components/ItemToolBar.custom-element.js +1 -1
- package/dist/components/PieAssessmentToolkit.custom-element.js +8 -8
- package/dist/components/SectionToolBar.custom-element.js +1 -1
- package/dist/components/chunks/{ItemToolBar-7tt7v2xp.js → ItemToolBar-3zrc4p3d.js} +4 -4
- package/dist/components/chunks/{ItemToolBar-jx38w99s.js → ItemToolBar-66hcwmfw.js} +2 -2
- package/dist/components/chunks/ItemToolBar-9gqhfxtn.js +40 -0
- package/dist/components/chunks/ItemToolBar-hzc5wyjp.js +2 -0
- package/dist/components/chunks/{ItemToolBar-97hx60z4.js → ItemToolBar-kkj69ptr.js} +1 -1
- package/dist/components/chunks/sre-engine-bj997w4b.js +1 -0
- package/dist/context/assessment-toolkit-context.d.ts +6 -0
- package/dist/index.d.ts +7 -7
- package/dist/index.js +4 -10
- package/dist/policy/core/PolicySource.d.ts +1 -1
- package/dist/policy/core/ToolPolicyEngine.d.ts +46 -7
- package/dist/policy/core/ToolPolicyEngine.js +73 -16
- package/dist/policy/core/compose-decision.d.ts +3 -3
- package/dist/policy/core/compose-decision.js +30 -30
- package/dist/policy/core/decision-types.d.ts +44 -32
- package/dist/policy/core/feature-decision.d.ts +17 -15
- package/dist/policy/core/feature-decision.js +11 -13
- package/dist/policy/core/pnp-policy-inputs.d.ts +5 -2
- package/dist/policy/core/pnp-policy-inputs.js +12 -32
- package/dist/policy/core/provenance.d.ts +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 +1 -1
- package/dist/policy/sources/PnpPolicySource.d.ts +14 -22
- package/dist/policy/sources/PnpPolicySource.js +30 -28
- package/dist/runtime/SectionControllerBinding.d.ts +6 -2
- package/dist/runtime/SectionControllerBinding.js +21 -15
- package/dist/runtime/adapter/subscriber-fanout.d.ts +0 -1
- package/dist/runtime/adapter/subscriber-fanout.js +1 -4
- package/dist/runtime/composition-emit-scheduler.d.ts +3 -3
- package/dist/runtime/composition-emit-scheduler.js +1 -1
- package/dist/runtime/content-region.d.ts +0 -4
- package/dist/runtime/content-region.js +2 -2
- package/dist/runtime/core/SectionEngineCore.d.ts +0 -2
- package/dist/runtime/core/SectionEngineCore.js +0 -4
- package/dist/runtime/core/cohort.d.ts +0 -5
- package/dist/runtime/core/cohort.js +0 -9
- package/dist/runtime/core/engine-output.d.ts +3 -2
- package/dist/runtime/core/engine-transition.js +3 -2
- package/dist/runtime/registration-events.d.ts +11 -14
- package/dist/runtime/runtime-id.d.ts +1 -1
- package/dist/runtime/runtime-id.js +1 -1
- package/dist/runtime/shell-scope.d.ts +4 -4
- package/dist/runtime/shell-scope.js +15 -9
- package/dist/runtime/tool-host-contract.d.ts +0 -4
- package/dist/runtime/tool-host-contract.js +1 -1
- package/dist/services/AccessibilityCatalogResolver.d.ts +21 -31
- package/dist/services/AccessibilityCatalogResolver.js +29 -42
- package/dist/services/ElementToolStateStore.d.ts +32 -61
- package/dist/services/ElementToolStateStore.js +37 -67
- package/dist/services/HighlightCoordinator.d.ts +9 -21
- package/dist/services/HighlightCoordinator.js +52 -80
- package/dist/services/RangeSerializer.d.ts +4 -35
- package/dist/services/RangeSerializer.js +4 -48
- package/dist/services/SSMLExtractor.d.ts +8 -31
- package/dist/services/SSMLExtractor.js +18 -40
- package/dist/services/TTSService.d.ts +49 -56
- package/dist/services/TTSService.js +308 -283
- package/dist/services/ToolCoordinator.d.ts +6 -49
- package/dist/services/ToolCoordinator.js +25 -61
- package/dist/services/ToolRegistry.d.ts +82 -80
- package/dist/services/ToolRegistry.js +91 -67
- package/dist/services/ToolkitCoordinator.d.ts +83 -81
- package/dist/services/ToolkitCoordinator.js +186 -174
- package/dist/services/framework-error.d.ts +30 -7
- package/dist/services/framework-error.js +10 -13
- package/dist/services/interfaces.d.ts +47 -71
- package/dist/services/section-controller-types.d.ts +7 -7
- package/dist/services/section-session-assignment.js +6 -8
- package/dist/services/spoken-audio-cards.d.ts +2 -4
- package/dist/services/spoken-audio-cards.js +2 -4
- package/dist/services/tool-config-validation.d.ts +5 -7
- package/dist/services/tool-config-validation.js +11 -26
- package/dist/services/tool-context.d.ts +7 -23
- package/dist/services/tool-context.js +99 -53
- package/dist/services/tool-failure.d.ts +30 -0
- package/dist/services/tool-failure.js +11 -0
- package/dist/services/tool-icons.d.ts +1 -2
- package/dist/services/tool-icons.js +2 -2
- package/dist/services/tool-instance-id.d.ts +8 -6
- package/dist/services/tool-instance-id.js +12 -18
- package/dist/services/tool-providers/TTSToolProvider.d.ts +6 -43
- package/dist/services/tool-providers/TTSToolProvider.js +7 -63
- package/dist/services/tool-providers/ToolProviderApi.d.ts +0 -7
- package/dist/services/tool-providers/ToolProviderRegistry.d.ts +7 -42
- package/dist/services/tool-providers/ToolProviderRegistry.js +21 -63
- package/dist/services/tool-request.d.ts +4 -0
- package/dist/services/tool-request.js +7 -2
- package/dist/services/toolbar-decided-tools.d.ts +1 -0
- package/dist/services/toolbar-decided-tools.js +1 -0
- package/dist/services/toolbar-items.js +2 -5
- package/dist/services/tools-config-normalizer.d.ts +18 -9
- package/dist/services/tools-config-normalizer.js +25 -19
- package/dist/services/tts/browser-provider.d.ts +2 -5
- package/dist/services/tts/browser-provider.js +4 -20
- package/dist/services/tts/catalog-span-alignment.js +14 -7
- package/dist/services/tts/flat-tree.d.ts +0 -7
- package/dist/services/tts/flat-tree.js +2 -2
- 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/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 +10 -12
- package/dist/services/tts/highlight-target-resolver.d.ts +12 -0
- package/dist/services/tts/math-aware-text-processing.js +10 -29
- package/dist/services/tts/math-speech.d.ts +1 -1
- package/dist/services/tts/math-speech.js +3 -0
- 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 +12 -1
- package/dist/services/tts/ssml/spoken-text.js +1 -1
- package/dist/services/tts/start-failure.d.ts +0 -7
- package/dist/services/tts/start-failure.js +1 -1
- package/dist/services/tts/text-segmentation.d.ts +5 -0
- package/dist/services/tts/text-segmentation.js +13 -10
- package/dist/services/tts-runtime-config.d.ts +32 -12
- package/dist/services/tts-runtime-config.js +14 -20
- package/dist/tools/content-capability-resolution.d.ts +2 -2
- package/dist/tools/registration.d.ts +6 -5
- package/dist/tools/registration.js +10 -9
- package/dist/tools/registrations/toolbar-registration-helpers.d.ts +6 -0
- package/dist/tools/registrations/toolbar-registration-helpers.js +6 -0
- package/dist/tools/tool-surface-host.js +1 -8
- package/package.json +8 -6
- package/dist/components/chunks/ItemToolBar-bxwyhr5p.js +0 -2
- package/dist/components/chunks/ItemToolBar-rd2bb4p6.js +0 -40
- package/dist/components/chunks/sre-engine-jd8cc08x.js +0 -1
- package/dist/services/ContextVariableStore.d.ts +0 -113
- package/dist/services/ContextVariableStore.js +0 -206
- package/dist/services/tts-control-events.d.ts +0 -13
- package/dist/services/tts-control-events.js +0 -7
- package/dist/utils/logger.d.ts +0 -6
- package/dist/utils/logger.js +0 -10
|
@@ -1,10 +1,25 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { ToolFailurePhase } from "./tool-failure.js";
|
|
2
2
|
export type FrameworkErrorKind = "tool-config" | "runtime-init" | "runtime-dispose" | "coordinator-init" | "provider-init" | "provider-register" | "tts-init" | "tool-state-load" | "tool-state-save" | "section-controller-init" | "section-controller-dispose" | "tool-surface"
|
|
3
3
|
/**
|
|
4
4
|
* A toolbar could not load a tool's module. Recoverable unless policy grants
|
|
5
5
|
* the tool: the toolbar withholds the tool and the assessment goes on.
|
|
6
6
|
*/
|
|
7
7
|
| "tool-module-load"
|
|
8
|
+
/**
|
|
9
|
+
* A toolbar threw opening a requested tool or answering whether it hosts one.
|
|
10
|
+
* Recoverable: the request goes unclaimed or passes the toolbar by.
|
|
11
|
+
*/
|
|
12
|
+
| "tool-request"
|
|
13
|
+
/**
|
|
14
|
+
* A tool registration's relevance check or applicability gate threw.
|
|
15
|
+
* Recoverable: the toolbar applies the answer a missing check would give.
|
|
16
|
+
*/
|
|
17
|
+
| "tool-registration"
|
|
18
|
+
/**
|
|
19
|
+
* A tool could not play, seek or change the rate of speech after it started.
|
|
20
|
+
* Recoverable: the tool stays available and the learner can retry.
|
|
21
|
+
*/
|
|
22
|
+
| "tool-playback"
|
|
8
23
|
/**
|
|
9
24
|
* A timed-media section could not deliver a policy as authored: a media time
|
|
10
25
|
* source missing `canPause` / `canRestrictSeeking` (recoverable — cues still
|
|
@@ -34,6 +49,14 @@ export type FrameworkErrorSeverity = "warning" | "error";
|
|
|
34
49
|
* later section runs on, so readiness stays failed. Set by the report site.
|
|
35
50
|
*/
|
|
36
51
|
export type FrameworkErrorScope = "cohort" | "runtime";
|
|
52
|
+
/**
|
|
53
|
+
* The section a `cohort`-scoped error was reported for. A section can fail after
|
|
54
|
+
* the learner has left it, so a reader holding another section ignores the error.
|
|
55
|
+
*/
|
|
56
|
+
export interface FrameworkErrorCohort {
|
|
57
|
+
sectionId: string;
|
|
58
|
+
attemptId?: string;
|
|
59
|
+
}
|
|
37
60
|
export interface FrameworkErrorModel {
|
|
38
61
|
kind: FrameworkErrorKind;
|
|
39
62
|
severity: FrameworkErrorSeverity;
|
|
@@ -42,6 +65,8 @@ export interface FrameworkErrorModel {
|
|
|
42
65
|
details: string[];
|
|
43
66
|
recoverable: boolean;
|
|
44
67
|
scope: FrameworkErrorScope;
|
|
68
|
+
/** Set on a `cohort`-scoped error whose report site knows its section. */
|
|
69
|
+
cohort?: FrameworkErrorCohort;
|
|
45
70
|
cause?: unknown;
|
|
46
71
|
}
|
|
47
72
|
export declare function toFrameworkErrorModel(args: {
|
|
@@ -53,6 +78,7 @@ export declare function toFrameworkErrorModel(args: {
|
|
|
53
78
|
recoverable?: boolean;
|
|
54
79
|
/** Defaults to `runtime`. */
|
|
55
80
|
scope?: FrameworkErrorScope;
|
|
81
|
+
cohort?: FrameworkErrorCohort;
|
|
56
82
|
cause?: unknown;
|
|
57
83
|
}): FrameworkErrorModel;
|
|
58
84
|
export declare function frameworkErrorFromUnknown(args: {
|
|
@@ -61,6 +87,7 @@ export declare function frameworkErrorFromUnknown(args: {
|
|
|
61
87
|
error: unknown;
|
|
62
88
|
recoverable?: boolean;
|
|
63
89
|
scope?: FrameworkErrorScope;
|
|
90
|
+
cohort?: FrameworkErrorCohort;
|
|
64
91
|
}): FrameworkErrorModel;
|
|
65
92
|
/**
|
|
66
93
|
* Coordinator-side error context shape consumed by
|
|
@@ -73,7 +100,7 @@ export declare function frameworkErrorFromUnknown(args: {
|
|
|
73
100
|
* truth for coordinator code; values of that type satisfy this shape.
|
|
74
101
|
*/
|
|
75
102
|
export interface FrameworkErrorCoordinatorContext {
|
|
76
|
-
phase: "coordinator-ready" | "state-load" | "state-save" | "provider-register" | "provider-init" | "tts-init" | "section-controller-init" | "section-controller-dispose" |
|
|
103
|
+
phase: "coordinator-ready" | "state-load" | "state-save" | "provider-register" | "provider-init" | "tts-init" | "section-controller-init" | "section-controller-dispose" | ToolFailurePhase;
|
|
77
104
|
toolId?: string;
|
|
78
105
|
details?: Record<string, unknown>;
|
|
79
106
|
}
|
|
@@ -95,10 +122,6 @@ export declare function frameworkErrorFromCoordinatorContext(args: {
|
|
|
95
122
|
context: FrameworkErrorCoordinatorContext;
|
|
96
123
|
recoverable?: boolean;
|
|
97
124
|
scope?: FrameworkErrorScope;
|
|
98
|
-
|
|
99
|
-
export declare function frameworkErrorFromToolConfigDiagnostics(args: {
|
|
100
|
-
source: string;
|
|
101
|
-
diagnostics: ToolConfigDiagnostic[];
|
|
102
|
-
recoverable?: boolean;
|
|
125
|
+
cohort?: FrameworkErrorCohort;
|
|
103
126
|
}): FrameworkErrorModel;
|
|
104
127
|
export declare function formatFrameworkErrorForConsole(error: FrameworkErrorModel): string;
|
|
@@ -7,6 +7,7 @@ export function toFrameworkErrorModel(args) {
|
|
|
7
7
|
details: [...(args.details || [])],
|
|
8
8
|
recoverable: args.recoverable === true,
|
|
9
9
|
scope: args.scope ?? "runtime",
|
|
10
|
+
...(args.cohort ? { cohort: { ...args.cohort } } : {}),
|
|
10
11
|
cause: args.cause,
|
|
11
12
|
};
|
|
12
13
|
}
|
|
@@ -20,6 +21,7 @@ export function frameworkErrorFromUnknown(args) {
|
|
|
20
21
|
message,
|
|
21
22
|
recoverable: args.recoverable,
|
|
22
23
|
scope: args.scope,
|
|
24
|
+
cohort: args.cohort,
|
|
23
25
|
cause: args.error,
|
|
24
26
|
});
|
|
25
27
|
}
|
|
@@ -33,6 +35,13 @@ const COORDINATOR_PHASE_TO_KIND = {
|
|
|
33
35
|
"section-controller-init": "section-controller-init",
|
|
34
36
|
"section-controller-dispose": "section-controller-dispose",
|
|
35
37
|
"tool-module-load": "tool-module-load",
|
|
38
|
+
"tool-request-open": "tool-request",
|
|
39
|
+
"tool-request-host-check": "tool-request",
|
|
40
|
+
"tool-visibility": "tool-registration",
|
|
41
|
+
"tool-applicability": "tool-registration",
|
|
42
|
+
"tool-state-load": "tool-state-load",
|
|
43
|
+
"tool-state-save": "tool-state-save",
|
|
44
|
+
"tool-playback": "tool-playback",
|
|
36
45
|
};
|
|
37
46
|
/**
|
|
38
47
|
* Build a {@link FrameworkErrorModel} from a coordinator-side error +
|
|
@@ -58,19 +67,7 @@ export function frameworkErrorFromCoordinatorContext(args) {
|
|
|
58
67
|
error: args.error,
|
|
59
68
|
recoverable: args.recoverable,
|
|
60
69
|
scope: args.scope,
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
export function frameworkErrorFromToolConfigDiagnostics(args) {
|
|
64
|
-
const details = args.diagnostics.map((diagnostic) => `${diagnostic.path}: ${diagnostic.message}`);
|
|
65
|
-
const message = details.length > 0
|
|
66
|
-
? "Invalid tools config."
|
|
67
|
-
: "Invalid tools config (no diagnostics details were provided).";
|
|
68
|
-
return toFrameworkErrorModel({
|
|
69
|
-
kind: "tool-config",
|
|
70
|
-
source: args.source,
|
|
71
|
-
message,
|
|
72
|
-
details,
|
|
73
|
-
recoverable: args.recoverable,
|
|
70
|
+
cohort: args.cohort,
|
|
74
71
|
});
|
|
75
72
|
}
|
|
76
73
|
export function formatFrameworkErrorForConsole(error) {
|
|
@@ -9,22 +9,24 @@
|
|
|
9
9
|
*/
|
|
10
10
|
import type { I18nServiceApi } from "@pie-players/pie-players-shared/i18n";
|
|
11
11
|
import type { AccessibilityCatalog, SectionControllerSessionState } from "@pie-players/pie-players-shared/types";
|
|
12
|
-
import type {
|
|
12
|
+
import type { CatalogChangeListener, CatalogLookupContext, CatalogLookupOptions, CatalogOwnerRegistration, CatalogOwnerView, CatalogStatistics, CatalogType, ResolvedCatalog } from "./AccessibilityCatalogResolver.js";
|
|
13
13
|
import type { CatalogOwnerContext } from "./catalog-owner.js";
|
|
14
14
|
import type { FrameworkErrorListener } from "./framework-error-bus.js";
|
|
15
15
|
import type { FrameworkErrorModel } from "./framework-error.js";
|
|
16
|
-
import type {
|
|
16
|
+
import type { ToolFailurePhase } from "./tool-failure.js";
|
|
17
|
+
import type { Annotation, HighlightColor } from "./HighlightCoordinator.js";
|
|
17
18
|
import type { SerializedRange } from "./RangeSerializer.js";
|
|
18
19
|
import type { SectionControllerHandle, SectionItemEventSubscriptionArgs, SectionScopedEventSubscriptionArgs, SectionEventSubscriptionArgs, ToolkitCoordinatorHooks } from "./ToolkitCoordinator.js";
|
|
20
|
+
import type { ElementIdComponents } from "./ElementToolStateStore.js";
|
|
19
21
|
import type { ZIndexLayer } from "./ToolCoordinator.js";
|
|
20
|
-
import type { PlaybackState
|
|
22
|
+
import type { PlaybackState } from "./TTSService.js";
|
|
21
23
|
import type { TTSHighlightTargetResolverProvider } from "./tts/highlight-target-resolver.js";
|
|
22
24
|
import type { TextToSpeechToolProviderConfig, ToolPlacementConfig, ToolProviderConfig } from "./tools-config-normalizer.js";
|
|
23
25
|
import type { ToolProviderApi } from "./tool-providers/ToolProviderApi.js";
|
|
24
26
|
import type { ToolProviderRegistry } from "./tool-providers/ToolProviderRegistry.js";
|
|
25
|
-
import type { FeaturePolicyDecision, PolicySource, PnpEnforcementMode, ResolvedEngineInputs, ToolPolicyChangeListener, ToolPolicyDecision, ToolPolicyDecisionRequest, ToolScope } from "../policy/engine.js";
|
|
26
|
-
import type { AssessmentEntity, ItemSettings } from "@pie-players/pie-players-shared/types";
|
|
27
|
-
import type {
|
|
27
|
+
import type { FeaturePolicyDecision, PolicySource, PnpEnforcementMode, ResolvedEngineInputs, ToolPolicyChangeListener, ToolPolicyDecision, ToolPolicyDecisionRequest, ToolPolicyDiagnostic, ToolScope } from "../policy/engine.js";
|
|
28
|
+
import type { AssessmentEntity, ItemSettings, ToolParametersFor } from "@pie-players/pie-players-shared/types";
|
|
29
|
+
import type { TTSConfig } from "@pie-players/pie-tts";
|
|
28
30
|
import type { ResolvedToolContext, ToolContextResolverContext, ToolRegistry } from "./ToolRegistry.js";
|
|
29
31
|
import type { ToolOpenRequest, ToolRequestTarget } from "./tool-request.js";
|
|
30
32
|
export type { I18nServiceApi };
|
|
@@ -34,10 +36,6 @@ export type { I18nServiceApi };
|
|
|
34
36
|
* Manages content highlighting for TTS, annotations, and selections.
|
|
35
37
|
*/
|
|
36
38
|
export interface HighlightCoordinatorApi {
|
|
37
|
-
/**
|
|
38
|
-
* Highlight a text range
|
|
39
|
-
*/
|
|
40
|
-
highlightRange(range: Range, type: HighlightType, color: HighlightColor): void;
|
|
41
39
|
/**
|
|
42
40
|
* Highlight the word being read (temporary): one range per tree the word
|
|
43
41
|
* spans, all painted, so a word split across inline elements highlights
|
|
@@ -68,17 +66,9 @@ export interface HighlightCoordinatorApi {
|
|
|
68
66
|
*/
|
|
69
67
|
clearTTS(): void;
|
|
70
68
|
/**
|
|
71
|
-
* Clear
|
|
72
|
-
*/
|
|
73
|
-
clearHighlights(type: HighlightType): void;
|
|
74
|
-
/**
|
|
75
|
-
* Check if highlighting is supported in current environment
|
|
69
|
+
* Clear the TTS word highlight, keeping the sentence highlight
|
|
76
70
|
*/
|
|
77
|
-
|
|
78
|
-
/**
|
|
79
|
-
* Update TTS highlight style dynamically
|
|
80
|
-
*/
|
|
81
|
-
updateTTSHighlightStyle(color: string, opacity: number): void;
|
|
71
|
+
clearTTSWord(): void;
|
|
82
72
|
/**
|
|
83
73
|
* Record a learner annotation over a range.
|
|
84
74
|
*
|
|
@@ -214,6 +204,13 @@ export interface SpeakOptions {
|
|
|
214
204
|
* element target is its own root.
|
|
215
205
|
*/
|
|
216
206
|
contentRoot?: Element | null;
|
|
207
|
+
/**
|
|
208
|
+
* Who starts the read. The run carries it until the next read starts, a
|
|
209
|
+
* seek's restart included, and {@link TtsServiceApi.getRunOwner} reports it.
|
|
210
|
+
*/
|
|
211
|
+
ownerId?: string;
|
|
212
|
+
/** The rate the read starts at; it stays the service's rate afterwards. */
|
|
213
|
+
rate?: number;
|
|
217
214
|
}
|
|
218
215
|
/**
|
|
219
216
|
* TTS service interface
|
|
@@ -222,10 +219,6 @@ export interface SpeakOptions {
|
|
|
222
219
|
* Supports QTI 3.0 accessibility catalogs for pre-authored spoken content.
|
|
223
220
|
*/
|
|
224
221
|
export interface TtsServiceApi {
|
|
225
|
-
/**
|
|
226
|
-
* Initialize TTS with a provider
|
|
227
|
-
*/
|
|
228
|
-
initialize(provider: ITTSProvider, config?: Partial<TTSConfig>): Promise<void>;
|
|
229
222
|
/**
|
|
230
223
|
* Read `target` aloud: a range reads the text it selects, an element its
|
|
231
224
|
* content. A node with a spoken card that the target holds whole reads its
|
|
@@ -243,7 +236,8 @@ export interface TtsServiceApi {
|
|
|
243
236
|
*/
|
|
244
237
|
resume(): void;
|
|
245
238
|
/**
|
|
246
|
-
* Stop playback
|
|
239
|
+
* Stop playback and release the run owner. A read that ends on its own
|
|
240
|
+
* keeps its owner.
|
|
247
241
|
*/
|
|
248
242
|
stop(): void;
|
|
249
243
|
/**
|
|
@@ -251,13 +245,6 @@ export interface TtsServiceApi {
|
|
|
251
245
|
* service cannot speak.
|
|
252
246
|
*/
|
|
253
247
|
dispose(): void;
|
|
254
|
-
/**
|
|
255
|
-
* Request active TTS controls to hand off/deactivate their UI state.
|
|
256
|
-
*
|
|
257
|
-
* This is an orchestration hint for TTS tool chrome and does not replace
|
|
258
|
-
* playback controls such as stop/pause/resume.
|
|
259
|
-
*/
|
|
260
|
-
requestControlHandoff(): void;
|
|
261
248
|
/**
|
|
262
249
|
* Seek forward by sentence units
|
|
263
250
|
*/
|
|
@@ -266,30 +253,21 @@ export interface TtsServiceApi {
|
|
|
266
253
|
* Seek backward by sentence units
|
|
267
254
|
*/
|
|
268
255
|
seekBackward(units?: number): Promise<void>;
|
|
269
|
-
/**
|
|
270
|
-
* Check if currently playing
|
|
271
|
-
*/
|
|
272
|
-
isPlaying(): boolean;
|
|
273
|
-
/**
|
|
274
|
-
* Check if paused
|
|
275
|
-
*/
|
|
276
|
-
isPaused(): boolean;
|
|
277
256
|
/**
|
|
278
257
|
* Get current playback state
|
|
279
258
|
*/
|
|
280
259
|
getState(): PlaybackState;
|
|
281
260
|
/**
|
|
282
|
-
*
|
|
261
|
+
* The `ownerId` the latest read started with, or null when it named none,
|
|
262
|
+
* nothing has been read or {@link stop} released it. A new read announces
|
|
263
|
+
* itself through {@link onStateChange} with `loading`, and a stop that
|
|
264
|
+
* releases an owner announces `idle`, so a listener sees the owner change.
|
|
283
265
|
*/
|
|
284
|
-
|
|
266
|
+
getRunOwner(): string | null;
|
|
285
267
|
/**
|
|
286
268
|
* Subscribe to state changes. Returns the function that unsubscribes.
|
|
287
269
|
*/
|
|
288
270
|
onStateChange(callback: (state: PlaybackState) => void): () => void;
|
|
289
|
-
/**
|
|
290
|
-
* Get capabilities of current provider
|
|
291
|
-
*/
|
|
292
|
-
getCapabilities(): TTSProviderCapabilities | null;
|
|
293
271
|
/**
|
|
294
272
|
* Update TTS settings dynamically (rate, pitch, voice)
|
|
295
273
|
*/
|
|
@@ -298,18 +276,10 @@ export interface TtsServiceApi {
|
|
|
298
276
|
* Update playback speed and apply it to active planned playback.
|
|
299
277
|
*/
|
|
300
278
|
setPlaybackRate(rate: number): Promise<void>;
|
|
301
|
-
/**
|
|
302
|
-
* Set highlight coordinator for word highlighting
|
|
303
|
-
*/
|
|
304
|
-
setHighlightCoordinator(coordinator: HighlightCoordinatorApi): void;
|
|
305
279
|
/**
|
|
306
280
|
* Set a late-bound provider for optional host TTS highlight target remapping.
|
|
307
281
|
*/
|
|
308
|
-
setHighlightTargetResolverProvider
|
|
309
|
-
/**
|
|
310
|
-
* Set accessibility catalog resolver for spoken content
|
|
311
|
-
*/
|
|
312
|
-
setCatalogResolver(resolver: AccessibilityCatalogResolver): void;
|
|
282
|
+
setHighlightTargetResolverProvider(provider: TTSHighlightTargetResolverProvider | null): () => void;
|
|
313
283
|
}
|
|
314
284
|
/**
|
|
315
285
|
* Accessibility catalog resolver interface
|
|
@@ -387,18 +357,15 @@ export interface AccessibilityCatalogResolverApi {
|
|
|
387
357
|
*/
|
|
388
358
|
export interface ElementToolStateStoreApi {
|
|
389
359
|
/**
|
|
390
|
-
* Generate a globally unique element ID from
|
|
360
|
+
* Generate a globally unique element ID from its parts. `attemptId` is `""`
|
|
361
|
+
* when the host names no attempt; a tool keyed by item or section leaves
|
|
362
|
+
* `elementId`, and for a section `itemId`, as `""`.
|
|
391
363
|
*/
|
|
392
|
-
getGlobalElementId(
|
|
364
|
+
getGlobalElementId(parts: ElementIdComponents): string;
|
|
393
365
|
/**
|
|
394
366
|
* Parse a global element ID into its components
|
|
395
367
|
*/
|
|
396
|
-
parseGlobalElementId(globalElementId: string):
|
|
397
|
-
assessmentId: string;
|
|
398
|
-
sectionId: string;
|
|
399
|
-
itemId: string;
|
|
400
|
-
elementId: string;
|
|
401
|
-
} | null;
|
|
368
|
+
parseGlobalElementId(globalElementId: string): ElementIdComponents | null;
|
|
402
369
|
/**
|
|
403
370
|
* Set state for a specific tool on an element
|
|
404
371
|
*/
|
|
@@ -436,7 +403,7 @@ export interface ElementToolStateStoreApi {
|
|
|
436
403
|
*/
|
|
437
404
|
clearTool(toolId: string): void;
|
|
438
405
|
/**
|
|
439
|
-
* Clear all elements in a specific section
|
|
406
|
+
* Clear all elements in a specific section, across its attempts
|
|
440
407
|
*/
|
|
441
408
|
clearSection(assessmentId: string, sectionId: string): void;
|
|
442
409
|
/**
|
|
@@ -480,9 +447,9 @@ export interface ToolkitCoordinatorApi {
|
|
|
480
447
|
*/
|
|
481
448
|
readonly toolProviderRegistry: ToolProviderRegistry;
|
|
482
449
|
/**
|
|
483
|
-
* Ensure TTS service is initialized
|
|
450
|
+
* Ensure the TTS service is initialized from the `textToSpeech` tool config.
|
|
484
451
|
*/
|
|
485
|
-
ensureTTSReady(
|
|
452
|
+
ensureTTSReady(): Promise<void>;
|
|
486
453
|
/**
|
|
487
454
|
* Ensure a tool's provider is initialized and ready. Providers register under
|
|
488
455
|
* their tool's id, so a tool passes its own base tool id. A tool starts its
|
|
@@ -619,11 +586,11 @@ export interface ToolkitCoordinatorApi {
|
|
|
619
586
|
*/
|
|
620
587
|
reportFrameworkError?(model: FrameworkErrorModel): void;
|
|
621
588
|
/**
|
|
622
|
-
* Report that a
|
|
623
|
-
*
|
|
624
|
-
*
|
|
589
|
+
* Report that a tool failed in `phase`, under the tool failure policy
|
|
590
|
+
* {@link ToolFailurePhase} describes. Optional so structural host
|
|
591
|
+
* coordinators remain assignable; a reporter without it logs.
|
|
625
592
|
*/
|
|
626
|
-
|
|
593
|
+
reportToolFailure?(toolId: string, phase: ToolFailurePhase, error: unknown): void;
|
|
627
594
|
/**
|
|
628
595
|
* Resolve the visible tool set for a given placement level + scope.
|
|
629
596
|
* Returns the engine's full decision (visible tools, diagnostics,
|
|
@@ -643,7 +610,7 @@ export interface ToolkitCoordinatorApi {
|
|
|
643
610
|
* Optional so host-supplied coordinator stubs predating this method stay
|
|
644
611
|
* assignable; call sites must feature-detect.
|
|
645
612
|
*/
|
|
646
|
-
decideFeaturePolicy
|
|
613
|
+
decideFeaturePolicy?<K extends string>(featureId: K, scope?: ToolScope): FeaturePolicyDecision<ToolParametersFor<K>>;
|
|
647
614
|
/**
|
|
648
615
|
* Subscribe to policy-engine change events. Fires whenever the
|
|
649
616
|
* coordinator's bound policy inputs change (`updateToolConfig`,
|
|
@@ -653,6 +620,15 @@ export interface ToolkitCoordinatorApi {
|
|
|
653
620
|
* should call `decideToolPolicy(...)` with their level / scope.
|
|
654
621
|
*/
|
|
655
622
|
onPolicyChange(listener: ToolPolicyChangeListener): () => void;
|
|
623
|
+
/**
|
|
624
|
+
* Subscribe to the policy diagnostics the coordinator reports: the ones it
|
|
625
|
+
* logs as console warnings, once per code, tool and item. A new listener is
|
|
626
|
+
* first handed every diagnostic already reported. A change to the bound
|
|
627
|
+
* policy inputs or to PNP enforcement clears the record, and so does a tool
|
|
628
|
+
* registration that makes a named support id known or unknown, so a conflict
|
|
629
|
+
* that survives the change is reported again once.
|
|
630
|
+
*/
|
|
631
|
+
onPolicyDiagnostic(listener: (diagnostic: ToolPolicyDiagnostic) => void): () => void;
|
|
656
632
|
/**
|
|
657
633
|
* Subscribe to accessibility-catalog registrations and removals.
|
|
658
634
|
*
|
|
@@ -27,14 +27,14 @@ export interface SectionSessionPersistenceConfig {
|
|
|
27
27
|
context: SectionControllerContext;
|
|
28
28
|
strategy: SectionSessionPersistenceStrategy;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* applySession contract:
|
|
32
|
+
* - Preferred input is the output of getSession().
|
|
33
|
+
* - itemSessions may contain canonical attempt entries
|
|
34
|
+
* ({ itemIdentifier, session, isCompleted }) or raw session payloads
|
|
35
|
+
* ({ id, data, ... }); controller normalizes these before applying.
|
|
36
|
+
*/
|
|
30
37
|
export interface SectionControllerApplySessionOptions {
|
|
31
|
-
/**
|
|
32
|
-
* applySession contract:
|
|
33
|
-
* - Preferred input is the output of getSession().
|
|
34
|
-
* - itemSessions may contain canonical attempt entries
|
|
35
|
-
* ({ itemIdentifier, session, isCompleted }) or raw session payloads
|
|
36
|
-
* ({ id, data, ... }); controller normalizes these before applying.
|
|
37
|
-
*/
|
|
38
38
|
mode?: "replace" | "merge";
|
|
39
39
|
}
|
|
40
40
|
export interface SectionControllerLoadedRenderable {
|
|
@@ -15,16 +15,14 @@
|
|
|
15
15
|
*/
|
|
16
16
|
import { hasResponseField, hasResponseValue, } from "@pie-players/pie-players-shared/pie";
|
|
17
17
|
import { structurallyEqual } from "../utils/structural-equality.js";
|
|
18
|
-
|
|
19
|
-
return Boolean(value) && typeof value === "object" && !Array.isArray(value);
|
|
20
|
-
}
|
|
18
|
+
import { isPlainRecord } from "@pie-players/pie-players-shared/object";
|
|
21
19
|
/** An entry is canonical (`{ itemIdentifier, session, ... }`) or the raw item session. */
|
|
22
20
|
function itemSessionOf(entry) {
|
|
23
|
-
return
|
|
21
|
+
return isPlainRecord(entry) && isPlainRecord(entry.session) ? entry.session : entry;
|
|
24
22
|
}
|
|
25
23
|
function sameItemSessions(next, current) {
|
|
26
|
-
const nextSessions =
|
|
27
|
-
const currentSessions =
|
|
24
|
+
const nextSessions = isPlainRecord(next) ? next : {};
|
|
25
|
+
const currentSessions = isPlainRecord(current) ? current : {};
|
|
28
26
|
const itemIds = new Set([
|
|
29
27
|
...Object.keys(nextSessions),
|
|
30
28
|
...Object.keys(currentSessions),
|
|
@@ -63,10 +61,10 @@ function sameSessionContent(next, current) {
|
|
|
63
61
|
export function resolveSectionSessionAssignment(current, next) {
|
|
64
62
|
if (!current)
|
|
65
63
|
return next;
|
|
66
|
-
const itemSessions =
|
|
64
|
+
const itemSessions = isPlainRecord(next.itemSessions)
|
|
67
65
|
? { ...next.itemSessions }
|
|
68
66
|
: {};
|
|
69
|
-
const currentItemSessions =
|
|
67
|
+
const currentItemSessions = isPlainRecord(current.itemSessions)
|
|
70
68
|
? current.itemSessions
|
|
71
69
|
: {};
|
|
72
70
|
for (const [itemId, currentEntry] of Object.entries(currentItemSessions)) {
|
|
@@ -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,8 +17,6 @@
|
|
|
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
22
|
/** A validated recorded spoken alternate, flattened for playback. */
|
|
@@ -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,8 +17,6 @@
|
|
|
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
22
|
/**
|
|
@@ -1,5 +1,4 @@
|
|
|
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";
|
|
@@ -19,13 +18,12 @@ export interface ToolConfigValidationResult {
|
|
|
19
18
|
config: CanonicalToolsConfig;
|
|
20
19
|
diagnostics: ToolConfigDiagnostic[];
|
|
21
20
|
}
|
|
22
|
-
export declare function frameworkErrorFromToolConfigValidation(args: {
|
|
23
|
-
source: string;
|
|
24
|
-
diagnostics?: ToolConfigDiagnostic[] | null;
|
|
25
|
-
error?: unknown;
|
|
26
|
-
recoverable?: boolean;
|
|
27
|
-
}): FrameworkErrorModel;
|
|
28
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
|
+
*/
|
|
29
27
|
export declare function normalizeAndValidateToolsConfig(input?: ToolsConfigInput | null, options?: ToolConfigValidationOptions): ToolConfigValidationResult;
|
|
30
28
|
/**
|
|
31
29
|
* The normalization and diagnostics of {@link normalizeAndValidateToolsConfig},
|
|
@@ -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") {
|
|
@@ -198,6 +182,11 @@ function throwValidationError(diagnostics, source) {
|
|
|
198
182
|
.join("\n");
|
|
199
183
|
throw new Error(`[tool-config-validation:${source}] Invalid tools config:\n${formatted}`);
|
|
200
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
|
+
*/
|
|
201
190
|
export function normalizeAndValidateToolsConfig(input, options = {}) {
|
|
202
191
|
const result = collectToolConfigDiagnostics(input, options.toolRegistry);
|
|
203
192
|
reportToolConfigDiagnostics(result.diagnostics, options);
|
|
@@ -212,11 +201,9 @@ export function collectToolConfigDiagnostics(input, toolRegistry) {
|
|
|
212
201
|
const normalized = normalizeToolsConfig(input);
|
|
213
202
|
const diagnostics = [];
|
|
214
203
|
// Tool-id and provider checks need a registry to check against, and every
|
|
215
|
-
// collector below returns early without one. Say so
|
|
216
|
-
//
|
|
217
|
-
//
|
|
218
|
-
// valid" to "nobody looked" is the kind of change that surfaces as a typo
|
|
219
|
-
// 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.
|
|
220
207
|
const hasConfiguredTools = Object.values(normalized.placement).some((ids) => ids.length > 0) ||
|
|
221
208
|
Object.keys(normalized.providers).length > 0 ||
|
|
222
209
|
(normalized.policy.allowed?.length ?? 0) > 0 ||
|
|
@@ -260,11 +247,9 @@ export function reportToolConfigDiagnostics(diagnostics, options = {}) {
|
|
|
260
247
|
if (strictness === "warn") {
|
|
261
248
|
emitWarnings(diagnostics, source);
|
|
262
249
|
}
|
|
263
|
-
// Severity decides what `strictness: "error"` rejects.
|
|
264
|
-
//
|
|
265
|
-
//
|
|
266
|
-
// turn "no registry supplied" from a host's existing, working setup into a
|
|
267
|
-
// 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.
|
|
268
253
|
const blocking = diagnostics.filter((entry) => entry.severity === "error");
|
|
269
254
|
if (strictness === "error" && blocking.length > 0) {
|
|
270
255
|
throwValidationError(blocking, source);
|
|
@@ -102,30 +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 isItemContext(context: ToolContext): context is ItemToolContext;
|
|
108
|
-
/**
|
|
109
|
-
* Type guard to check if context is at passage level
|
|
110
|
-
*/
|
|
111
|
-
export declare function isPassageContext(context: ToolContext): context is PassageToolContext;
|
|
112
|
-
/**
|
|
113
|
-
* Type guard to check if context is at rubric level
|
|
114
|
-
*/
|
|
115
|
-
export declare function isRubricContext(context: ToolContext): context is RubricToolContext;
|
|
116
|
-
/**
|
|
117
|
-
* Type guard to check if context is at element level
|
|
118
|
-
*/
|
|
119
|
-
export declare function isElementContext(context: ToolContext): context is ElementToolContext;
|
|
120
|
-
/** The plain text a context carries, tags removed. */
|
|
121
|
-
export declare function extractTextContent(context: ToolContext): string;
|
|
122
|
-
/**
|
|
123
|
-
* The authored markup a context carries, tags intact.
|
|
124
|
-
*
|
|
125
|
-
* For indicators that live in the markup rather than in the prose — `<math>`
|
|
126
|
-
* 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)
|
|
127
107
|
*/
|
|
128
|
-
export declare function extractMarkupContent(context: ToolContext): string;
|
|
129
108
|
export declare function hasMathContent(context: ToolContext): boolean;
|
|
130
109
|
/**
|
|
131
110
|
* Helper to check if context contains choice-based interactions
|
|
@@ -135,6 +114,11 @@ export declare function hasChoiceInteraction(context: ToolContext): boolean;
|
|
|
135
114
|
* Helper to check if context contains text that can be read aloud
|
|
136
115
|
*/
|
|
137
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;
|
|
138
122
|
/**
|
|
139
123
|
* Helper to check if context contains science content
|
|
140
124
|
* (Basic heuristic - can be overridden by tools)
|