@intellectif/lk-core 0.13.1 → 0.14.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.
Files changed (55) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +1 -1
  3. package/dist/{activity-DfAmJ1sl.d.cts → activity-BVkg9VDo.d.cts} +153 -4
  4. package/dist/{activity-DfAmJ1sl.d.ts → activity-BVkg9VDo.d.ts} +153 -4
  5. package/dist/{chunk-DQKJUMUW.cjs → chunk-2NIALQEH.cjs} +24 -19
  6. package/dist/chunk-2NIALQEH.cjs.map +1 -0
  7. package/dist/{chunk-XKKKWKRH.js → chunk-6RND47QE.js} +694 -126
  8. package/dist/chunk-6RND47QE.js.map +1 -0
  9. package/dist/{chunk-FT7SAC3X.cjs → chunk-CZRUMHKW.cjs} +4 -4
  10. package/dist/{chunk-FT7SAC3X.cjs.map → chunk-CZRUMHKW.cjs.map} +1 -1
  11. package/dist/chunk-J5OIRIOW.cjs +1034 -0
  12. package/dist/chunk-J5OIRIOW.cjs.map +1 -0
  13. package/dist/{chunk-Y36S3X3L.js → chunk-NBADQ3JU.js} +7 -2
  14. package/dist/chunk-NBADQ3JU.js.map +1 -0
  15. package/dist/{chunk-PYP3HCRQ.js → chunk-R7PV3XIC.js} +2 -2
  16. package/dist/chunk-RTIR6R2U.js +1034 -0
  17. package/dist/chunk-RTIR6R2U.js.map +1 -0
  18. package/dist/{chunk-XONKWL6D.cjs → chunk-VCXIPLEW.cjs} +585 -17
  19. package/dist/chunk-VCXIPLEW.cjs.map +1 -0
  20. package/dist/{index-BefQ8FAS.d.cts → index-BE1bM2Wi.d.cts} +238 -16
  21. package/dist/{index-BiIvdASA.d.ts → index-v2_-Fyn3.d.ts} +238 -16
  22. package/dist/index.cjs +110 -80
  23. package/dist/index.cjs.map +1 -1
  24. package/dist/index.d.cts +45 -17
  25. package/dist/index.d.ts +45 -17
  26. package/dist/index.js +35 -5
  27. package/dist/index.js.map +1 -1
  28. package/dist/schemas.cjs +11 -3
  29. package/dist/schemas.cjs.map +1 -1
  30. package/dist/schemas.d.cts +2 -2
  31. package/dist/schemas.d.ts +2 -2
  32. package/dist/schemas.js +10 -2
  33. package/dist/scoring.cjs +23 -3
  34. package/dist/scoring.cjs.map +1 -1
  35. package/dist/scoring.d.cts +471 -16
  36. package/dist/scoring.d.ts +471 -16
  37. package/dist/scoring.js +24 -4
  38. package/dist/xapi.cjs +3 -3
  39. package/dist/xapi.d.cts +1 -1
  40. package/dist/xapi.d.ts +1 -1
  41. package/dist/xapi.js +2 -2
  42. package/package.json +1 -1
  43. package/vectors/README.md +63 -3
  44. package/vectors/replay.d.mts +7 -2
  45. package/vectors/replay.mjs +83 -1
  46. package/vectors/scoring.json +10875 -2
  47. package/dist/chunk-DQKJUMUW.cjs.map +0 -1
  48. package/dist/chunk-FGN4LLSP.js +0 -387
  49. package/dist/chunk-FGN4LLSP.js.map +0 -1
  50. package/dist/chunk-UHQVIC3P.cjs +0 -387
  51. package/dist/chunk-UHQVIC3P.cjs.map +0 -1
  52. package/dist/chunk-XKKKWKRH.js.map +0 -1
  53. package/dist/chunk-XONKWL6D.cjs.map +0 -1
  54. package/dist/chunk-Y36S3X3L.js.map +0 -1
  55. /package/dist/{chunk-PYP3HCRQ.js.map → chunk-R7PV3XIC.js.map} +0 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,28 @@
1
1
  # @intellectif/lk-core
2
2
 
3
+ ## 0.14.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 7d25492: A built-in `read-aloud` activity type: the learner reads a text aloud, a pronunciation-assessment engine judges the recording, and the SDK turns that judgement into a grade.
8
+
9
+ - `ReadAloudData` carries the `referenceText` the learner reads, a `locale` in canonical BCP 47 with a region, a model recording and an optional slower one (`slowMedia`, a separate file that needs the recording it is the slower reading of), the bounds of a take (`recording`), and `scoring.dimensions` — one to four of `accuracy`, `fluency`, `completeness` and `prosody`, each weighted, at least one above 0. There is no default set of dimensions and a new draft starts with none: an untouched draft must not quietly become a grading rule. The text, the weights and the bounds are all public, so a read-aloud item has no answer key: `redact()` drops the authored feedback, marks the copy, and keeps the rest — a projection a learner may render in full. The schema refuses a text nothing survives of once punctuation and spacing are folded away (`"..."` marks no word at all, so a silent take would record no omission and a perfect reading would align as one insertion after another), and, for now, a script written without spaces between its words, because per-word marks need boundaries the SDK does not compute. Nineteen draft issue codes (`ra_*`) with their severities and paths are in the authoring guide.
10
+ - `ReadAloudLearnerResponse` carries a `RecordingRef` — `{ key, mimeType }`, where the key is opaque storage identity your application issues, never a URL and never bytes — or `null` for a learner who submitted without recording. A `durationMs` the browser reports may ride along and no grade reads it.
11
+ - **Grading is deferred.** `evaluate(data, response)` answers `{ status: 'deferred', reason: 'requires_async_grading', maxScore: 1, partial: { hasRecording } }`, and `score('read-aloud', data, response)` throws `DeferredScoringError` rather than inventing a number. A stored read-aloud item therefore keeps a composed assessment result provisional until it is graded; an unscorable one is left out of the total, so route those to a re-record or a person before releasing a verdict.
12
+ - `SpeechAssessment` is the evidence shape, neutral across engines: the assessed locale, the reference text and recording key the assessment is bound to, who assessed it, dimension scores on a declared 0–100 scale, the recognised text, and per-word marks with optional syllables, phonemes, what each was heard as, timings and break confidences. An absent score means "not measured" and is never a 0. `validateSpeechAssessment(value)` answers `{ success: true, data }` or `{ success: false, errors }` — one error per problem, with the same `path`, `message` and `code` `validateActivity` gives a schema failure — and every object is strict, so a misspelt key is an error rather than silently ignored. Three rules span fields: a scripted assessment carries its `referenceText` and `recordingKey`; a phoneme that names a symbol, or what it was heard as, needs `phonemeAlphabet`; and the words carry at most 8000 characters between them, as they are written and again as they spell once normalised — one character can stand for eighteen, and the marks are made by aligning tokens, so a per-word cap bounds no total.
13
+ - `gradeReadAloud(data, response, assessment, { measured, plausibility, allowAiAssessor?, rounding? })` returns a `GradeRecord` or `{ unscorable: true, code, reason }`. `measured` is your server's own measurement of the stored recording and `plausibility` your own policy; neither has a default, because every value in them decides whether a grade exists. Ten reasons a take is unscorable rather than a zero — evidence that is not well formed, not scripted, made for another locale, another text or another take, produced by a generative model you did not opt into, no speech, too little voiced time, more words per second than your policy allows, or a weighted dimension the assessment does not score. A blank grades 0 with every reference word marked omitted and no grader, because nobody measured it. The weighted dimensions become rubric criteria out of 100 and `gradeFromRubric` computes the total; `GradeRecord.details` carries one mark per reference word, and **word marks never move the item score**.
14
+ - `alignReadAloud(data, assessment)` returns the same comparison as a list a review screen can render: every reference word with its state — correct, mispronounced or omitted — and every inserted word where it was spoken, each pointing back into `assessment.words` so syllables, phonemes and timings are one lookup away. `reference` and `heard` are normalised, because that is what was compared. Branch on `state`, never on `heard === ''`: an inserted word whose text normalises to nothing reads empty too.
15
+ - `inspectWav(bytes, { silenceDbfs, frameMs })` measures a 16-bit PCM WAV's duration, sample rate, channels, peak level and voiced time without a decoding library, and refuses what it cannot read as `not_wav`, `unsupported_encoding` or `truncated`. Both policy fields are required, because neither has an answer that is right for every microphone. Voiced time is counted in windows and never exceeds the duration, which is what `gradeReadAloud` requires of a measurement.
16
+ - Additive elsewhere: `GradeRecord.details`, a machine-readable `code` on an `ItemOutcome`'s unscorable arm, written by the new `outcomeFromUnscorable`; a `rounding` option on `gradeFromRubric`, so a pass line can be compared the way a score is displayed, with the score itself left unrounded; and recording and assessment `InteractionKind` literals. `GraderKind`'s three values are now documented: `'auto'` is a non-generative measurement engine, `'ai'` a generative model, `'human'` a person.
17
+ - `@intellectif/lk-core/scoring` now names its own functions' types. Every argument, return value and nested shape a public signature on that subpath mentions is re-exported from it — twenty type names, including `GradeRecord`, `ItemOutcome`, `ReadAloudData`, `SpeechAssessment`, `SpeechWord` and `WavInspection`. A function whose arguments cannot be named is one that has to be called from `any`, which is how evidence stops being checked. Type-only: the bundle is unchanged.
18
+
19
+ **Upgrading.**
20
+
21
+ - `read-aloud` is now a built-in. If you registered an activity type of your own under that name, `registerActivityType` will throw; rename yours before upgrading.
22
+ - **`RedactedScoringError`'s message has been reworded**, for every type it is thrown for and not only the new one. Its old remedy — "or use `evaluate()` which returns `{ status: "unscorable" }`" — is not true of a deferred type, which `evaluate()` answers `deferred` for, redacted or not. The class, its `name` and its `activityType` are unchanged and no grade moves; only the sentence does, so an assertion on the exact text needs updating.
23
+ - A `switch` that must be exhaustive over `ActivityType`, `InteractionKind` or the redacted activity union gains new members to handle.
24
+ - **The grade-stability corpus is written in encoding version 2.** `CORPUS_VERSION` is now `2`: a vector can carry the bytes of a recording, as `{ "$bytes": "<base64>" }`, which `inspectWav` needs. `replay()` throws rather than comparing a corpus written in another encoding, so if you replay `vectors/scoring.json` yourself, load the `replay.mjs` shipped beside it rather than a copy you pinned earlier. No expectation moved with the bump, and every grade a released version froze replays unchanged.
25
+
3
26
  ## 0.13.1
4
27
 
5
28
  ### Patch Changes
package/README.md CHANGED
@@ -14,7 +14,7 @@ npm install @intellectif/lk-core
14
14
 
15
15
  ## What's in the box
16
16
 
17
- - **Activity schemas** for `multiple-choice`, `fill-in-the-blanks`, `written-response`, `gap-select` and `dictation`, with semantic refinements (e.g. *at least one correct option*, *single-select ⇒ exactly one correct*, *passage ↔ blank-id bijection*, *image/embed require `alt`*, *a dictation title never contains its whole transcript as words*). Loose at every level, so your sidecar fields survive validation.
17
+ - **Activity schemas** for `multiple-choice`, `fill-in-the-blanks`, `written-response`, `gap-select`, `dictation` and `read-aloud`, with semantic refinements (e.g. *at least one correct option*, *single-select ⇒ exactly one correct*, *passage ↔ blank-id bijection*, *image/embed require `alt`*, *a dictation title never contains its whole transcript as words*, *a read-aloud's text leaves at least one word once punctuation is folded away*). Loose at every level, so your sidecar fields survive validation.
18
18
  - **`validateActivity(type, data)`** — the authoritative runtime validator. Returns a typed `{ success, data }` or a structured `{ success: false, errors[] }`, and **throws `UnknownActivityTypeError` if `type` is not registered** — so guard it when validating a content bank that may carry types this build does not know. `validateItemGroup(data)` is the equivalent for a `Stimulus` + `ItemGroup` container, which `validateActivity` cannot take.
19
19
  - **`validateDraft(type, draft)`** — for editors. Reports `complete`, `incomplete` (something not written yet) or `invalid` (something wrong), each issue with a `severity` and a `code` — documented for every problem the checks recognise — and deliberately no `success` boolean to misread. Stricter than `validateActivity`, never looser. **`createDraft(type, { newId })`** returns an empty draft to start from; a multiple-choice draft marks no option correct.
20
20
  - **An open type system** — `defineActivityType` / `registerActivityType` make an activity type a *value*, not a hard-coded union member: register one and `validateActivity`, `validateDraft`, `score`, `evaluate`, `redact` and `jsonSchemaFor` all work for it, with no SDK release. An `authoring` block on the descriptor gives it draft support.
@@ -77,13 +77,21 @@ declare function matchText(input: string, accepted: string | readonly string[],
77
77
  * The SDK models the SHAPE and the arithmetic. It never calls a model, never
78
78
  * holds a key, and never decides what a rubric means — that stays yours.
79
79
  */
80
+
80
81
  /**
81
82
  * Lifecycle of a deferred grade. A grade exists only in the `graded` state;
82
83
  * every other state means "no grade, and here is why" — which is precisely the
83
84
  * distinction that stops an ungraded submission being rendered as a zero.
84
85
  */
85
86
  type GradingState = 'queued' | 'running' | 'graded' | 'failed' | 'skipped';
86
- /** Who produced a grade. */
87
+ /**
88
+ * Who produced a grade.
89
+ *
90
+ * - `'auto'` — a non-generative measurement engine, for example a
91
+ * pronunciation-assessment service.
92
+ * - `'ai'` — a generative model.
93
+ * - `'human'` — a person.
94
+ */
87
95
  type GraderKind = 'ai' | 'human' | 'auto';
88
96
  /** Provenance of a grade, so a re-grade two years later is explicable. */
89
97
  interface Grader {
@@ -166,6 +174,12 @@ interface GradeRecord {
166
174
  feedback: string | null;
167
175
  /** Per-criterion breakdown, when the grader worked against a rubric. */
168
176
  criteria?: CriterionScore[];
177
+ /**
178
+ * Per-item marks carried by a grade — for example the per-word marks of a
179
+ * read-aloud grade. `outcomeFromGrade` does not mirror them onto the
180
+ * outcome; read `outcome.grade.details`.
181
+ */
182
+ details?: ScoringDetail[];
169
183
  /** Corrections anchored in the learner's text. */
170
184
  corrections?: InlineCorrection[];
171
185
  /** Supporting observations the grader cited. */
@@ -361,6 +375,7 @@ interface ActivityDataMap {
361
375
  'written-response': WrittenResponseData;
362
376
  'gap-select': GapSelectData;
363
377
  dictation: DictationData;
378
+ 'read-aloud': ReadAloudData;
364
379
  }
365
380
  /**
366
381
  * The set of activity types supported by learning-kit. Derived from
@@ -885,6 +900,96 @@ interface DictationData {
885
900
  /** Subjective difficulty on a 1–5 scale. */
886
901
  difficultyLevel?: 1 | 2 | 3 | 4 | 5;
887
902
  }
903
+ /** A dimension of speech a pronunciation assessor scores, on a 0–100 scale. */
904
+ type ReadAloudDimension = 'accuracy' | 'fluency' | 'completeness' | 'prosody';
905
+ /** One assessor dimension counted towards a read-aloud grade, and its weight. */
906
+ interface ReadAloudDimensionWeight {
907
+ name: ReadAloudDimension;
908
+ /**
909
+ * Relative weight, 0..1000 (`READ_ALOUD_MAX_DIMENSION_WEIGHT`). Weights need
910
+ * not add up to anything; a weight of 0 leaves the dimension out of the grade.
911
+ */
912
+ weight: number;
913
+ }
914
+ /**
915
+ * The limits on a read-aloud take, applied where the learner records. No grade
916
+ * reads them: whether a take is plausible speech is decided from the server's
917
+ * own measurement of the recording, never from a bound the client enforced.
918
+ */
919
+ interface RecordingBounds {
920
+ /** The longest take, in seconds: above 0, and at most `READ_ALOUD_MAX_SECONDS` (300). */
921
+ maxSeconds: number;
922
+ /** The shortest take, in seconds: at least 0, and below `maxSeconds`. */
923
+ minSeconds?: number;
924
+ /** How many takes the learner may record: a whole number from 1 to `READ_ALOUD_MAX_TAKES` (20). */
925
+ maxTakes?: number;
926
+ }
927
+ /**
928
+ * A second, slower model recording of the reference text — a separate file,
929
+ * not a `playbackRate` change. It carries no `captionsUrl` and no `playback`
930
+ * policy of its own, requires `media`, must be a different file from it, and
931
+ * cannot accompany a play limit on `media`.
932
+ */
933
+ interface ReadAloudSlowMedia {
934
+ type: 'audio';
935
+ /** Source URL, under the same policy as {@link ActivityMedia.url}. */
936
+ url: string;
937
+ /** Accessible label — a description ("Model recording, slow"). */
938
+ alt?: string;
939
+ }
940
+ /**
941
+ * Data contract for a Read Aloud activity: the learner reads a text aloud, an
942
+ * assessor measures the recording, and the grade is the weighted total of the
943
+ * assessor's dimension scores.
944
+ *
945
+ * Grading is deferred — `evaluate()` returns `deferred` until the application
946
+ * holds an assessment — and nothing here is an answer key: the learner is shown
947
+ * the text they are asked to read.
948
+ */
949
+ interface ReadAloudData {
950
+ schemaVersion: '1.0';
951
+ type: 'read-aloud';
952
+ /** Unique identifier for this activity. */
953
+ id: string;
954
+ /** Human-readable title used in xAPI statements and error boundaries. */
955
+ title: string;
956
+ /** Optional instructions shown to the learner, as plain text. */
957
+ instructions?: string;
958
+ /**
959
+ * The text the learner reads aloud. Shown to the learner (public). At most
960
+ * `READ_ALOUD_MAX_REFERENCE_LENGTH` code points before and after
961
+ * normalisation, in a script written with spaces between words.
962
+ */
963
+ referenceText: string;
964
+ /**
965
+ * BCP 47 tag in canonical form with a region (e.g. `en-US`). GRADE-DECIDING:
966
+ * an assessment made for another locale is unscorable.
967
+ */
968
+ locale: string;
969
+ /** A model recording of the text. Audio only; a playback policy is allowed. */
970
+ media?: ActivityMedia;
971
+ /** A second, slower model recording. See {@link ReadAloudSlowMedia}. */
972
+ slowMedia?: ReadAloudSlowMedia;
973
+ /** The limits on a take. See {@link RecordingBounds}. */
974
+ recording: RecordingBounds;
975
+ /**
976
+ * The assessor dimensions the grade is made of, with their weights: 1 to 4
977
+ * entries, each name at most once, at least one weight above 0. A weighted
978
+ * dimension the assessment has no score for makes the take unscorable, never
979
+ * a zero. Public.
980
+ */
981
+ scoring: {
982
+ dimensions: ReadAloudDimensionWeight[];
983
+ };
984
+ /** Minimum scaled score [0–1] required to pass once graded. Defaults to {@link DEFAULT_PASS_THRESHOLD} (0.7) when absent. */
985
+ passThreshold?: number;
986
+ /** Optional authored overall feedback, selected once the grade exists. */
987
+ feedback?: ActivityFeedback;
988
+ /** IRI references to learning objectives addressed by this activity. */
989
+ learningObjectives?: string[];
990
+ /** Subjective difficulty on a 1–5 scale. */
991
+ difficultyLevel?: 1 | 2 | 3 | 4 | 5;
992
+ }
888
993
  /**
889
994
  * Maps each ActivityType string to its learner-response shape. Open for
890
995
  * extension via module augmentation, mirroring {@link ActivityDataMap}.
@@ -895,6 +1000,7 @@ interface LearnerResponseMap {
895
1000
  'written-response': WrittenResponseLearnerResponse;
896
1001
  'gap-select': GapSelectLearnerResponse;
897
1002
  dictation: DictationLearnerResponse;
1003
+ 'read-aloud': ReadAloudLearnerResponse;
898
1004
  }
899
1005
  /** Union of all learner response shapes. */
900
1006
  type LearnerResponse = LearnerResponseMap[keyof LearnerResponseMap];
@@ -947,6 +1053,28 @@ interface DictationLearnerResponse {
947
1053
  /** Hint words revealed before submitting (practice only). Absent or 0 means none. */
948
1054
  hintsRevealed?: number;
949
1055
  }
1056
+ /**
1057
+ * A learner recording held by the application. `key` is opaque,
1058
+ * application-issued storage identity: never a URL or bytes. `durationMs` is a
1059
+ * client claim no grade reads.
1060
+ */
1061
+ interface RecordingRef {
1062
+ key: string;
1063
+ /** The media type the recording was stored as, e.g. `audio/wav`. */
1064
+ mimeType: string;
1065
+ durationMs?: number;
1066
+ }
1067
+ /**
1068
+ * Learner response for a Read Aloud activity: a reference to the recording the
1069
+ * application stored, never the audio itself.
1070
+ */
1071
+ interface ReadAloudLearnerResponse {
1072
+ type: 'read-aloud';
1073
+ /** `null`: the learner submitted without recording (a blank). A take that failed to upload is never `null`. */
1074
+ recording: RecordingRef | null;
1075
+ /** Telemetry: takes used. No grade reads it. */
1076
+ takes?: number;
1077
+ }
950
1078
  /**
951
1079
  * Fine-grained outcome of the learner's action on a single item, replacing the
952
1080
  * ambiguous {@link ScoringDetail.correct}:
@@ -989,7 +1117,9 @@ interface ScoringDetail {
989
1117
  * The item's own scaled score in [0, 1], for a type that grades its items on
990
1118
  * a continuum rather than right or wrong. Written by the dictation scorer
991
1119
  * (the similarity of each transcript word to what was typed for it) and by
992
- * nothing else today. Absent, an item is right or wrong: read `outcome`.
1120
+ * `gradeReadAloud` (the assessor's accuracy for each reference word as a
1121
+ * fraction, 0 for an omitted word, and absent where the assessor gave none).
1122
+ * Absent, an item is right or wrong: read `outcome`.
993
1123
  */
994
1124
  score?: number;
995
1125
  }
@@ -1082,6 +1212,11 @@ type ItemOutcome = {
1082
1212
  reason: string;
1083
1213
  /** Maximum possible scaled score, when known. */
1084
1214
  maxScore: number;
1215
+ /**
1216
+ * A machine-readable reason, written by `outcomeFromUnscorable` — for
1217
+ * example a read-aloud `SpeechUnscorableCode`. `evaluate` never writes it.
1218
+ */
1219
+ code?: string;
1085
1220
  };
1086
1221
  /** A single validation error produced by `validateActivity`. */
1087
1222
  interface ValidationError {
@@ -1134,7 +1269,21 @@ type InteractionKind = 'option-selected' | 'option-deselected' | 'blank-filled'
1134
1269
  /** A charged play produced no audio — a failed or expired media URL. */
1135
1270
  | 'media-play-errored'
1136
1271
  /** A charged play was returned, because the consumer accepted the refund. */
1137
- | 'media-play-refunded' | (string & {});
1272
+ | 'media-play-refunded'
1273
+ /** The microphone began capturing a take. */
1274
+ | 'recording-started'
1275
+ /** A take ended, by the learner or at its time limit. */
1276
+ | 'recording-stopped'
1277
+ /** A take was thrown away, to record another. */
1278
+ | 'recording-discarded'
1279
+ /** The application stored a take and returned its reference. */
1280
+ | 'recording-uploaded'
1281
+ /** Storing a take failed. A take that failed to upload is never a blank answer. */
1282
+ | 'recording-upload-failed'
1283
+ /** A stored take was sent for assessment. */
1284
+ | 'assessment-requested'
1285
+ /** An assessment request failed: the take has no grade. */
1286
+ | 'assessment-failed' | (string & {});
1138
1287
  /** Fired by activity components on every discrete learner interaction. */
1139
1288
  interface InteractionEvent {
1140
1289
  /** The kind of interaction that occurred. */
@@ -1147,4 +1296,4 @@ interface InteractionEvent {
1147
1296
  payload: Record<string, unknown>;
1148
1297
  }
1149
1298
 
1150
- export { type XAPIError as $, type ActivityData as A, type BlankConfig as B, type CriterionScore as C, type DeferredScoringPartial as D, type MultipleChoiceOption as E, type FillInTheBlanksData as F, type GapSelectBank as G, type MultipleChoiceOptionMedia as H, type InlineCorrection as I, type ScoringOutcome as J, type ScoringResult as K, type LearnerResponse as L, type MediaPlaybackPolicy as M, type NativeControlHint as N, type TextMatchResult as O, type ValidationResult as P, type WrittenResponseLearnerResponse as Q, type WrittenResponseRubric as R, type ScoringDetail as S, type TextMatchPolicy as T, type WrittenResponseRubricCriterion as U, type ValidationError as V, type WrittenResponseData as W, type XAPIActor as X, type XAPIConfig as Y, type XAPIContext as Z, type XAPIContextActivities as _, type ActivityDataMap as a, type XAPIObject as a0, type XAPIResult as a1, type XAPIScore as a2, type XAPIStatement as a3, type XAPIVerbObject as a4, levenshteinDistance as a5, matchText as a6, type ActivityFeedback as b, type ActivityMedia as c, type ActivityResult as d, type ActivityType as e, type DictationData as f, type DictationEquivalence as g, type DictationLearnerResponse as h, type DictationSlowMedia as i, type DictationTolerance as j, type FillInTheBlanksLearnerResponse as k, type GapSelectChoice as l, type GapSelectData as m, type GapSelectGap as n, type GapSelectLearnerResponse as o, type GradeRecord as p, type Grader as q, type GraderKind as r, type GraderUsage as s, type GradingState as t, type InteractionEvent as u, type InteractionKind as v, type ItemOutcome as w, type LearnerResponseMap as x, type MultipleChoiceData as y, type MultipleChoiceLearnerResponse as z };
1299
+ export { type WrittenResponseData as $, type ActivityData as A, type BlankConfig as B, type CriterionScore as C, type DeferredReason as D, type MultipleChoiceLearnerResponse as E, type FillInTheBlanksData as F, type GapSelectBank as G, type MultipleChoiceOption as H, type InlineCorrection as I, type MultipleChoiceOptionMedia as J, type ReadAloudDimension as K, type LearnerResponse as L, type MediaPlaybackPolicy as M, type NativeControlHint as N, type ReadAloudDimensionWeight as O, type ReadAloudLearnerResponse as P, type ReadAloudSlowMedia as Q, type ReadAloudData as R, type RecordingBounds as S, type RecordingRef as T, type ScoringDetail as U, type ScoringOutcome as V, type ScoringResult as W, type TextMatchPolicy as X, type TextMatchResult as Y, type ValidationError as Z, type ValidationResult as _, type ActivityDataMap as a, type WrittenResponseLearnerResponse as a0, type WrittenResponseRubric as a1, type WrittenResponseRubricCriterion as a2, type XAPIActor as a3, type XAPIConfig as a4, type XAPIContext as a5, type XAPIContextActivities as a6, type XAPIError as a7, type XAPIObject as a8, type XAPIResult as a9, type XAPIScore as aa, type XAPIStatement as ab, type XAPIVerbObject as ac, levenshteinDistance as ad, matchText as ae, type ActivityFeedback as b, type ActivityMedia as c, type ActivityResult as d, type ActivityType as e, type DeferredScoringPartial as f, type DictationData as g, type DictationEquivalence as h, type DictationLearnerResponse as i, type DictationSlowMedia as j, type DictationTolerance as k, type FillInTheBlanksLearnerResponse as l, type GapSelectChoice as m, type GapSelectData as n, type GapSelectGap as o, type GapSelectLearnerResponse as p, type GradeRecord as q, type Grader as r, type GraderKind as s, type GraderUsage as t, type GradingState as u, type InteractionEvent as v, type InteractionKind as w, type ItemOutcome as x, type LearnerResponseMap as y, type MultipleChoiceData as z };
@@ -77,13 +77,21 @@ declare function matchText(input: string, accepted: string | readonly string[],
77
77
  * The SDK models the SHAPE and the arithmetic. It never calls a model, never
78
78
  * holds a key, and never decides what a rubric means — that stays yours.
79
79
  */
80
+
80
81
  /**
81
82
  * Lifecycle of a deferred grade. A grade exists only in the `graded` state;
82
83
  * every other state means "no grade, and here is why" — which is precisely the
83
84
  * distinction that stops an ungraded submission being rendered as a zero.
84
85
  */
85
86
  type GradingState = 'queued' | 'running' | 'graded' | 'failed' | 'skipped';
86
- /** Who produced a grade. */
87
+ /**
88
+ * Who produced a grade.
89
+ *
90
+ * - `'auto'` — a non-generative measurement engine, for example a
91
+ * pronunciation-assessment service.
92
+ * - `'ai'` — a generative model.
93
+ * - `'human'` — a person.
94
+ */
87
95
  type GraderKind = 'ai' | 'human' | 'auto';
88
96
  /** Provenance of a grade, so a re-grade two years later is explicable. */
89
97
  interface Grader {
@@ -166,6 +174,12 @@ interface GradeRecord {
166
174
  feedback: string | null;
167
175
  /** Per-criterion breakdown, when the grader worked against a rubric. */
168
176
  criteria?: CriterionScore[];
177
+ /**
178
+ * Per-item marks carried by a grade — for example the per-word marks of a
179
+ * read-aloud grade. `outcomeFromGrade` does not mirror them onto the
180
+ * outcome; read `outcome.grade.details`.
181
+ */
182
+ details?: ScoringDetail[];
169
183
  /** Corrections anchored in the learner's text. */
170
184
  corrections?: InlineCorrection[];
171
185
  /** Supporting observations the grader cited. */
@@ -361,6 +375,7 @@ interface ActivityDataMap {
361
375
  'written-response': WrittenResponseData;
362
376
  'gap-select': GapSelectData;
363
377
  dictation: DictationData;
378
+ 'read-aloud': ReadAloudData;
364
379
  }
365
380
  /**
366
381
  * The set of activity types supported by learning-kit. Derived from
@@ -885,6 +900,96 @@ interface DictationData {
885
900
  /** Subjective difficulty on a 1–5 scale. */
886
901
  difficultyLevel?: 1 | 2 | 3 | 4 | 5;
887
902
  }
903
+ /** A dimension of speech a pronunciation assessor scores, on a 0–100 scale. */
904
+ type ReadAloudDimension = 'accuracy' | 'fluency' | 'completeness' | 'prosody';
905
+ /** One assessor dimension counted towards a read-aloud grade, and its weight. */
906
+ interface ReadAloudDimensionWeight {
907
+ name: ReadAloudDimension;
908
+ /**
909
+ * Relative weight, 0..1000 (`READ_ALOUD_MAX_DIMENSION_WEIGHT`). Weights need
910
+ * not add up to anything; a weight of 0 leaves the dimension out of the grade.
911
+ */
912
+ weight: number;
913
+ }
914
+ /**
915
+ * The limits on a read-aloud take, applied where the learner records. No grade
916
+ * reads them: whether a take is plausible speech is decided from the server's
917
+ * own measurement of the recording, never from a bound the client enforced.
918
+ */
919
+ interface RecordingBounds {
920
+ /** The longest take, in seconds: above 0, and at most `READ_ALOUD_MAX_SECONDS` (300). */
921
+ maxSeconds: number;
922
+ /** The shortest take, in seconds: at least 0, and below `maxSeconds`. */
923
+ minSeconds?: number;
924
+ /** How many takes the learner may record: a whole number from 1 to `READ_ALOUD_MAX_TAKES` (20). */
925
+ maxTakes?: number;
926
+ }
927
+ /**
928
+ * A second, slower model recording of the reference text — a separate file,
929
+ * not a `playbackRate` change. It carries no `captionsUrl` and no `playback`
930
+ * policy of its own, requires `media`, must be a different file from it, and
931
+ * cannot accompany a play limit on `media`.
932
+ */
933
+ interface ReadAloudSlowMedia {
934
+ type: 'audio';
935
+ /** Source URL, under the same policy as {@link ActivityMedia.url}. */
936
+ url: string;
937
+ /** Accessible label — a description ("Model recording, slow"). */
938
+ alt?: string;
939
+ }
940
+ /**
941
+ * Data contract for a Read Aloud activity: the learner reads a text aloud, an
942
+ * assessor measures the recording, and the grade is the weighted total of the
943
+ * assessor's dimension scores.
944
+ *
945
+ * Grading is deferred — `evaluate()` returns `deferred` until the application
946
+ * holds an assessment — and nothing here is an answer key: the learner is shown
947
+ * the text they are asked to read.
948
+ */
949
+ interface ReadAloudData {
950
+ schemaVersion: '1.0';
951
+ type: 'read-aloud';
952
+ /** Unique identifier for this activity. */
953
+ id: string;
954
+ /** Human-readable title used in xAPI statements and error boundaries. */
955
+ title: string;
956
+ /** Optional instructions shown to the learner, as plain text. */
957
+ instructions?: string;
958
+ /**
959
+ * The text the learner reads aloud. Shown to the learner (public). At most
960
+ * `READ_ALOUD_MAX_REFERENCE_LENGTH` code points before and after
961
+ * normalisation, in a script written with spaces between words.
962
+ */
963
+ referenceText: string;
964
+ /**
965
+ * BCP 47 tag in canonical form with a region (e.g. `en-US`). GRADE-DECIDING:
966
+ * an assessment made for another locale is unscorable.
967
+ */
968
+ locale: string;
969
+ /** A model recording of the text. Audio only; a playback policy is allowed. */
970
+ media?: ActivityMedia;
971
+ /** A second, slower model recording. See {@link ReadAloudSlowMedia}. */
972
+ slowMedia?: ReadAloudSlowMedia;
973
+ /** The limits on a take. See {@link RecordingBounds}. */
974
+ recording: RecordingBounds;
975
+ /**
976
+ * The assessor dimensions the grade is made of, with their weights: 1 to 4
977
+ * entries, each name at most once, at least one weight above 0. A weighted
978
+ * dimension the assessment has no score for makes the take unscorable, never
979
+ * a zero. Public.
980
+ */
981
+ scoring: {
982
+ dimensions: ReadAloudDimensionWeight[];
983
+ };
984
+ /** Minimum scaled score [0–1] required to pass once graded. Defaults to {@link DEFAULT_PASS_THRESHOLD} (0.7) when absent. */
985
+ passThreshold?: number;
986
+ /** Optional authored overall feedback, selected once the grade exists. */
987
+ feedback?: ActivityFeedback;
988
+ /** IRI references to learning objectives addressed by this activity. */
989
+ learningObjectives?: string[];
990
+ /** Subjective difficulty on a 1–5 scale. */
991
+ difficultyLevel?: 1 | 2 | 3 | 4 | 5;
992
+ }
888
993
  /**
889
994
  * Maps each ActivityType string to its learner-response shape. Open for
890
995
  * extension via module augmentation, mirroring {@link ActivityDataMap}.
@@ -895,6 +1000,7 @@ interface LearnerResponseMap {
895
1000
  'written-response': WrittenResponseLearnerResponse;
896
1001
  'gap-select': GapSelectLearnerResponse;
897
1002
  dictation: DictationLearnerResponse;
1003
+ 'read-aloud': ReadAloudLearnerResponse;
898
1004
  }
899
1005
  /** Union of all learner response shapes. */
900
1006
  type LearnerResponse = LearnerResponseMap[keyof LearnerResponseMap];
@@ -947,6 +1053,28 @@ interface DictationLearnerResponse {
947
1053
  /** Hint words revealed before submitting (practice only). Absent or 0 means none. */
948
1054
  hintsRevealed?: number;
949
1055
  }
1056
+ /**
1057
+ * A learner recording held by the application. `key` is opaque,
1058
+ * application-issued storage identity: never a URL or bytes. `durationMs` is a
1059
+ * client claim no grade reads.
1060
+ */
1061
+ interface RecordingRef {
1062
+ key: string;
1063
+ /** The media type the recording was stored as, e.g. `audio/wav`. */
1064
+ mimeType: string;
1065
+ durationMs?: number;
1066
+ }
1067
+ /**
1068
+ * Learner response for a Read Aloud activity: a reference to the recording the
1069
+ * application stored, never the audio itself.
1070
+ */
1071
+ interface ReadAloudLearnerResponse {
1072
+ type: 'read-aloud';
1073
+ /** `null`: the learner submitted without recording (a blank). A take that failed to upload is never `null`. */
1074
+ recording: RecordingRef | null;
1075
+ /** Telemetry: takes used. No grade reads it. */
1076
+ takes?: number;
1077
+ }
950
1078
  /**
951
1079
  * Fine-grained outcome of the learner's action on a single item, replacing the
952
1080
  * ambiguous {@link ScoringDetail.correct}:
@@ -989,7 +1117,9 @@ interface ScoringDetail {
989
1117
  * The item's own scaled score in [0, 1], for a type that grades its items on
990
1118
  * a continuum rather than right or wrong. Written by the dictation scorer
991
1119
  * (the similarity of each transcript word to what was typed for it) and by
992
- * nothing else today. Absent, an item is right or wrong: read `outcome`.
1120
+ * `gradeReadAloud` (the assessor's accuracy for each reference word as a
1121
+ * fraction, 0 for an omitted word, and absent where the assessor gave none).
1122
+ * Absent, an item is right or wrong: read `outcome`.
993
1123
  */
994
1124
  score?: number;
995
1125
  }
@@ -1082,6 +1212,11 @@ type ItemOutcome = {
1082
1212
  reason: string;
1083
1213
  /** Maximum possible scaled score, when known. */
1084
1214
  maxScore: number;
1215
+ /**
1216
+ * A machine-readable reason, written by `outcomeFromUnscorable` — for
1217
+ * example a read-aloud `SpeechUnscorableCode`. `evaluate` never writes it.
1218
+ */
1219
+ code?: string;
1085
1220
  };
1086
1221
  /** A single validation error produced by `validateActivity`. */
1087
1222
  interface ValidationError {
@@ -1134,7 +1269,21 @@ type InteractionKind = 'option-selected' | 'option-deselected' | 'blank-filled'
1134
1269
  /** A charged play produced no audio — a failed or expired media URL. */
1135
1270
  | 'media-play-errored'
1136
1271
  /** A charged play was returned, because the consumer accepted the refund. */
1137
- | 'media-play-refunded' | (string & {});
1272
+ | 'media-play-refunded'
1273
+ /** The microphone began capturing a take. */
1274
+ | 'recording-started'
1275
+ /** A take ended, by the learner or at its time limit. */
1276
+ | 'recording-stopped'
1277
+ /** A take was thrown away, to record another. */
1278
+ | 'recording-discarded'
1279
+ /** The application stored a take and returned its reference. */
1280
+ | 'recording-uploaded'
1281
+ /** Storing a take failed. A take that failed to upload is never a blank answer. */
1282
+ | 'recording-upload-failed'
1283
+ /** A stored take was sent for assessment. */
1284
+ | 'assessment-requested'
1285
+ /** An assessment request failed: the take has no grade. */
1286
+ | 'assessment-failed' | (string & {});
1138
1287
  /** Fired by activity components on every discrete learner interaction. */
1139
1288
  interface InteractionEvent {
1140
1289
  /** The kind of interaction that occurred. */
@@ -1147,4 +1296,4 @@ interface InteractionEvent {
1147
1296
  payload: Record<string, unknown>;
1148
1297
  }
1149
1298
 
1150
- export { type XAPIError as $, type ActivityData as A, type BlankConfig as B, type CriterionScore as C, type DeferredScoringPartial as D, type MultipleChoiceOption as E, type FillInTheBlanksData as F, type GapSelectBank as G, type MultipleChoiceOptionMedia as H, type InlineCorrection as I, type ScoringOutcome as J, type ScoringResult as K, type LearnerResponse as L, type MediaPlaybackPolicy as M, type NativeControlHint as N, type TextMatchResult as O, type ValidationResult as P, type WrittenResponseLearnerResponse as Q, type WrittenResponseRubric as R, type ScoringDetail as S, type TextMatchPolicy as T, type WrittenResponseRubricCriterion as U, type ValidationError as V, type WrittenResponseData as W, type XAPIActor as X, type XAPIConfig as Y, type XAPIContext as Z, type XAPIContextActivities as _, type ActivityDataMap as a, type XAPIObject as a0, type XAPIResult as a1, type XAPIScore as a2, type XAPIStatement as a3, type XAPIVerbObject as a4, levenshteinDistance as a5, matchText as a6, type ActivityFeedback as b, type ActivityMedia as c, type ActivityResult as d, type ActivityType as e, type DictationData as f, type DictationEquivalence as g, type DictationLearnerResponse as h, type DictationSlowMedia as i, type DictationTolerance as j, type FillInTheBlanksLearnerResponse as k, type GapSelectChoice as l, type GapSelectData as m, type GapSelectGap as n, type GapSelectLearnerResponse as o, type GradeRecord as p, type Grader as q, type GraderKind as r, type GraderUsage as s, type GradingState as t, type InteractionEvent as u, type InteractionKind as v, type ItemOutcome as w, type LearnerResponseMap as x, type MultipleChoiceData as y, type MultipleChoiceLearnerResponse as z };
1299
+ export { type WrittenResponseData as $, type ActivityData as A, type BlankConfig as B, type CriterionScore as C, type DeferredReason as D, type MultipleChoiceLearnerResponse as E, type FillInTheBlanksData as F, type GapSelectBank as G, type MultipleChoiceOption as H, type InlineCorrection as I, type MultipleChoiceOptionMedia as J, type ReadAloudDimension as K, type LearnerResponse as L, type MediaPlaybackPolicy as M, type NativeControlHint as N, type ReadAloudDimensionWeight as O, type ReadAloudLearnerResponse as P, type ReadAloudSlowMedia as Q, type ReadAloudData as R, type RecordingBounds as S, type RecordingRef as T, type ScoringDetail as U, type ScoringOutcome as V, type ScoringResult as W, type TextMatchPolicy as X, type TextMatchResult as Y, type ValidationError as Z, type ValidationResult as _, type ActivityDataMap as a, type WrittenResponseLearnerResponse as a0, type WrittenResponseRubric as a1, type WrittenResponseRubricCriterion as a2, type XAPIActor as a3, type XAPIConfig as a4, type XAPIContext as a5, type XAPIContextActivities as a6, type XAPIError as a7, type XAPIObject as a8, type XAPIResult as a9, type XAPIScore as aa, type XAPIStatement as ab, type XAPIVerbObject as ac, levenshteinDistance as ad, matchText as ae, type ActivityFeedback as b, type ActivityMedia as c, type ActivityResult as d, type ActivityType as e, type DeferredScoringPartial as f, type DictationData as g, type DictationEquivalence as h, type DictationLearnerResponse as i, type DictationSlowMedia as j, type DictationTolerance as k, type FillInTheBlanksLearnerResponse as l, type GapSelectChoice as m, type GapSelectData as n, type GapSelectGap as o, type GapSelectLearnerResponse as p, type GradeRecord as q, type Grader as r, type GraderKind as s, type GraderUsage as t, type GradingState as u, type InteractionEvent as v, type InteractionKind as w, type ItemOutcome as x, type LearnerResponseMap as y, type MultipleChoiceData as z };
@@ -10,7 +10,8 @@
10
10
 
11
11
 
12
12
 
13
- var _chunkXONKWL6Dcjs = require('./chunk-XONKWL6D.cjs');
13
+
14
+ var _chunkVCXIPLEWcjs = require('./chunk-VCXIPLEW.cjs');
14
15
 
15
16
  // src/schemas/item-group.ts
16
17
  var _v4 = require('zod/v4');
@@ -38,7 +39,7 @@ var StimulusSchema = _v4.z.looseObject({
38
39
  title: _v4.z.string().optional(),
39
40
  body: _v4.z.string().optional(),
40
41
  bodyHtml: _v4.z.string().optional(),
41
- media: _chunkXONKWL6Dcjs.MediaSchema.optional(),
42
+ media: _chunkVCXIPLEWcjs.MediaSchema.optional(),
42
43
  transcript: _v4.z.string().optional(),
43
44
  locale: _v4.z.string().optional(),
44
45
  attribution: _v4.z.string().optional()
@@ -88,7 +89,7 @@ var RedactedStimulusSchema = _v4.z.strictObject({
88
89
  title: _v4.z.string().optional(),
89
90
  body: _v4.z.string().optional(),
90
91
  bodyHtml: _v4.z.string().optional(),
91
- media: _chunkXONKWL6Dcjs.RedactedMediaSchema.optional(),
92
+ media: _chunkVCXIPLEWcjs.RedactedMediaSchema.optional(),
92
93
  locale: _v4.z.string().optional(),
93
94
  attribution: _v4.z.string().optional()
94
95
  });
@@ -103,11 +104,11 @@ var RedactedItemGroupSchema = _v4.z.strictObject({
103
104
  items: _v4.z.array(_v4.z.unknown()).min(1),
104
105
  shuffle: _v4.z.enum(["none", "within-group"]).optional()
105
106
  }).check((ctx) => {
106
- if (_chunkXONKWL6Dcjs.groupCaptionsRevealDictation.call(void 0, ctx.value)) {
107
+ if (_chunkVCXIPLEWcjs.groupCaptionsRevealDictation.call(void 0, ctx.value)) {
107
108
  ctx.issues.push({
108
109
  code: "custom",
109
110
  input: _optionalChain([ctx, 'access', _ => _.value, 'access', _2 => _2.stimulus, 'access', _3 => _3.media, 'optionalAccess', _4 => _4.captionsUrl]),
110
- message: _chunkXONKWL6Dcjs.GROUP_CAPTIONS_REVEAL_DICTATION,
111
+ message: _chunkVCXIPLEWcjs.GROUP_CAPTIONS_REVEAL_DICTATION,
111
112
  path: ["stimulus", "media", "captionsUrl"]
112
113
  });
113
114
  }
@@ -127,7 +128,7 @@ function validateItemGroup(data) {
127
128
  const errors = [];
128
129
  const items = [];
129
130
  container.data.items.forEach((item, index) => {
130
- const descriptor = _chunkXONKWL6Dcjs.getActivityTypeDescriptor.call(void 0, item.type);
131
+ const descriptor = _chunkVCXIPLEWcjs.getActivityTypeDescriptor.call(void 0, item.type);
131
132
  if (descriptor === void 0) {
132
133
  errors.push({
133
134
  path: ["items", String(index), "type"],
@@ -143,10 +144,10 @@ function validateItemGroup(data) {
143
144
  }
144
145
  items.push(parsed.data);
145
146
  });
146
- if (_chunkXONKWL6Dcjs.groupCaptionsRevealDictation.call(void 0, container.data)) {
147
+ if (_chunkVCXIPLEWcjs.groupCaptionsRevealDictation.call(void 0, container.data)) {
147
148
  errors.push({
148
149
  path: ["stimulus", "media", "captionsUrl"],
149
- message: _chunkXONKWL6Dcjs.GROUP_CAPTIONS_REVEAL_DICTATION,
150
+ message: _chunkVCXIPLEWcjs.GROUP_CAPTIONS_REVEAL_DICTATION,
150
151
  code: "custom"
151
152
  });
152
153
  }
@@ -160,34 +161,37 @@ function validateItemGroup(data) {
160
161
 
161
162
  var stimulusJsonSchema = _v4.z.toJSONSchema(StimulusSchema, { target: "draft-7" });
162
163
  var itemGroupJsonSchema = _v4.z.toJSONSchema(ItemGroupSchema, { target: "draft-7" });
163
- var gapSelectJsonSchema = _v4.z.toJSONSchema(_chunkXONKWL6Dcjs.GapSelectDataSchema, {
164
+ var gapSelectJsonSchema = _v4.z.toJSONSchema(_chunkVCXIPLEWcjs.GapSelectDataSchema, {
165
+ target: "draft-7"
166
+ });
167
+ var dictationJsonSchema = _v4.z.toJSONSchema(_chunkVCXIPLEWcjs.DictationDataSchema, {
164
168
  target: "draft-7"
165
169
  });
166
- var dictationJsonSchema = _v4.z.toJSONSchema(_chunkXONKWL6Dcjs.DictationDataSchema, {
170
+ var readAloudJsonSchema = _v4.z.toJSONSchema(_chunkVCXIPLEWcjs.ReadAloudDataSchema, {
167
171
  target: "draft-7"
168
172
  });
169
- var multipleChoiceJsonSchema = _v4.z.toJSONSchema(_chunkXONKWL6Dcjs.MultipleChoiceDataSchema, {
173
+ var multipleChoiceJsonSchema = _v4.z.toJSONSchema(_chunkVCXIPLEWcjs.MultipleChoiceDataSchema, {
170
174
  target: "draft-7"
171
175
  });
172
- var fillInTheBlanksJsonSchema = _v4.z.toJSONSchema(_chunkXONKWL6Dcjs.FillInTheBlanksDataSchema, {
176
+ var fillInTheBlanksJsonSchema = _v4.z.toJSONSchema(_chunkVCXIPLEWcjs.FillInTheBlanksDataSchema, {
173
177
  target: "draft-7"
174
178
  });
175
- var writtenResponseJsonSchema = _v4.z.toJSONSchema(_chunkXONKWL6Dcjs.WrittenResponseDataSchema, {
179
+ var writtenResponseJsonSchema = _v4.z.toJSONSchema(_chunkVCXIPLEWcjs.WrittenResponseDataSchema, {
176
180
  target: "draft-7"
177
181
  });
178
182
  function jsonSchemaFor(type) {
179
- const descriptor = _chunkXONKWL6Dcjs.getActivityTypeDescriptor.call(void 0, type);
183
+ const descriptor = _chunkVCXIPLEWcjs.getActivityTypeDescriptor.call(void 0, type);
180
184
  if (descriptor === void 0) {
181
- throw new (0, _chunkXONKWL6Dcjs.UnknownActivityTypeError)(type);
185
+ throw new (0, _chunkVCXIPLEWcjs.UnknownActivityTypeError)(type);
182
186
  }
183
187
  return _v4.z.toJSONSchema(descriptor.schema, { target: "draft-7" });
184
188
  }
185
189
 
186
190
  // src/schemas/index.ts
187
191
  function validateActivity(type, data) {
188
- const descriptor = _chunkXONKWL6Dcjs.getActivityTypeDescriptor.call(void 0, type);
192
+ const descriptor = _chunkVCXIPLEWcjs.getActivityTypeDescriptor.call(void 0, type);
189
193
  if (descriptor === void 0) {
190
- throw new (0, _chunkXONKWL6Dcjs.UnknownActivityTypeError)(String(type));
194
+ throw new (0, _chunkVCXIPLEWcjs.UnknownActivityTypeError)(String(type));
191
195
  }
192
196
  const result = descriptor.schema.safeParse(data);
193
197
  if (result.success) {
@@ -218,5 +222,6 @@ function validateActivity(type, data) {
218
222
 
219
223
 
220
224
 
221
- exports.StimulusSchema = StimulusSchema; exports.ItemGroupSchema = ItemGroupSchema; exports.RedactedStimulusSchema = RedactedStimulusSchema; exports.RedactedItemGroupSchema = RedactedItemGroupSchema; exports.validateItemGroup = validateItemGroup; exports.stimulusJsonSchema = stimulusJsonSchema; exports.itemGroupJsonSchema = itemGroupJsonSchema; exports.gapSelectJsonSchema = gapSelectJsonSchema; exports.dictationJsonSchema = dictationJsonSchema; exports.multipleChoiceJsonSchema = multipleChoiceJsonSchema; exports.fillInTheBlanksJsonSchema = fillInTheBlanksJsonSchema; exports.writtenResponseJsonSchema = writtenResponseJsonSchema; exports.jsonSchemaFor = jsonSchemaFor; exports.validateActivity = validateActivity;
222
- //# sourceMappingURL=chunk-DQKJUMUW.cjs.map
225
+
226
+ exports.StimulusSchema = StimulusSchema; exports.ItemGroupSchema = ItemGroupSchema; exports.RedactedStimulusSchema = RedactedStimulusSchema; exports.RedactedItemGroupSchema = RedactedItemGroupSchema; exports.validateItemGroup = validateItemGroup; exports.stimulusJsonSchema = stimulusJsonSchema; exports.itemGroupJsonSchema = itemGroupJsonSchema; exports.gapSelectJsonSchema = gapSelectJsonSchema; exports.dictationJsonSchema = dictationJsonSchema; exports.readAloudJsonSchema = readAloudJsonSchema; exports.multipleChoiceJsonSchema = multipleChoiceJsonSchema; exports.fillInTheBlanksJsonSchema = fillInTheBlanksJsonSchema; exports.writtenResponseJsonSchema = writtenResponseJsonSchema; exports.jsonSchemaFor = jsonSchemaFor; exports.validateActivity = validateActivity;
227
+ //# sourceMappingURL=chunk-2NIALQEH.cjs.map