@intellectif/lk-core 1.5.0 → 1.7.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/CHANGELOG.md +77 -0
- package/dist/{ai-BYryFkF9.d.ts → ai-B1wYrqcB.d.cts} +83 -18
- package/dist/ai-B1wYrqcB.d.cts.map +1 -0
- package/dist/{ai-BYryFkF9.d.cts → ai-B1wYrqcB.d.ts} +83 -18
- package/dist/ai-B1wYrqcB.d.ts.map +1 -0
- package/dist/ai-check.cjs +13 -6
- package/dist/ai-check.cjs.map +1 -1
- package/dist/ai-check.d.cts +1 -5
- package/dist/ai-check.d.cts.map +1 -1
- package/dist/ai-check.d.ts +1 -5
- package/dist/ai-check.d.ts.map +1 -1
- package/dist/ai-check.js +13 -6
- package/dist/ai-check.js.map +1 -1
- package/dist/{ai-writing-D8PdhJJz.js → ai-writing-B7oMCt66.js} +311 -66
- package/dist/ai-writing-B7oMCt66.js.map +1 -0
- package/dist/{ai-writing-Cen7-3qs.cjs → ai-writing-DrPTV3R2.cjs} +313 -50
- package/dist/ai-writing-DrPTV3R2.cjs.map +1 -0
- package/dist/{index-DUaW1Tj5.d.ts → index-BM8LeDWn.d.cts} +2 -42
- package/dist/index-BM8LeDWn.d.cts.map +1 -0
- package/dist/{index-Bg0aeWtM.d.cts → index-BTkMQtws.d.ts} +2 -42
- package/dist/index-BTkMQtws.d.ts.map +1 -0
- package/dist/{index-wMc1E_aM.d.ts → index-BU99GFTl.d.ts} +2 -8
- package/dist/index-BU99GFTl.d.ts.map +1 -0
- package/dist/{index-CxpiWedW.d.ts → index-BdXs4-en.d.ts} +42 -20
- package/dist/index-BdXs4-en.d.ts.map +1 -0
- package/dist/{index-qMbxed1B.d.cts → index-DP9rvyOz.d.cts} +42 -20
- package/dist/index-DP9rvyOz.d.cts.map +1 -0
- package/dist/{index-D7R3Ll8R.d.cts → index-XCCoPoTU.d.cts} +2 -8
- package/dist/index-XCCoPoTU.d.cts.map +1 -0
- package/dist/index.cjs +70 -21
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +135 -69
- package/dist/index.d.cts.map +1 -1
- package/dist/index.d.ts +135 -69
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +65 -22
- package/dist/index.js.map +1 -1
- package/dist/{item-group-DEB7nLID.cjs → item-group-8P3WFuUK.cjs} +5 -6
- package/dist/item-group-8P3WFuUK.cjs.map +1 -0
- package/dist/{item-group-DdSUCUjM.js → item-group-CeDk7mfM.js} +5 -6
- package/dist/item-group-CeDk7mfM.js.map +1 -0
- package/dist/{registry-DaZRpqjW.js → registry-D92hz9iA.js} +124 -106
- package/dist/registry-D92hz9iA.js.map +1 -0
- package/dist/{registry-Ce00A_OW.cjs → registry-hzrkTeIT.cjs} +142 -107
- package/dist/registry-hzrkTeIT.cjs.map +1 -0
- package/dist/{schemas-DksueYsu.cjs → schemas-BWeskONy.cjs} +79 -18
- package/dist/schemas-BWeskONy.cjs.map +1 -0
- package/dist/{schemas-BioKFf3F.js → schemas-C7TViWCg.js} +74 -19
- package/dist/schemas-C7TViWCg.js.map +1 -0
- package/dist/schemas.cjs +5 -2
- package/dist/schemas.d.cts +2 -2
- package/dist/schemas.d.ts +2 -2
- package/dist/schemas.js +4 -3
- package/dist/{scoring-lKQVYsxy.cjs → scoring-CtkCFyFT.cjs} +22 -42
- package/dist/{scoring-lKQVYsxy.cjs.map → scoring-CtkCFyFT.cjs.map} +1 -1
- package/dist/{scoring-BKNNTz-s.js → scoring-DD1GHcLI.js} +22 -42
- package/dist/{scoring-BKNNTz-s.js.map → scoring-DD1GHcLI.js.map} +1 -1
- package/dist/scoring.cjs +2 -2
- package/dist/scoring.d.cts +2 -2
- package/dist/scoring.d.ts +2 -2
- package/dist/scoring.js +2 -2
- package/dist/{xapi-NYrTlpID.cjs → xapi-7btSpx6v.cjs} +5 -8
- package/dist/{xapi-NYrTlpID.cjs.map → xapi-7btSpx6v.cjs.map} +1 -1
- package/dist/{xapi-wR6gu4qS.js → xapi-Cgicg-zU.js} +5 -8
- package/dist/{xapi-wR6gu4qS.js.map → xapi-Cgicg-zU.js.map} +1 -1
- package/dist/xapi.cjs +1 -1
- package/dist/xapi.d.cts +1 -1
- package/dist/xapi.d.ts +1 -1
- package/dist/xapi.js +1 -1
- package/package.json +2 -2
- package/dist/ai-BYryFkF9.d.cts.map +0 -1
- package/dist/ai-BYryFkF9.d.ts.map +0 -1
- package/dist/ai-writing-Cen7-3qs.cjs.map +0 -1
- package/dist/ai-writing-D8PdhJJz.js.map +0 -1
- package/dist/index-Bg0aeWtM.d.cts.map +0 -1
- package/dist/index-CxpiWedW.d.ts.map +0 -1
- package/dist/index-D7R3Ll8R.d.cts.map +0 -1
- package/dist/index-DUaW1Tj5.d.ts.map +0 -1
- package/dist/index-qMbxed1B.d.cts.map +0 -1
- package/dist/index-wMc1E_aM.d.ts.map +0 -1
- package/dist/item-group-DEB7nLID.cjs.map +0 -1
- package/dist/item-group-DdSUCUjM.js.map +0 -1
- package/dist/registry-Ce00A_OW.cjs.map +0 -1
- package/dist/registry-DaZRpqjW.js.map +0 -1
- package/dist/schemas-BioKFf3F.js.map +0 -1
- package/dist/schemas-DksueYsu.cjs.map +0 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import * as z from "zod/v4";
|
|
2
2
|
import { $ZodCheck } from "zod/v4/core";
|
|
3
|
-
|
|
3
|
+
// src/schemas/ai.ts
|
|
4
4
|
/**
|
|
5
5
|
* What an author allows AI to do for one item: see `ActivityAiPermissions`.
|
|
6
6
|
* Loose like every content schema, so a key a later release adds survives an
|
|
@@ -10,8 +10,7 @@ const AiPermissionsSchema = z.looseObject({
|
|
|
10
10
|
explanations: z.boolean().optional(),
|
|
11
11
|
hints: z.boolean().optional()
|
|
12
12
|
});
|
|
13
|
-
|
|
14
|
-
//#region src/schemas/feedback.ts
|
|
13
|
+
// src/schemas/feedback.ts
|
|
15
14
|
/**
|
|
16
15
|
* Optional authored "overall feedback" shown after submission, selected by
|
|
17
16
|
* whether the learner passed (h5p-style overall feedback). Both fields are
|
|
@@ -21,8 +20,7 @@ const FeedbackSchema = z.looseObject({
|
|
|
21
20
|
correct: z.string().min(1).optional(),
|
|
22
21
|
incorrect: z.string().min(1).optional()
|
|
23
22
|
});
|
|
24
|
-
|
|
25
|
-
//#region src/schemas/text-length.ts
|
|
23
|
+
// src/schemas/text-length.ts
|
|
26
24
|
/**
|
|
27
25
|
* `schema`, refusing a string longer than `max` UTF-16 code units — its
|
|
28
26
|
* JavaScript `length`, the unit these limits have always counted in.
|
|
@@ -45,8 +43,7 @@ function maxUnits(schema, max) {
|
|
|
45
43
|
});
|
|
46
44
|
}).meta({ maxLength: max });
|
|
47
45
|
}
|
|
48
|
-
|
|
49
|
-
//#region src/schemas/media.ts
|
|
46
|
+
// src/schemas/media.ts
|
|
50
47
|
/**
|
|
51
48
|
* Optional media attached to an activity, rendered above the question or
|
|
52
49
|
* passage — e.g. a recording to listen to, or an embedded video to watch
|
|
@@ -134,6 +131,20 @@ const MediaTrackSchema = z.strictObject({
|
|
|
134
131
|
default: z.boolean().optional()
|
|
135
132
|
});
|
|
136
133
|
const MAX_TRACKS = 12;
|
|
134
|
+
/** The most turns a recording's `script` may hold. */
|
|
135
|
+
const SCRIPT_MAX_TURNS = 500;
|
|
136
|
+
/**
|
|
137
|
+
* One speaker's turn in an author-only `script`. Loose, as content is: a host
|
|
138
|
+
* may keep its own fields on a turn (the voice it cast, a direction for it).
|
|
139
|
+
* Unlike a track's, both fields are required, so a misspelt one is still
|
|
140
|
+
* caught.
|
|
141
|
+
*/
|
|
142
|
+
const ScriptTurnSchema = z.looseObject({
|
|
143
|
+
speaker: maxUnits(z.string(), 60).refine((speaker) => speaker.trim().length > 0, { error: "A script turn needs a speaker." }),
|
|
144
|
+
text: z.string().refine((text) => text.trim().length > 0, { error: "A script turn needs words." })
|
|
145
|
+
});
|
|
146
|
+
/** An author-only `script`: one turn or more, in the order they are spoken. */
|
|
147
|
+
const ScriptSchema = z.array(ScriptTurnSchema).min(1).max(500);
|
|
137
148
|
/** `poster` on anything but a video: an image with nothing to stand in for. */
|
|
138
149
|
function posterFits(m) {
|
|
139
150
|
return m.poster === void 0 || m.type === "video";
|
|
@@ -176,7 +187,9 @@ const MediaSchema = z.looseObject({
|
|
|
176
187
|
captionsUrl: MediaUrlSchema.optional(),
|
|
177
188
|
tracks: z.array(MediaTrackSchema).min(1).max(MAX_TRACKS).optional(),
|
|
178
189
|
poster: MediaUrlSchema.optional(),
|
|
179
|
-
playback: MediaPlaybackSchema.optional()
|
|
190
|
+
playback: MediaPlaybackSchema.optional(),
|
|
191
|
+
transcript: z.string().optional(),
|
|
192
|
+
script: ScriptSchema.optional()
|
|
180
193
|
}).refine((m) => m.type !== "image" && m.type !== "embed" || typeof m.alt === "string" && m.alt.length > 0, {
|
|
181
194
|
error: "image and embed media require non-empty alt text (WCAG 1.1.1 / 4.1.2).",
|
|
182
195
|
path: ["alt"]
|
|
@@ -228,8 +241,7 @@ const RedactedMediaSchema = z.strictObject({
|
|
|
228
241
|
error: "embed media requires an absolute http(s) provider URL. data:, blob:, and relative URLs are not allowed for embeds — the embed iframe runs with allow-scripts, and a data:/same-origin document there is an XSS vector.",
|
|
229
242
|
path: ["url"]
|
|
230
243
|
}).refine(posterFits, POSTER_FITS).refine(tracksFit, TRACKS_FIT).refine(tracksAreDistinct, TRACKS_DISTINCT);
|
|
231
|
-
|
|
232
|
-
//#region src/schemas/fill-in-the-blanks.ts
|
|
244
|
+
// src/schemas/fill-in-the-blanks.ts
|
|
233
245
|
/**
|
|
234
246
|
* Matches `{{ blank_id }}` placeholders in a passage, capturing the trimmed id.
|
|
235
247
|
* Exported for the draft checks in `authoring/`, which must read a passage
|
|
@@ -237,6 +249,12 @@ const RedactedMediaSchema = z.strictObject({
|
|
|
237
249
|
*/
|
|
238
250
|
const PLACEHOLDER_RE = /\{\{\s*([^{}]+?)\s*\}\}/g;
|
|
239
251
|
/**
|
|
252
|
+
* The instructions of an item with a passage: plain text, with no `{{id}}`
|
|
253
|
+
* placeholder. Blanks and gaps live in the passage only, and one written here
|
|
254
|
+
* would be shown to the learner as it stands. Shared by Gap Select.
|
|
255
|
+
*/
|
|
256
|
+
const PassageInstructionsSchema = z.string().refine((text) => text.match(PLACEHOLDER_RE) === null, { error: "The instructions are plain text: a {{id}} placeholder belongs in the passage, where its blank or gap is." });
|
|
257
|
+
/**
|
|
240
258
|
* Zod schema for a `TextMatchPolicy` — the opt-in matching tolerances a blank
|
|
241
259
|
* may declare. Every default reproduces the v1 trim + case-fold semantics.
|
|
242
260
|
*/
|
|
@@ -284,6 +302,7 @@ const FillInTheBlanksDataSchema = z.looseObject({
|
|
|
284
302
|
type: z.literal("fill-in-the-blanks"),
|
|
285
303
|
id: z.string().min(1),
|
|
286
304
|
title: z.string().min(1),
|
|
305
|
+
instructions: PassageInstructionsSchema.optional(),
|
|
287
306
|
passage: z.string().min(1),
|
|
288
307
|
passageHtml: z.string().optional(),
|
|
289
308
|
blanks: z.array(BlankConfigSchema).min(1),
|
|
@@ -315,8 +334,7 @@ const FillInTheBlanksDataSchema = z.looseObject({
|
|
|
315
334
|
error: "Each blank id must appear exactly once in blanks[] and have exactly one matching {{id}} placeholder in the passage, and vice versa.",
|
|
316
335
|
path: ["passage"]
|
|
317
336
|
});
|
|
318
|
-
|
|
319
|
-
//#region src/answer-leak.ts
|
|
337
|
+
// src/answer-leak.ts
|
|
320
338
|
/**
|
|
321
339
|
* Whether a text gives an answer away: the rule an AI hint is held to, and the
|
|
322
340
|
* one the item critic holds an author's own hint, title and passage to.
|
|
@@ -403,8 +421,7 @@ function revealsAnswer(text, answer, passage, position) {
|
|
|
403
421
|
if (before === void 0 && after === void 0) return containsWords(words, needle);
|
|
404
422
|
return before !== void 0 && containsWords(words, [before, ...needle]) || after !== void 0 && containsWords(words, [...needle, after]);
|
|
405
423
|
}
|
|
406
|
-
|
|
407
|
-
//#region src/built-in-types.ts
|
|
424
|
+
// src/built-in-types.ts
|
|
408
425
|
/**
|
|
409
426
|
* The activity types the SDK ships, in one closed list.
|
|
410
427
|
*
|
|
@@ -440,8 +457,7 @@ function isBuiltInActivityType(type) {
|
|
|
440
457
|
* @internal
|
|
441
458
|
*/
|
|
442
459
|
function everyBuiltInTypeHandled(_value) {}
|
|
443
|
-
|
|
444
|
-
//#region src/scoring/dictation/edit-distance.ts
|
|
460
|
+
// src/scoring/dictation/edit-distance.ts
|
|
445
461
|
/**
|
|
446
462
|
* The code points of `text`, as numbers. A surrogate pair is one code point; a
|
|
447
463
|
* lone surrogate iterates as one code point too — deterministic, never thrown.
|
|
@@ -493,8 +509,7 @@ function similarity(a, b) {
|
|
|
493
509
|
const max = Math.max(codePoints(a).length, codePoints(b).length);
|
|
494
510
|
return max === 0 ? 0 : (max - editDistance(a, b)) / max;
|
|
495
511
|
}
|
|
496
|
-
|
|
497
|
-
//#region src/validation-scope.ts
|
|
512
|
+
// src/validation-scope.ts
|
|
498
513
|
/**
|
|
499
514
|
* Work shared for the length of one outermost validation call.
|
|
500
515
|
*
|
|
@@ -533,8 +548,7 @@ function scopeCache(key, create) {
|
|
|
533
548
|
}
|
|
534
549
|
return value;
|
|
535
550
|
}
|
|
536
|
-
|
|
537
|
-
//#region src/scoring/dictation/unicode-joining.ts
|
|
551
|
+
// src/scoring/dictation/unicode-joining.ts
|
|
538
552
|
/**
|
|
539
553
|
* Unicode data the dictation normaliser reads when it decides whether a joiner
|
|
540
554
|
* changes how the text is drawn (see `normalize.ts`): the viramas, and which
|
|
@@ -752,8 +766,7 @@ const JOINS_BACKWARD = [
|
|
|
752
766
|
[69577, 69578],
|
|
753
767
|
[125184, 125251]
|
|
754
768
|
];
|
|
755
|
-
|
|
756
|
-
//#region src/scoring/dictation/normalize.ts
|
|
769
|
+
// src/scoring/dictation/normalize.ts
|
|
757
770
|
/**
|
|
758
771
|
* The longest transcript a dictation accepts, in code points, before and after
|
|
759
772
|
* its equivalences are applied — and its rules may not grow it past twice
|
|
@@ -1713,8 +1726,7 @@ function searchReveal(forms, candidate) {
|
|
|
1713
1726
|
return fields.some((field) => containsPhrase(field, phrase));
|
|
1714
1727
|
});
|
|
1715
1728
|
}
|
|
1716
|
-
|
|
1717
|
-
//#region src/scoring/dictation/align.ts
|
|
1729
|
+
// src/scoring/dictation/align.ts
|
|
1718
1730
|
/**
|
|
1719
1731
|
* The words the scorer can emit a detail for, one list per candidate — index 0
|
|
1720
1732
|
* is the transcript, index n is `acceptedTranscripts[n − 1]` — each word in the
|
|
@@ -1913,8 +1925,7 @@ function alignWords(reference, attempt) {
|
|
|
1913
1925
|
}
|
|
1914
1926
|
return words;
|
|
1915
1927
|
}
|
|
1916
|
-
|
|
1917
|
-
//#region src/errors.ts
|
|
1928
|
+
// src/errors.ts
|
|
1918
1929
|
/** Thrown when activity data fails schema validation at a component boundary. */
|
|
1919
1930
|
var ActivitySchemaError = class extends Error {
|
|
1920
1931
|
activityType;
|
|
@@ -1968,8 +1979,7 @@ var DeferredScoringError = class extends Error {
|
|
|
1968
1979
|
this.name = "DeferredScoringError";
|
|
1969
1980
|
}
|
|
1970
1981
|
};
|
|
1971
|
-
|
|
1972
|
-
//#region src/schemas/after-issues.ts
|
|
1982
|
+
// src/schemas/after-issues.ts
|
|
1973
1983
|
/**
|
|
1974
1984
|
* A check zod runs even when another field was refused. An ordinary check is
|
|
1975
1985
|
* skipped once any issue has been reported, so an author fixing a recording's
|
|
@@ -2006,8 +2016,7 @@ function parsedFields(payload) {
|
|
|
2006
2016
|
refused
|
|
2007
2017
|
};
|
|
2008
2018
|
}
|
|
2009
|
-
|
|
2010
|
-
//#region src/schemas/dictation.ts
|
|
2019
|
+
// src/schemas/dictation.ts
|
|
2011
2020
|
/**
|
|
2012
2021
|
* Zod schema for the slower second recording of a dictation. Loose like every
|
|
2013
2022
|
* content schema (a sidecar survives), audio only, and — deliberately — with no
|
|
@@ -2189,8 +2198,7 @@ function groupCaptionsField(group, written) {
|
|
|
2189
2198
|
}
|
|
2190
2199
|
/** The message every validator gives for {@link groupCaptionsRevealDictation}. */
|
|
2191
2200
|
const GROUP_CAPTIONS_REVEAL_DICTATION = "The stimulus recording carries captions, and a dictation in this group plays that recording: the captions are the answer. Remove the captions, or give the dictation its own recording.";
|
|
2192
|
-
|
|
2193
|
-
//#region src/authoring/issues.ts
|
|
2201
|
+
// src/authoring/issues.ts
|
|
2194
2202
|
/**
|
|
2195
2203
|
* Every issue code the SDK's draft checks can report, with its severity.
|
|
2196
2204
|
*
|
|
@@ -2526,8 +2534,7 @@ function coveredPathsOf(reported) {
|
|
|
2526
2534
|
}
|
|
2527
2535
|
return covered;
|
|
2528
2536
|
}
|
|
2529
|
-
|
|
2530
|
-
//#region src/authoring/dictation.ts
|
|
2537
|
+
// src/authoring/dictation.ts
|
|
2531
2538
|
/**
|
|
2532
2539
|
* Draft support for `dictation`.
|
|
2533
2540
|
*
|
|
@@ -2717,8 +2724,7 @@ function checkTolerance(tolerance) {
|
|
|
2717
2724
|
}
|
|
2718
2725
|
return issues;
|
|
2719
2726
|
}
|
|
2720
|
-
|
|
2721
|
-
//#region src/count-words.ts
|
|
2727
|
+
// src/count-words.ts
|
|
2722
2728
|
/**
|
|
2723
2729
|
* Canonical word counter for written-response bounds: tokens are
|
|
2724
2730
|
* maximal runs of non-whitespace (split on `\s+`), so hyphenated forms
|
|
@@ -2823,8 +2829,7 @@ function levelDistribution(values, count, chosen) {
|
|
|
2823
2829
|
const sum = read.reduce((total, p) => total + p, 0);
|
|
2824
2830
|
return Math.abs(sum - 1) <= 1e-6 && read[chosen] === Math.max(...read) ? read : null;
|
|
2825
2831
|
}
|
|
2826
|
-
|
|
2827
|
-
//#region src/scoring/strategies/all-or-nothing.ts
|
|
2832
|
+
// src/scoring/strategies/all-or-nothing.ts
|
|
2828
2833
|
/**
|
|
2829
2834
|
* All-or-nothing scoring: full credit only when every item is correct.
|
|
2830
2835
|
*
|
|
@@ -2834,8 +2839,7 @@ function levelDistribution(values, count, chosen) {
|
|
|
2834
2839
|
function allOrNothingStrategy(correctItems) {
|
|
2835
2840
|
return correctItems.every((isCorrect) => isCorrect) ? 1 : 0;
|
|
2836
2841
|
}
|
|
2837
|
-
|
|
2838
|
-
//#region src/scoring/strategies/partial.ts
|
|
2842
|
+
// src/scoring/strategies/partial.ts
|
|
2839
2843
|
/**
|
|
2840
2844
|
* Partial-credit scoring for Multiple Choice — balanced/symmetric scheme.
|
|
2841
2845
|
*
|
|
@@ -2875,8 +2879,7 @@ function partialStrategy(correctSelected, incorrectSelected, totalCorrect, total
|
|
|
2875
2879
|
function partialBlankStrategy(correctBlanks, totalBlanks) {
|
|
2876
2880
|
return correctBlanks / totalBlanks;
|
|
2877
2881
|
}
|
|
2878
|
-
|
|
2879
|
-
//#region src/scoring/text-match.ts
|
|
2882
|
+
// src/scoring/text-match.ts
|
|
2880
2883
|
/** Combining marks (any script) removed for diacritic folding after NFD decomposition. */
|
|
2881
2884
|
const COMBINING_MARKS_RE = /\p{M}/gu;
|
|
2882
2885
|
/**
|
|
@@ -2969,8 +2972,7 @@ function matchText(input, accepted, policy = {}) {
|
|
|
2969
2972
|
via: "none"
|
|
2970
2973
|
};
|
|
2971
2974
|
}
|
|
2972
|
-
|
|
2973
|
-
//#region src/scoring/activity-scorers/fill-in-the-blanks.ts
|
|
2975
|
+
// src/scoring/activity-scorers/fill-in-the-blanks.ts
|
|
2974
2976
|
/**
|
|
2975
2977
|
* Resolves the effective match policy for a blank. The legacy
|
|
2976
2978
|
* `caseSensitive` / `trimWhitespace` flags map onto the baseline policy
|
|
@@ -3014,8 +3016,7 @@ function scoreFillInTheBlanks(data, response) {
|
|
|
3014
3016
|
details
|
|
3015
3017
|
};
|
|
3016
3018
|
}
|
|
3017
|
-
|
|
3018
|
-
//#region src/authoring/findings.ts
|
|
3019
|
+
// src/authoring/findings.ts
|
|
3019
3020
|
/**
|
|
3020
3021
|
* Every finding code the SDK's item critic can report, with its severity.
|
|
3021
3022
|
*
|
|
@@ -3041,6 +3042,9 @@ const ITEM_FINDING_SEVERITY = {
|
|
|
3041
3042
|
wr_criterion_name_duplicate: "warning",
|
|
3042
3043
|
wr_levels_unreadable: "warning",
|
|
3043
3044
|
ra_text_long_for_time: "warning",
|
|
3045
|
+
media_transcript_unused: "advice",
|
|
3046
|
+
media_script_differs: "warning",
|
|
3047
|
+
media_transcript_differs: "warning",
|
|
3044
3048
|
set_key_position_same: "warning"
|
|
3045
3049
|
};
|
|
3046
3050
|
function finding(code, path, message) {
|
|
@@ -3065,8 +3069,7 @@ function normaliseFinding(found) {
|
|
|
3065
3069
|
severity: documented ?? (found.severity === "advice" ? "advice" : "warning")
|
|
3066
3070
|
};
|
|
3067
3071
|
}
|
|
3068
|
-
|
|
3069
|
-
//#region src/authoring/critique.ts
|
|
3072
|
+
// src/authoring/critique.ts
|
|
3070
3073
|
/**
|
|
3071
3074
|
* The built-in item critic: what an experienced item writer points out on
|
|
3072
3075
|
* review, as far as a rule can see it without a model.
|
|
@@ -3349,8 +3352,7 @@ function keyPositionFinding(items, path) {
|
|
|
3349
3352
|
if (positions.length < KEY_POSITION_MINIMUM || !positions.every((at) => at === positions[0])) return [];
|
|
3350
3353
|
return [finding("set_key_position_same", path, `In all ${positions.length} single-answer questions the right option is option ${ordinal(positions[0])}. Vary its position, or shuffle the options.`)];
|
|
3351
3354
|
}
|
|
3352
|
-
|
|
3353
|
-
//#region src/authoring/fill-in-the-blanks.ts
|
|
3355
|
+
// src/authoring/fill-in-the-blanks.ts
|
|
3354
3356
|
/**
|
|
3355
3357
|
* Draft support for `fill-in-the-blanks`.
|
|
3356
3358
|
*
|
|
@@ -3482,8 +3484,7 @@ function pairsOneToOne$1(placeholders, blanks) {
|
|
|
3482
3484
|
if (placeholders.size !== blankIds.length) return false;
|
|
3483
3485
|
return blankIds.every((id) => typeof id === "string" && placeholders.get(id) === 1);
|
|
3484
3486
|
}
|
|
3485
|
-
|
|
3486
|
-
//#region src/authoring/gap-select.ts
|
|
3487
|
+
// src/authoring/gap-select.ts
|
|
3487
3488
|
/** Mirrors `GapSelectChoiceSchema` arrays: `.min(2)` on both a gap's own list and a bank. */
|
|
3488
3489
|
const MIN_CHOICES = 2;
|
|
3489
3490
|
/**
|
|
@@ -3681,8 +3682,7 @@ function pairsOneToOne(placeholders, gaps) {
|
|
|
3681
3682
|
if (new Set(ids).size !== ids.length || placeholders.size !== ids.length) return false;
|
|
3682
3683
|
return ids.every((id) => typeof id === "string" && placeholders.get(id) === 1);
|
|
3683
3684
|
}
|
|
3684
|
-
|
|
3685
|
-
//#region src/schemas/multiple-choice.ts
|
|
3685
|
+
// src/schemas/multiple-choice.ts
|
|
3686
3686
|
/**
|
|
3687
3687
|
* Zod schema for a single Multiple Choice option. Loose: unknown keys are
|
|
3688
3688
|
* preserved through validation (forward-compat / consumer sidecars — B7).
|
|
@@ -3709,7 +3709,9 @@ const MultipleChoiceOptionMediaSchema = z.looseObject({
|
|
|
3709
3709
|
type: z.enum(["image", "audio"]),
|
|
3710
3710
|
url: MediaUrlSchema,
|
|
3711
3711
|
alt: z.string().min(1).optional(),
|
|
3712
|
-
captionsUrl: MediaUrlSchema.optional()
|
|
3712
|
+
captionsUrl: MediaUrlSchema.optional(),
|
|
3713
|
+
transcript: z.string().optional(),
|
|
3714
|
+
script: ScriptSchema.optional()
|
|
3713
3715
|
}).refine((media) => media.type !== "image" || media.alt !== void 0 && media.alt !== "", {
|
|
3714
3716
|
error: "An image option requires a non-empty `alt`.",
|
|
3715
3717
|
path: ["alt"]
|
|
@@ -3744,6 +3746,7 @@ const MultipleChoiceDataSchema = z.looseObject({
|
|
|
3744
3746
|
type: z.literal("multiple-choice"),
|
|
3745
3747
|
id: z.string().min(1),
|
|
3746
3748
|
title: z.string().min(1),
|
|
3749
|
+
instructions: z.string().optional(),
|
|
3747
3750
|
question: z.string().min(1),
|
|
3748
3751
|
questionHtml: z.string().optional(),
|
|
3749
3752
|
mode: z.enum(["single", "multi"]),
|
|
@@ -3773,8 +3776,7 @@ const MultipleChoiceDataSchema = z.looseObject({
|
|
|
3773
3776
|
error: "Option ids must be unique within the activity.",
|
|
3774
3777
|
path: ["options"]
|
|
3775
3778
|
});
|
|
3776
|
-
|
|
3777
|
-
//#region src/authoring/multiple-choice.ts
|
|
3779
|
+
// src/authoring/multiple-choice.ts
|
|
3778
3780
|
/** Mirrors `MultipleChoiceDataSchema`: `options` is `.min(2).max(26)`. */
|
|
3779
3781
|
const MIN_OPTIONS = 2;
|
|
3780
3782
|
const MAX_OPTIONS = 26;
|
|
@@ -3877,8 +3879,7 @@ function checkOptionMedia(media, index, ordinal) {
|
|
|
3877
3879
|
if (kind === "video" || kind === "embed") return [issue("mc_option_media_kind", [...path, "type"], `Option ${ordinal} carries ${kind === "embed" ? "an embedded player" : "a video"}, which cannot be an option: its controls swallow the click that selects the answer. Use a picture or a recording.`)];
|
|
3878
3880
|
return checkMedia(media, path, MultipleChoiceOptionMediaSchema);
|
|
3879
3881
|
}
|
|
3880
|
-
|
|
3881
|
-
//#region src/scoring/speech/limits.ts
|
|
3882
|
+
// src/scoring/speech/limits.ts
|
|
3882
3883
|
/**
|
|
3883
3884
|
* The longest reference text a read-aloud item accepts, in code points, before
|
|
3884
3885
|
* and after normalisation. It is the dictation transcript cap on purpose: the
|
|
@@ -3928,8 +3929,7 @@ const SPEECH_ASSESSMENT_MAX_WORDS = 1e3;
|
|
|
3928
3929
|
* read-aloud item comes near it.
|
|
3929
3930
|
*/
|
|
3930
3931
|
const SPEECH_ASSESSMENT_MAX_TEXT_LENGTH = DICTATION_MAX_TEXT_LENGTH;
|
|
3931
|
-
|
|
3932
|
-
//#region src/scoring/speech/locale.ts
|
|
3932
|
+
// src/scoring/speech/locale.ts
|
|
3933
3933
|
/**
|
|
3934
3934
|
* A BCP 47 tag in the one spelling read-aloud accepts: a lowercase language of
|
|
3935
3935
|
* two or three letters, an optional title-case script, and a region of two
|
|
@@ -3945,8 +3945,7 @@ const SPEECH_ASSESSMENT_MAX_TEXT_LENGTH = DICTATION_MAX_TEXT_LENGTH;
|
|
|
3945
3945
|
* Internal: the content schema and the assessment validator share it.
|
|
3946
3946
|
*/
|
|
3947
3947
|
const CANONICAL_LOCALE_RE = /^[a-z]{2,3}(?:-[A-Z][a-z]{3})?-(?:[A-Z]{2}|[0-9]{3})$/;
|
|
3948
|
-
|
|
3949
|
-
//#region src/schemas/read-aloud.ts
|
|
3948
|
+
// src/schemas/read-aloud.ts
|
|
3950
3949
|
/** The dimensions a read-aloud grade can be made of, in the order they are documented. */
|
|
3951
3950
|
const READ_ALOUD_DIMENSIONS = [
|
|
3952
3951
|
"accuracy",
|
|
@@ -4099,8 +4098,7 @@ const ReadAloudDataSchema = z.looseObject({
|
|
|
4099
4098
|
if (minSeconds !== void 0 && minSeconds >= maxSeconds) report(["recording", "minSeconds"], minSeconds, "The shortest take must be shorter than the longest.");
|
|
4100
4099
|
}
|
|
4101
4100
|
}));
|
|
4102
|
-
|
|
4103
|
-
//#region src/authoring/read-aloud.ts
|
|
4101
|
+
// src/authoring/read-aloud.ts
|
|
4104
4102
|
/**
|
|
4105
4103
|
* Draft support for `read-aloud`.
|
|
4106
4104
|
*
|
|
@@ -4263,8 +4261,7 @@ function checkSlowRecording(draft) {
|
|
|
4263
4261
|
if (typeof slow.url === "string" && slow.url !== "" && slow.url === media.url) issues.push(issue("ra_slow_media_same_recording", ["slowMedia", "url"], "The slow model recording is the same file as the recording. Point it at the slower reading."));
|
|
4264
4262
|
return issues;
|
|
4265
4263
|
}
|
|
4266
|
-
|
|
4267
|
-
//#region src/authoring/written-response.ts
|
|
4264
|
+
// src/authoring/written-response.ts
|
|
4268
4265
|
/**
|
|
4269
4266
|
* Draft support for `written-response`.
|
|
4270
4267
|
*
|
|
@@ -4352,8 +4349,7 @@ function checkCriteria(criteria) {
|
|
|
4352
4349
|
else if (totalWeight === Number.POSITIVE_INFINITY) issues.push(issue("wr_rubric_weights_too_large", ["rubric", "criteria"], "The rubric weights add up to more than can be calculated with. Use smaller weights."));
|
|
4353
4350
|
return issues;
|
|
4354
4351
|
}
|
|
4355
|
-
|
|
4356
|
-
//#region src/schemas/gap-select.ts
|
|
4352
|
+
// src/schemas/gap-select.ts
|
|
4357
4353
|
/**
|
|
4358
4354
|
* Zod schema for one selectable choice. Loose, like every other schema here:
|
|
4359
4355
|
* unknown keys are preserved so a consumer sidecar survives validation.
|
|
@@ -4417,6 +4413,7 @@ const GapSelectDataSchema = z.looseObject({
|
|
|
4417
4413
|
type: z.literal("gap-select"),
|
|
4418
4414
|
id: z.string().min(1),
|
|
4419
4415
|
title: z.string().min(1),
|
|
4416
|
+
instructions: PassageInstructionsSchema.optional(),
|
|
4420
4417
|
passage: z.string().min(1),
|
|
4421
4418
|
passageHtml: z.string().optional(),
|
|
4422
4419
|
gaps: z.array(GapSelectGapSchema).min(1),
|
|
@@ -4477,8 +4474,7 @@ const GapSelectDataSchema = z.looseObject({
|
|
|
4477
4474
|
error: "Each gap needs unique choice ids and a `correctChoiceId` that is one of the choices it offers.",
|
|
4478
4475
|
path: ["gaps"]
|
|
4479
4476
|
});
|
|
4480
|
-
|
|
4481
|
-
//#region src/schemas/written-response.ts
|
|
4477
|
+
// src/schemas/written-response.ts
|
|
4482
4478
|
/** Zod schema for a single rubric criterion. Loose: unknown keys preserved. */
|
|
4483
4479
|
const WrittenResponseRubricCriterionSchema = z.looseObject({
|
|
4484
4480
|
name: z.string().min(1),
|
|
@@ -4549,8 +4545,7 @@ const WrittenResponseDataSchema = z.looseObject({
|
|
|
4549
4545
|
error: "maxWords must be greater than or equal to minWords.",
|
|
4550
4546
|
path: ["maxWords"]
|
|
4551
4547
|
});
|
|
4552
|
-
|
|
4553
|
-
//#region src/schemas/redacted.ts
|
|
4548
|
+
// src/schemas/redacted.ts
|
|
4554
4549
|
/**
|
|
4555
4550
|
* Schemas for REDACTED activity data — the learner-safe projection `redact()`
|
|
4556
4551
|
* produces (R7). Deliberately STRICT (`z.strictObject`), the opposite of the
|
|
@@ -4614,6 +4609,7 @@ const RedactedMultipleChoiceOptionSchema = z.strictObject({
|
|
|
4614
4609
|
const RedactedMultipleChoiceDataSchema = z.strictObject({
|
|
4615
4610
|
...redactedBase,
|
|
4616
4611
|
type: z.literal("multiple-choice"),
|
|
4612
|
+
instructions: z.string().optional(),
|
|
4617
4613
|
question: z.string().min(1),
|
|
4618
4614
|
questionHtml: z.string().optional(),
|
|
4619
4615
|
mode: z.enum(["single", "multi"]),
|
|
@@ -4629,6 +4625,7 @@ const RedactedBlankConfigSchema = z.strictObject({
|
|
|
4629
4625
|
const RedactedFillInTheBlanksDataSchema = z.strictObject({
|
|
4630
4626
|
...redactedBase,
|
|
4631
4627
|
type: z.literal("fill-in-the-blanks"),
|
|
4628
|
+
instructions: z.string().optional(),
|
|
4632
4629
|
passage: z.string().min(1),
|
|
4633
4630
|
passageHtml: z.string().optional(),
|
|
4634
4631
|
blanks: z.array(RedactedBlankConfigSchema).min(1)
|
|
@@ -4667,6 +4664,7 @@ const RedactedGapSelectGapSchema = z.strictObject({
|
|
|
4667
4664
|
const RedactedGapSelectDataSchema = z.strictObject({
|
|
4668
4665
|
...redactedBase,
|
|
4669
4666
|
type: z.literal("gap-select"),
|
|
4667
|
+
instructions: z.string().optional(),
|
|
4670
4668
|
passage: z.string().min(1),
|
|
4671
4669
|
passageHtml: z.string().optional(),
|
|
4672
4670
|
gaps: z.array(RedactedGapSelectGapSchema).min(1),
|
|
@@ -4792,8 +4790,7 @@ const RedactedReadAloudDataSchema = z.strictObject({
|
|
|
4792
4790
|
path: ["slowMedia", "url"]
|
|
4793
4791
|
});
|
|
4794
4792
|
});
|
|
4795
|
-
|
|
4796
|
-
//#region src/scoring/activity-scorers/dictation.ts
|
|
4793
|
+
// src/scoring/activity-scorers/dictation.ts
|
|
4797
4794
|
/**
|
|
4798
4795
|
* Scores a Dictation response: the character-level similarity of what the
|
|
4799
4796
|
* learner typed to the transcript, over the whole sentence.
|
|
@@ -4832,8 +4829,7 @@ function scoreDictation(data, response) {
|
|
|
4832
4829
|
details
|
|
4833
4830
|
};
|
|
4834
4831
|
}
|
|
4835
|
-
|
|
4836
|
-
//#region src/scoring/activity-scorers/gap-select.ts
|
|
4832
|
+
// src/scoring/activity-scorers/gap-select.ts
|
|
4837
4833
|
/**
|
|
4838
4834
|
* The choices a gap offers: its own list, or the bank it names.
|
|
4839
4835
|
*
|
|
@@ -4887,8 +4883,7 @@ function scoreGapSelect(data, response) {
|
|
|
4887
4883
|
details
|
|
4888
4884
|
};
|
|
4889
4885
|
}
|
|
4890
|
-
|
|
4891
|
-
//#region src/scoring/activity-scorers/multiple-choice.ts
|
|
4886
|
+
// src/scoring/activity-scorers/multiple-choice.ts
|
|
4892
4887
|
/**
|
|
4893
4888
|
* Scores a Multiple Choice response. Pure; trusts its typed inputs (validation
|
|
4894
4889
|
* is the component boundary's job). Options are looked up by id; an unknown
|
|
@@ -4932,8 +4927,7 @@ function scoreMultipleChoice(data, response) {
|
|
|
4932
4927
|
details
|
|
4933
4928
|
};
|
|
4934
4929
|
}
|
|
4935
|
-
|
|
4936
|
-
//#region src/registry/define.ts
|
|
4930
|
+
// src/registry/define.ts
|
|
4937
4931
|
/**
|
|
4938
4932
|
* Identity helper that gives full type inference when authoring a descriptor:
|
|
4939
4933
|
*
|
|
@@ -4948,8 +4942,7 @@ function scoreMultipleChoice(data, response) {
|
|
|
4948
4942
|
function defineActivityType(descriptor) {
|
|
4949
4943
|
return descriptor;
|
|
4950
4944
|
}
|
|
4951
|
-
|
|
4952
|
-
//#region src/registry/keep-when.ts
|
|
4945
|
+
// src/registry/keep-when.ts
|
|
4953
4946
|
/**
|
|
4954
4947
|
* A nested field policy that keeps its field only when the field's value
|
|
4955
4948
|
* passes a test. Internal: the symbol is never exported, so no host policy can
|
|
@@ -4974,8 +4967,22 @@ function keepWhen(policy, test) {
|
|
|
4974
4967
|
function guardOf(policy) {
|
|
4975
4968
|
return policy[KEEP_WHEN];
|
|
4976
4969
|
}
|
|
4977
|
-
|
|
4978
|
-
|
|
4970
|
+
// src/registry/builtins.ts
|
|
4971
|
+
/**
|
|
4972
|
+
* Where the built-in types keep their files (`mediaSlots`). Every type has its
|
|
4973
|
+
* `media`; dictation and read-aloud add a slower recording; a multiple-choice
|
|
4974
|
+
* option may carry a picture or a recording of its own.
|
|
4975
|
+
*/
|
|
4976
|
+
const MAIN_MEDIA = [{ path: ["media"] }];
|
|
4977
|
+
const MAIN_AND_SLOW_MEDIA = [{ path: ["media"] }, { path: ["slowMedia"] }];
|
|
4978
|
+
function multipleChoiceMediaSlots(data) {
|
|
4979
|
+
const options = Array.isArray(data.options) ? data.options : [];
|
|
4980
|
+
return [...MAIN_MEDIA, ...options.map((_, index) => ({ path: [
|
|
4981
|
+
"options",
|
|
4982
|
+
index,
|
|
4983
|
+
"media"
|
|
4984
|
+
] }))];
|
|
4985
|
+
}
|
|
4979
4986
|
/**
|
|
4980
4987
|
* Field-sensitivity policies for the built-in types (R7). Fail-closed:
|
|
4981
4988
|
* anything not listed here is dropped by `redact()`. `scoringStrategy` is
|
|
@@ -4996,10 +5003,11 @@ function guardOf(policy) {
|
|
|
4996
5003
|
* documents ("a field the policy does not classify is removed") stopped at the
|
|
4997
5004
|
* media boundary. It no longer does.
|
|
4998
5005
|
*
|
|
4999
|
-
*
|
|
5000
|
-
* and enforces the policy, and "1 play remaining" is text the
|
|
5001
|
-
*
|
|
5002
|
-
* `
|
|
5006
|
+
* Public by necessity, except what the recording says: the client is the thing
|
|
5007
|
+
* that renders and enforces the policy, and "1 play remaining" is text the
|
|
5008
|
+
* learner has to read. `transcript` and `script` are the exception, and
|
|
5009
|
+
* `author-only`: what a listening question's recording says is that question's
|
|
5010
|
+
* answer, as `stimulus.transcript` is a listening paper's.
|
|
5003
5011
|
*/
|
|
5004
5012
|
const MEDIA_FIELD_POLICY = {
|
|
5005
5013
|
type: "public",
|
|
@@ -5020,7 +5028,9 @@ const MEDIA_FIELD_POLICY = {
|
|
|
5020
5028
|
seek: "public",
|
|
5021
5029
|
rate: "public",
|
|
5022
5030
|
nativeControlHints: "public"
|
|
5023
|
-
}
|
|
5031
|
+
},
|
|
5032
|
+
transcript: "author-only",
|
|
5033
|
+
script: "author-only"
|
|
5024
5034
|
};
|
|
5025
5035
|
const SHARED_PUBLIC_FIELDS = {
|
|
5026
5036
|
schemaVersion: "public",
|
|
@@ -5075,6 +5085,7 @@ const TEXT_MATCH_FIELD_POLICY = {
|
|
|
5075
5085
|
};
|
|
5076
5086
|
const MULTIPLE_CHOICE_FIELD_POLICY = {
|
|
5077
5087
|
...SHARED_PUBLIC_FIELDS,
|
|
5088
|
+
instructions: "public",
|
|
5078
5089
|
question: "public",
|
|
5079
5090
|
questionHtml: "public",
|
|
5080
5091
|
mode: "public",
|
|
@@ -5090,7 +5101,9 @@ const MULTIPLE_CHOICE_FIELD_POLICY = {
|
|
|
5090
5101
|
type: "public",
|
|
5091
5102
|
url: "public",
|
|
5092
5103
|
alt: "public",
|
|
5093
|
-
captionsUrl: "public"
|
|
5104
|
+
captionsUrl: "public",
|
|
5105
|
+
transcript: "author-only",
|
|
5106
|
+
script: "author-only"
|
|
5094
5107
|
}
|
|
5095
5108
|
}
|
|
5096
5109
|
};
|
|
@@ -5107,6 +5120,7 @@ const MULTIPLE_CHOICE_FIELD_POLICY = {
|
|
|
5107
5120
|
*/
|
|
5108
5121
|
const GAP_SELECT_FIELD_POLICY = {
|
|
5109
5122
|
...SHARED_PUBLIC_FIELDS,
|
|
5123
|
+
instructions: "public",
|
|
5110
5124
|
passage: "public",
|
|
5111
5125
|
passageHtml: "public",
|
|
5112
5126
|
presentation: "public",
|
|
@@ -5133,6 +5147,7 @@ const GAP_SELECT_FIELD_POLICY = {
|
|
|
5133
5147
|
};
|
|
5134
5148
|
const FILL_IN_THE_BLANKS_FIELD_POLICY = {
|
|
5135
5149
|
...SHARED_PUBLIC_FIELDS,
|
|
5150
|
+
instructions: "public",
|
|
5136
5151
|
passage: "public",
|
|
5137
5152
|
passageHtml: "public",
|
|
5138
5153
|
scoringStrategy: "answer-key",
|
|
@@ -5230,7 +5245,8 @@ const multipleChoiceType = defineActivityType({
|
|
|
5230
5245
|
"option-deselected",
|
|
5231
5246
|
"submitted"
|
|
5232
5247
|
],
|
|
5233
|
-
authoring: multipleChoiceAuthoring
|
|
5248
|
+
authoring: multipleChoiceAuthoring,
|
|
5249
|
+
mediaSlots: multipleChoiceMediaSlots
|
|
5234
5250
|
});
|
|
5235
5251
|
/** Built-in Fill-in-the-Blanks descriptor. */
|
|
5236
5252
|
const fillInTheBlanksType = defineActivityType({
|
|
@@ -5253,7 +5269,8 @@ const fillInTheBlanksType = defineActivityType({
|
|
|
5253
5269
|
"hint-requested",
|
|
5254
5270
|
"submitted"
|
|
5255
5271
|
],
|
|
5256
|
-
authoring: fillInTheBlanksAuthoring
|
|
5272
|
+
authoring: fillInTheBlanksAuthoring,
|
|
5273
|
+
mediaSlots: () => MAIN_MEDIA
|
|
5257
5274
|
});
|
|
5258
5275
|
/**
|
|
5259
5276
|
* Built-in Written Response descriptor. Grading is DEFERRED: submissions are
|
|
@@ -5285,7 +5302,8 @@ const writtenResponseType = defineActivityType({
|
|
|
5285
5302
|
correctResponsesPattern: () => []
|
|
5286
5303
|
},
|
|
5287
5304
|
interactions: ["text-changed", "submitted"],
|
|
5288
|
-
authoring: writtenResponseAuthoring
|
|
5305
|
+
authoring: writtenResponseAuthoring,
|
|
5306
|
+
mediaSlots: () => MAIN_MEDIA
|
|
5289
5307
|
});
|
|
5290
5308
|
/** Built-in Gap Select descriptor. */
|
|
5291
5309
|
const gapSelectType = defineActivityType({
|
|
@@ -5304,7 +5322,8 @@ const gapSelectType = defineActivityType({
|
|
|
5304
5322
|
correctResponsesPattern: (data) => [data.gaps.map((gap) => `${gap.id}[.]${gap.correctChoiceId}`).join("[,]")]
|
|
5305
5323
|
},
|
|
5306
5324
|
interactions: ["gap-selected", "submitted"],
|
|
5307
|
-
authoring: gapSelectAuthoring
|
|
5325
|
+
authoring: gapSelectAuthoring,
|
|
5326
|
+
mediaSlots: () => MAIN_MEDIA
|
|
5308
5327
|
});
|
|
5309
5328
|
/**
|
|
5310
5329
|
* Built-in Dictation descriptor. Graded synchronously: the score is the
|
|
@@ -5331,7 +5350,8 @@ const dictationType = defineActivityType({
|
|
|
5331
5350
|
"hint-requested",
|
|
5332
5351
|
"submitted"
|
|
5333
5352
|
],
|
|
5334
|
-
authoring: dictationAuthoring
|
|
5353
|
+
authoring: dictationAuthoring,
|
|
5354
|
+
mediaSlots: () => MAIN_AND_SLOW_MEDIA
|
|
5335
5355
|
});
|
|
5336
5356
|
/**
|
|
5337
5357
|
* Read Aloud, the type with no answer key at all.
|
|
@@ -5412,7 +5432,8 @@ const readAloudType = defineActivityType({
|
|
|
5412
5432
|
"recording-uploaded",
|
|
5413
5433
|
"submitted"
|
|
5414
5434
|
],
|
|
5415
|
-
authoring: readAloudAuthoring
|
|
5435
|
+
authoring: readAloudAuthoring,
|
|
5436
|
+
mediaSlots: () => MAIN_AND_SLOW_MEDIA
|
|
5416
5437
|
});
|
|
5417
5438
|
/**
|
|
5418
5439
|
* The SDK's own types, by type: what the registry is created holding
|
|
@@ -5429,8 +5450,7 @@ const BUILT_IN_DESCRIPTORS = {
|
|
|
5429
5450
|
dictation: dictationType,
|
|
5430
5451
|
"read-aloud": readAloudType
|
|
5431
5452
|
};
|
|
5432
|
-
|
|
5433
|
-
//#region src/schemas/read-schema.ts
|
|
5453
|
+
// src/schemas/read-schema.ts
|
|
5434
5454
|
/**
|
|
5435
5455
|
* How every entry point reads a schema — `validateActivity`, `validateDraft`,
|
|
5436
5456
|
* `validateItemGroup`, `redact`, `assertRedacted` — so a schema is read one way
|
|
@@ -5540,14 +5560,13 @@ function isStandardSchema(value) {
|
|
|
5540
5560
|
* A schema's own JSON Schema, when it implements the Standard JSON Schema
|
|
5541
5561
|
* converter (`'~standard'.jsonSchema`) — zod 4.6 does — or `undefined`.
|
|
5542
5562
|
*/
|
|
5543
|
-
function standardJsonSchemaOf(schema) {
|
|
5563
|
+
function standardJsonSchemaOf(schema, target = "draft-07") {
|
|
5544
5564
|
const converter = schema["~standard"].jsonSchema;
|
|
5545
5565
|
if (typeof converter?.output !== "function") return;
|
|
5546
|
-
const generated = converter.output({ target
|
|
5566
|
+
const generated = converter.output({ target });
|
|
5547
5567
|
return generated !== null && typeof generated === "object" && !Array.isArray(generated) ? generated : void 0;
|
|
5548
5568
|
}
|
|
5549
|
-
|
|
5550
|
-
//#region src/registry/registry.ts
|
|
5569
|
+
// src/registry/registry.ts
|
|
5551
5570
|
/**
|
|
5552
5571
|
* Module-scoped default registry (deliberate — no registry instances until a
|
|
5553
5572
|
* second consumer exists), created holding the SDK's own types.
|
|
@@ -5593,7 +5612,6 @@ function getActivityTypeDescriptor(type) {
|
|
|
5593
5612
|
function registeredActivityTypes() {
|
|
5594
5613
|
return [...registry.keys()];
|
|
5595
5614
|
}
|
|
5596
|
-
|
|
5597
|
-
export { RedactedScoringError as $, levenshteinDistance as A, covers as B, READ_ALOUD_MAX_TAKES as C, RedactedMediaSchema as Ct, MultipleChoiceOptionMediaSchema as D, MultipleChoiceDataSchema as E, readRubricLevels as F, issue as G, isRecord as H, countWords as I, DictationDataSchema as J, pathKey as K, DRAFT_ISSUE_SEVERITY as L, LEVEL_PROBABILITY_TOLERANCE as M, levelDistribution as N, keyPositionFinding as O, levelKey as P, DeferredScoringError as Q, checkMedia as R, READ_ALOUD_MAX_SECONDS as S, MediaSchema as St, SPEECH_ASSESSMENT_MAX_WORDS as T, isUnset as U, isMissingId as V, isUnwritten as W, groupCaptionsField as X, GROUP_CAPTIONS_REVEAL_DICTATION as Y, ActivitySchemaError as Z, GapSelectDataSchema as _, fold as _t, readSchema as a, DICTATION_MAX_ACCEPTED_TRANSCRIPTS as at, READ_ALOUD_MAX_DIMENSION_WEIGHT as b, revealsAnswer as bt, dictationType as c, DICTATION_MAX_TEXT_LENGTH as ct, multipleChoiceType as d, normalizeDictationText as dt, UnknownActivityTypeError as et, readAloudType as f, withValidationScope as ft, WrittenResponseDataSchema as g, containsWords as gt, defineActivityType as h, isBuiltInActivityType as ht, isOwnSchema as i, dictationReferenceWords as it, matchText as j, normaliseFinding as k, fillInTheBlanksType as l, DICTATION_MAX_TRANSCRIPT_LENGTH as lt, guardOf as m, everyBuiltInTypeHandled as mt, registerActivityType as n, alignDictation as nt, standardJsonSchemaOf as o, DICTATION_MAX_EQUIVALENCES as ot, writtenResponseType as p, BUILT_IN_ACTIVITY_TYPES as pt, refusesEmpty as q, registeredActivityTypes as r, alignSequences as rt, MEDIA_FIELD_POLICY as s, DICTATION_MAX_EQUIVALENCE_LENGTH as st, getActivityTypeDescriptor as t, STEP as tt, gapSelectType as u, codePointLength as ut, ReadAloudDataSchema as v, numberedPassage as vt, SPEECH_ASSESSMENT_MAX_TEXT_LENGTH as w, maxUnits as wt, READ_ALOUD_MAX_REFERENCE_LENGTH as x, FillInTheBlanksDataSchema as xt, CANONICAL_LOCALE_RE as y, placeholderOrder as yt, coveredPathsOf as z };
|
|
5615
|
+
export { DeferredScoringError as $, normaliseFinding as A, coveredPathsOf as B, READ_ALOUD_MAX_TAKES as C, MediaSchema as Ct, MultipleChoiceOptionMediaSchema as D, maxUnits as Dt, MultipleChoiceDataSchema as E, ScriptSchema as Et, levelKey as F, isUnwritten as G, isMissingId as H, readRubricLevels as I, refusesEmpty as J, issue as K, countWords as L, matchText as M, LEVEL_PROBABILITY_TOLERANCE as N, keyPositionFinding as O, levelDistribution as P, ActivitySchemaError as Q, DRAFT_ISSUE_SEVERITY as R, READ_ALOUD_MAX_SECONDS as S, FillInTheBlanksDataSchema as St, SPEECH_ASSESSMENT_MAX_WORDS as T, SCRIPT_MAX_TURNS as Tt, isRecord as U, covers as V, isUnset as W, GROUP_CAPTIONS_REVEAL_DICTATION as X, DictationDataSchema as Y, groupCaptionsField as Z, GapSelectDataSchema as _, containsWords as _t, readSchema as a, dictationReferenceWords as at, READ_ALOUD_MAX_DIMENSION_WEIGHT as b, placeholderOrder as bt, dictationType as c, DICTATION_MAX_EQUIVALENCE_LENGTH as ct, multipleChoiceType as d, codePointLength as dt, RedactedScoringError as et, readAloudType as f, normalizeDictationText as ft, WrittenResponseDataSchema as g, isBuiltInActivityType as gt, defineActivityType as h, everyBuiltInTypeHandled as ht, isOwnSchema as i, alignSequences as it, levenshteinDistance as j, finding as k, fillInTheBlanksType as l, DICTATION_MAX_TEXT_LENGTH as lt, guardOf as m, BUILT_IN_ACTIVITY_TYPES as mt, registerActivityType as n, STEP as nt, standardJsonSchemaOf as o, DICTATION_MAX_ACCEPTED_TRANSCRIPTS as ot, writtenResponseType as p, withValidationScope as pt, pathKey as q, registeredActivityTypes as r, alignDictation as rt, MEDIA_FIELD_POLICY as s, DICTATION_MAX_EQUIVALENCES as st, getActivityTypeDescriptor as t, UnknownActivityTypeError as tt, gapSelectType as u, DICTATION_MAX_TRANSCRIPT_LENGTH as ut, ReadAloudDataSchema as v, fold as vt, SPEECH_ASSESSMENT_MAX_TEXT_LENGTH as w, RedactedMediaSchema as wt, READ_ALOUD_MAX_REFERENCE_LENGTH as x, revealsAnswer as xt, CANONICAL_LOCALE_RE as y, numberedPassage as yt, checkMedia as z };
|
|
5598
5616
|
|
|
5599
|
-
//# sourceMappingURL=registry-
|
|
5617
|
+
//# sourceMappingURL=registry-D92hz9iA.js.map
|