@intellectif/lk-core 1.0.0 → 1.2.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 +30 -0
- package/README.md +2 -1
- package/dist/{activity-DgpBJeBc.d.cts → activity-D705CXng.d.cts} +439 -7
- package/dist/{activity-DgpBJeBc.d.ts → activity-D705CXng.d.ts} +439 -7
- package/dist/ai-check.cjs +300 -9
- package/dist/ai-check.cjs.map +1 -1
- package/dist/ai-check.d.cts +18 -3
- package/dist/ai-check.d.ts +18 -3
- package/dist/ai-check.js +295 -4
- package/dist/ai-check.js.map +1 -1
- package/dist/{chunk-TJJFKKH2.cjs → chunk-46BXIGLG.cjs} +4 -4
- package/dist/{chunk-TJJFKKH2.cjs.map → chunk-46BXIGLG.cjs.map} +1 -1
- package/dist/{chunk-VSH7ECQL.cjs → chunk-4YANYTFN.cjs} +43 -43
- package/dist/{chunk-VSH7ECQL.cjs.map → chunk-4YANYTFN.cjs.map} +1 -1
- package/dist/chunk-7KOWU4RO.js +2207 -0
- package/dist/chunk-7KOWU4RO.js.map +1 -0
- package/dist/{chunk-DSDXL3JO.cjs → chunk-7THXD7AN.cjs} +657 -197
- package/dist/chunk-7THXD7AN.cjs.map +1 -0
- package/dist/chunk-CYCTIXUN.cjs +118 -0
- package/dist/chunk-CYCTIXUN.cjs.map +1 -0
- package/dist/chunk-CYPA5BW5.js +118 -0
- package/dist/chunk-CYPA5BW5.js.map +1 -0
- package/dist/{chunk-SJVRUPJT.js → chunk-JTNDIBZO.js} +2 -2
- package/dist/{chunk-XS6U2ARZ.js → chunk-MV2N2WNS.js} +6 -112
- package/dist/chunk-MV2N2WNS.js.map +1 -0
- package/dist/chunk-MXI26H62.cjs +2207 -0
- package/dist/chunk-MXI26H62.cjs.map +1 -0
- package/dist/{chunk-FBKTION6.js → chunk-QS7B42ZR.js} +640 -180
- package/dist/chunk-QS7B42ZR.js.map +1 -0
- package/dist/{chunk-IARLJ5MW.js → chunk-QX2ERL72.js} +2 -2
- package/dist/{chunk-2JT2WUQ2.cjs → chunk-ZWXQSKCX.cjs} +14 -120
- package/dist/chunk-ZWXQSKCX.cjs.map +1 -0
- package/dist/{index-BVNeSCWC.d.ts → index-BChYtrEe.d.ts} +1 -1
- package/dist/{index-BlOLlwOi.d.cts → index-VXt_v3YI.d.cts} +1 -1
- package/dist/index.cjs +76 -593
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +308 -66
- package/dist/index.d.ts +308 -66
- package/dist/index.js +76 -593
- package/dist/index.js.map +1 -1
- package/dist/schemas.cjs +5 -3
- package/dist/schemas.cjs.map +1 -1
- package/dist/schemas.d.cts +2 -2
- package/dist/schemas.d.ts +2 -2
- package/dist/schemas.js +5 -3
- package/dist/scoring.cjs +3 -3
- package/dist/scoring.d.cts +242 -242
- package/dist/scoring.d.ts +242 -242
- package/dist/scoring.js +2 -2
- package/dist/xapi.cjs +3 -3
- package/dist/xapi.d.cts +1 -1
- package/dist/xapi.d.ts +1 -1
- package/dist/xapi.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-2JT2WUQ2.cjs.map +0 -1
- package/dist/chunk-DSDXL3JO.cjs.map +0 -1
- package/dist/chunk-FBKTION6.js.map +0 -1
- package/dist/chunk-RCZCP5OE.js +0 -729
- package/dist/chunk-RCZCP5OE.js.map +0 -1
- package/dist/chunk-W5KB3DNT.cjs +0 -729
- package/dist/chunk-W5KB3DNT.cjs.map +0 -1
- package/dist/chunk-XS6U2ARZ.js.map +0 -1
- /package/dist/{chunk-SJVRUPJT.js.map → chunk-JTNDIBZO.js.map} +0 -0
- /package/dist/{chunk-IARLJ5MW.js.map → chunk-QX2ERL72.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/chunk-W5KB3DNT.cjs","../src/ai-text.ts","../src/ai.ts","../src/ai-writing.ts"],"names":["folded","needle","score"],"mappings":"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AAA;AACG,IAAA;AACf,EAAA;AACW,EAAA;AACI,IAAA;AACf,EAAA;AACQ,EAAA;AACO,IAAA;AACf,EAAA;AACc,EAAA;AACA,EAAA;AACR,EAAA;AACK,EAAA;AACJ,IAAA;AACM,MAAA;AACX,IAAA;AACW,IAAA;AACA,MAAA;AACX,IAAA;AAEM,IAAA;AAGK,MAAA;AACX,IAAA;AAEW,IAAA;AACA,MAAA;AACX,IAAA;AACM,IAAA;AACA,IAAA;AACD,IAAA;AACI,MAAA;AACT,IAAA;AACK,IAAA;AACI,MAAA;AACT,IAAA;AACI,IAAA;AACM,IAAA;AACH,MAAA;AACM,QAAA;AACX,MAAA;AACU,MAAA;AACZ,IAAA;AACW,IAAA;AACA,IAAA;AACA,MAAA;AACX,IAAA;AACY,IAAA;AACA,MAAA;AACC,MAAA;AACP,MAAA;AACA,MAAA;AACG,MAAA;AACR,IAAA;AACH,EAAA;AACa,EAAA;AACf;AAGS;AACO,EAAA;AACL,IAAA;AACT,EAAA;AACY,EAAA;AAEHC,EAAAA;AAQX;AAGS;AAIK,EAAA;AACG,IAAA;AACf,EAAA;AACW,EAAA;AACI,IAAA;AACf,EAAA;AACQ,EAAA;AACO,IAAA;AACf,EAAA;AAEe,EAAA;AACA,IAAA;AACf,EAAA;AACM,EAAA;AACO,EAAA;AACP,EAAA;AACK,EAAA;AACJ,IAAA;AACM,MAAA;AACX,IAAA;AACM,IAAA;AACF,IAAA;AACO,MAAA;AACX,IAAA;AACS,IAAA;AACJ,IAAA;AACM,MAAA;AACX,IAAA;AACU,IAAA;AACC,MAAA;AACX,IAAA;AACa,IAAA;AACP,IAAA;AACI,IAAA;AACD,MAAA;AACT,IAAA;AACa,IAAA;AACJ,MAAA;AACT,IAAA;AACS,IAAA;AACD,MAAA;AACK,MAAA;AACA,MAAA;AACF,MAAA;AACG,MAAA;AACF,MAAA;AACV,MAAA;AACD,IAAA;AACH,EAAA;AACa,EAAA;AACf;AA0BgB;AAID,EAAA;AACC,EAAA;AACL,IAAA;AACT,EAAA;AACe,EAAA;AACT,EAAA;AACD,EAAA;AACI,IAAA;AACT,EAAA;AACe,EAAA;AACT,EAAA;AACQ,EAAA;AACL,IAAA;AACT,EAAA;AACI,EAAA;AACW,EAAA;AACH,EAAA;AACJ,IAAA;AACN,IAAA;AACF,EAAA;AACc,EAAA;AACP,EAAA;AACD,IAAA;AACM,IAAA;AACR,MAAA;AACA,MAAA;AACU,MAAA;AACV,MAAA;AACI,MAAA;AACA,MAAA;AACN,IAAA;AACF,EAAA;AACF;AH4SiB;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/chunk-W5KB3DNT.cjs","sourcesContent":[null,"/**\n * How the SDK reads text a model wrote, before a learner does. Internal: shared\n * by the AI checks, and exported by none of the package's entry points.\n */\n\n/**\n * Plain text as the learner will read it: line endings unified, control\n * characters other than line breaks and tabs removed, runs of blank lines\n * collapsed, the ends trimmed.\n */\nexport function cleanText(text: string): string {\n return (\n text\n .replace(/\\r\\n?/g, '\\n')\n // biome-ignore lint/suspicious/noControlCharactersInRegex: removing them is the point\n .replace(/[\\u0000-\\u0008\\u000B\\u000C\\u000E-\\u001F\\u007F-\\u009F\\u2028\\u2029]/g, '')\n .replace(/\\n{3,}/g, '\\n\\n')\n .trim()\n );\n}\n","import { cleanText } from './ai-text.js';\nimport { PLACEHOLDER_RE } from './schemas/fill-in-the-blanks.js';\nimport { alignDictation } from './scoring/dictation/align.js';\nimport { isGradeInRange } from './scoring/grade-numbers.js';\nimport { score } from './scoring/index.js';\nimport type {\n ActivityData,\n DictationData,\n FillInTheBlanksData,\n GapSelectData,\n ItemOutcome,\n LearnerResponse,\n MultipleChoiceData,\n ScoringDetail,\n} from './types/activity.js';\nimport type {\n AiActivityInput,\n AiExplanationRequest,\n AiFeature,\n AiGrade,\n AiHintRequest,\n AiItemFacts,\n AiProvenance,\n AiRefusal,\n AiSupportedActivityType,\n AiTextResult,\n AiVerdict,\n AiWordFact,\n} from './types/ai.js';\nimport type { GraderUsage } from './types/grading.js';\n\n/**\n * The activity types the SDK builds facts for, and which of them take hints.\n * A dictation takes none: its answer is the whole sentence, and it has\n * word-by-word hints of its own.\n */\nexport const AI_EXPLANATION_TYPES: readonly AiSupportedActivityType[] = [\n 'multiple-choice',\n 'fill-in-the-blanks',\n 'gap-select',\n 'dictation',\n];\nexport const AI_HINT_TYPES: readonly AiSupportedActivityType[] = [\n 'multiple-choice',\n 'fill-in-the-blanks',\n 'gap-select',\n];\n\n/** The longest AI text shown, in code points. Longer is refused, not cut. */\nexport const AI_TEXT_MAX_LENGTH = 2000;\n\n/**\n * Whether the SDK supports `feature` for this activity type: explanations and\n * hints for the types it builds facts for, and writing feedback for a written\n * response. A read-aloud, or a consumer's own type, has none.\n */\nexport function aiSupports(activityType: string, feature: AiFeature): boolean {\n if (feature === 'writing-feedback') {\n return activityType === 'written-response';\n }\n const types = feature === 'hint' ? AI_HINT_TYPES : AI_EXPLANATION_TYPES;\n return (types as readonly string[]).includes(activityType);\n}\n\n/**\n * Whether the item's author allows `feature`. Only an explicit `false`\n * switches it off: an author can refuse a feature, never force one on.\n *\n * Writing feedback reads `explanations`: both are a model's words about the\n * learner's own answer, and an author who switched one off has switched off\n * the other.\n */\nexport function aiAllowedByContent(data: AiActivityInput, feature: AiFeature): boolean {\n const permissions = (data as { ai?: unknown }).ai;\n if (typeof permissions !== 'object' || permissions === null) {\n return true;\n }\n const key = feature === 'hint' ? 'hints' : 'explanations';\n return (permissions as Record<string, unknown>)[key] !== false;\n}\n\n/** A grade as an explanation must speak to it: all marks, some, or none. */\nexport function aiGradeOf(result: { score: number; maxScore: number; passed: boolean }): AiGrade {\n const ratio = result.maxScore > 0 ? result.score / result.maxScore : 0;\n let category: AiVerdict = 'partly-correct';\n if (ratio >= 1 - 1e-9) {\n category = 'correct';\n } else if (ratio <= 1e-9) {\n category = 'incorrect';\n }\n return { score: result.score, maxScore: result.maxScore, passed: result.passed, category };\n}\n\n// ── Facts ──────────────────────────────────────────────────────────────\n\n/**\n * The ids of a passage's placeholders, in the order they appear. Read with the\n * schema's own expression, so a passage means here what it means to validation.\n */\nfunction placeholderOrder(passage: string): string[] {\n return [...passage.matchAll(PLACEHOLDER_RE)].map((match) => match[1] as string);\n}\n\n/** The passage with each placeholder written as `[n]`, in passage order. */\nfunction numberedPassage(passage: string): string {\n let position = 0;\n return passage.replace(PLACEHOLDER_RE, () => {\n position += 1;\n return `[${position}]`;\n });\n}\n\n/**\n * The `correct` flag a detail stored before 0.3 carries instead of an\n * `outcome`. On a blank, a gap or a word it meant the part was right; on a\n * multiple-choice option, that the learner acted rightly on it.\n */\nconst legacyCorrect = (detail: ScoringDetail): boolean =>\n (detail as { correct?: unknown }).correct === true;\n\n/** Whether a blank, a gap or a word was right, read from a server's detail. */\nfunction detailRight(detail: ScoringDetail): boolean {\n const outcome: unknown = detail.outcome;\n return outcome === undefined ? legacyCorrect(detail) : outcome === 'correct';\n}\n\n/** Whether an option is part of the answer, read from a server's detail (as the renderer reads it). */\nfunction isAnswerOption(detail: ScoringDetail, chosen: boolean): boolean {\n switch (detail.outcome) {\n case 'correct':\n case 'incorrect-omission':\n return true;\n case 'incorrect':\n case 'correct-omission':\n return false;\n default:\n return chosen ? legacyCorrect(detail) : !legacyCorrect(detail);\n }\n}\n\nconst firstString = (value: string | string[] | undefined): string | undefined =>\n Array.isArray(value) ? value[0] : value;\n\nconst listOf = (value: string | string[] | undefined): string[] | null =>\n value === undefined ? null : Array.isArray(value) ? [...value] : [value];\n\n/** The response a learner has before touching anything. */\nfunction emptyResponse(type: string): LearnerResponse | null {\n switch (type) {\n case 'multiple-choice':\n return { type: 'multiple-choice', selectedOptionIds: [] };\n case 'fill-in-the-blanks':\n return { type: 'fill-in-the-blanks', answers: {} };\n case 'gap-select':\n return { type: 'gap-select', selections: {} };\n case 'dictation':\n return { type: 'dictation', text: '' };\n default:\n return null;\n }\n}\n\nconst base = (data: AiActivityInput) => ({\n activityId: data.id,\n title: data.title,\n ...(typeof data.locale === 'string' ? { locale: data.locale } : {}),\n});\n\n/**\n * The facts a model is given about one item and one answer. `details` are the\n * SDK's per-part verdicts — from its own scorer, or from a server's outcome in\n * review — and every `correct` is `null` without them. A redacted item yields\n * facts without a key, which is what the learner's side holds; a port that\n * needs the key loads the item on its server.\n *\n * `null` for a type the SDK builds no facts for.\n */\nexport function buildAiFacts(\n data: AiActivityInput,\n response: LearnerResponse | null,\n details: readonly ScoringDetail[] | null,\n): AiItemFacts | null {\n const byId = new Map((details ?? []).map((detail) => [detail.itemId, detail]));\n const full = (data as { redacted?: unknown }).redacted !== true;\n switch (data.type) {\n case 'multiple-choice': {\n const item = data as unknown as MultipleChoiceData;\n const chosen = new Set(\n response?.type === 'multiple-choice' ? response.selectedOptionIds : [],\n );\n return {\n ...base(data),\n activityType: 'multiple-choice',\n question: item.question,\n mode: item.mode,\n options: item.options.map((option) => {\n const detail = byId.get(option.id);\n const wasChosen = chosen.has(option.id);\n let correct: boolean | null = null;\n if (full && typeof option.isCorrect === 'boolean') {\n correct = option.isCorrect;\n } else if (detail !== undefined) {\n correct = isAnswerOption(detail, wasChosen);\n }\n return {\n id: option.id,\n text: option.text,\n chosen: wasChosen,\n correct,\n ...(typeof option.feedback === 'string' ? { feedback: option.feedback } : {}),\n };\n }),\n };\n }\n case 'fill-in-the-blanks': {\n const item = data as unknown as FillInTheBlanksData;\n const answers = response?.type === 'fill-in-the-blanks' ? response.answers : {};\n const blanks = new Map(item.blanks.map((blank) => [blank.id, blank]));\n return {\n ...base(data),\n activityType: 'fill-in-the-blanks',\n passage: numberedPassage(item.passage),\n blanks: placeholderOrder(item.passage).map((id, index) => {\n const blank = blanks.get(id);\n const detail = byId.get(id);\n const accepted =\n full && Array.isArray(blank?.acceptedAnswers)\n ? [...blank.acceptedAnswers]\n : listOf(detail?.correctResponse);\n return {\n id,\n position: index + 1,\n typed: typeof answers[id] === 'string' ? (answers[id] as string) : '',\n accepted,\n correct: detail === undefined ? null : detailRight(detail),\n ...(typeof blank?.hint === 'string' ? { hint: blank.hint } : {}),\n ...(typeof blank?.feedback === 'string' ? { feedback: blank.feedback } : {}),\n };\n }),\n };\n }\n case 'gap-select': {\n const item = data as unknown as GapSelectData;\n const selections = response?.type === 'gap-select' ? response.selections : {};\n const gaps = new Map(item.gaps.map((gap) => [gap.id, gap]));\n const banks = new Map((item.banks ?? []).map((bank) => [bank.id, bank]));\n return {\n ...base(data),\n activityType: 'gap-select',\n passage: numberedPassage(item.passage),\n gaps: placeholderOrder(item.passage).map((id, index) => {\n const gap = gaps.get(id);\n const choices =\n gap?.choices ??\n (gap?.bankId === undefined ? [] : (banks.get(gap.bankId)?.choices ?? []));\n const textOf = (choiceId: string | undefined): string | null =>\n choiceId === undefined\n ? null\n : (choices.find((choice) => choice.id === choiceId)?.text ?? null);\n const detail = byId.get(id);\n const answerId =\n full && typeof gap?.correctChoiceId === 'string'\n ? gap.correctChoiceId\n : firstString(detail?.correctResponse);\n return {\n id,\n position: index + 1,\n choices: choices.map((choice) => choice.text),\n chosen: textOf(selections[id]),\n answer: textOf(answerId),\n correct: detail === undefined ? null : detailRight(detail),\n ...(typeof gap?.feedback === 'string' ? { feedback: gap.feedback } : {}),\n };\n }),\n };\n }\n case 'dictation': {\n const item = data as unknown as DictationData;\n const typed = response?.type === 'dictation' ? response.text : '';\n const hasKey = full && typeof item.transcript === 'string';\n let words: AiWordFact[] | null = null;\n if (hasKey) {\n words = alignDictation(item, typed).words.map((word) => ({\n expected: word.reference,\n typed: word.attempt,\n status: word.status,\n }));\n } else if (details !== null && details.length > 0) {\n words = details.map((detail) => {\n const expected = firstString(detail.correctResponse) ?? '';\n const attempt = firstString(detail.learnerResponse) ?? '';\n let status: 'correct' | 'incorrect' | 'missing' | 'extra' = 'incorrect';\n if (detailRight(detail)) {\n status = 'correct';\n } else if (attempt === '') {\n status = 'missing';\n } else if (expected === '') {\n status = 'extra';\n }\n return { expected, typed: attempt, status };\n });\n }\n return {\n ...base(data),\n activityType: 'dictation',\n transcript: hasKey ? item.transcript : null,\n typed,\n words,\n };\n }\n default:\n return null;\n }\n}\n\n/** The SDK's own grade of `response`, with its per-part details; `null` when it cannot grade. */\nfunction gradeLocally(\n data: AiActivityInput,\n response: LearnerResponse,\n): { details: ScoringDetail[]; grade: AiGrade } | null {\n if ((data as { redacted?: unknown }).redacted === true) {\n return null;\n }\n try {\n const result = score(data.type as never, data as unknown as ActivityData, response);\n return { details: result.details, grade: aiGradeOf(result) };\n } catch {\n return null;\n }\n}\n\n/**\n * The request for an explanation of `response`, or `null` when there is none\n * to give: an unsupported type, an author who switched explanations off,\n * nothing graded to explain, or a grade of record that cannot be a grade.\n *\n * A scored `outcome` — the grade of record a review shows — wins over grading\n * locally, so the explanation speaks to the grade on the screen. One whose\n * numbers cannot be a grade (the rule `outcomeFromGrade` applies: `maxScore`\n * positive and finite, `score` finite from 0 to it) gets no explanation at all:\n * explaining 85 \"out of 1\" would tell the model a wrong answer was correct, and\n * grading locally instead would speak to a grade the screen does not show.\n */\nexport function aiExplanationRequest(input: {\n data: AiActivityInput;\n response: LearnerResponse | null;\n outcome?: ItemOutcome;\n learnerLocale?: string;\n}): AiExplanationRequest | null {\n const { data, response, outcome, learnerLocale } = input;\n if (!aiSupports(data.type, 'explanation') || !aiAllowedByContent(data, 'explanation')) {\n return null;\n }\n let details: ScoringDetail[] | null = null;\n let grade: AiGrade | null = null;\n if (outcome?.status === 'scored') {\n // Read once, so the check and the grade handed on see the same numbers.\n const { score: recorded, maxScore, passed } = outcome;\n if (!isGradeInRange(recorded, maxScore)) {\n return null;\n }\n details = outcome.details;\n grade = aiGradeOf({ score: recorded, maxScore, passed });\n } else if (response !== null) {\n const local = gradeLocally(data, response);\n if (local !== null) {\n details = local.details;\n grade = local.grade;\n }\n }\n if (grade === null) {\n return null;\n }\n const facts = buildAiFacts(data, response, details);\n if (facts === null) {\n return null;\n }\n return {\n feature: 'explanation',\n facts,\n grade,\n ...(learnerLocale !== undefined ? { learnerLocale } : {}),\n };\n}\n\n/**\n * The request for the next hint on an unsubmitted answer, or `null` when\n * there is none to give: an unsupported type, an author who switched hints\n * off, or a redacted item — hints are for practice, where the item is whole.\n *\n * The facts carry the key, and which parts the learner has right so far, so a\n * model can hint where it helps. The learner never sees them; a hint that\n * contains an answer is refused by {@link checkAiHint}.\n */\nexport function aiHintRequest(input: {\n data: AiActivityInput;\n response: LearnerResponse | null;\n previousHints: readonly string[];\n learnerLocale?: string;\n}): AiHintRequest | null {\n const { data, previousHints, learnerLocale } = input;\n if (\n !aiSupports(data.type, 'hint') ||\n !aiAllowedByContent(data, 'hint') ||\n (data as { redacted?: unknown }).redacted === true\n ) {\n return null;\n }\n const response = input.response ?? emptyResponse(data.type);\n const local = response === null ? null : gradeLocally(data, response);\n const facts = buildAiFacts(data, response, local?.details ?? null);\n if (facts === null) {\n return null;\n }\n return {\n feature: 'hint',\n facts,\n hintNumber: previousHints.length + 1,\n previousHints: [...previousHints],\n ...(learnerLocale !== undefined ? { learnerLocale } : {}),\n };\n}\n\n// ── Checking what comes back ───────────────────────────────────────────\n\nconst VERDICTS: readonly string[] = ['correct', 'partly-correct', 'incorrect'];\n\n/** A provenance field a host may send, kept only when it is a short string. */\nfunction provenanceOf(raw: unknown): AiProvenance | undefined {\n if (typeof raw !== 'object' || raw === null) {\n return undefined;\n }\n const kept: AiProvenance = {};\n for (const key of ['model', 'promptHash', 'generatedAt'] as const) {\n const value = (raw as Record<string, unknown>)[key];\n if (typeof value === 'string' && value.length > 0 && value.length <= 200) {\n kept[key] = value;\n }\n }\n return Object.keys(kept).length > 0 ? kept : undefined;\n}\n\n/**\n * What the call cost, as a port reported it. Read on the same terms as the\n * provenance: a number that is not finite and zero or more says nothing about\n * a cost, so it is dropped rather than carried into a host's totals.\n */\nfunction usageOf(raw: unknown): GraderUsage | undefined {\n if (typeof raw !== 'object' || raw === null) {\n return undefined;\n }\n const kept: GraderUsage = {};\n for (const key of ['promptTokens', 'completionTokens', 'costUsd'] as const) {\n const value = (raw as Record<string, unknown>)[key];\n if (typeof value === 'number' && Number.isFinite(value) && value >= 0) {\n kept[key] = value;\n }\n }\n return Object.keys(kept).length > 0 ? kept : undefined;\n}\n\n/**\n * Reads what a port returned. Anything but an object with a string `text` is\n * `malformed`; text that is empty once cleaned, or longer than\n * {@link AI_TEXT_MAX_LENGTH}, is refused rather than shown or cut.\n */\nexport function readAiTextResult(\n raw: unknown,\n): { ok: true; result: AiTextResult } | { ok: false; refusal: AiRefusal } {\n if (typeof raw !== 'object' || raw === null || Array.isArray(raw)) {\n return { ok: false, refusal: 'malformed' };\n }\n const record = raw as Record<string, unknown>;\n if (typeof record.text !== 'string') {\n return { ok: false, refusal: 'malformed' };\n }\n if (record.verdict !== undefined && !VERDICTS.includes(record.verdict as string)) {\n return { ok: false, refusal: 'malformed' };\n }\n const text = cleanText(record.text);\n if (text === '') {\n return { ok: false, refusal: 'empty' };\n }\n if ([...text].length > AI_TEXT_MAX_LENGTH) {\n return { ok: false, refusal: 'too-long' };\n }\n const provenance = provenanceOf(record.provenance);\n const usage = usageOf(record.usage);\n return {\n ok: true,\n result: {\n text,\n ...(record.verdict !== undefined ? { verdict: record.verdict as AiVerdict } : {}),\n ...(provenance !== undefined ? { provenance } : {}),\n ...(usage !== undefined ? { usage } : {}),\n },\n };\n}\n\n/**\n * Checks an explanation a port returned for `request`. On top of\n * {@link readAiTextResult}: an explanation that states a verdict other than\n * the SDK's grade is refused (`contradicts-grade`) — it explains an answer\n * the learner did not get.\n */\nexport function checkAiExplanation(\n raw: unknown,\n request: AiExplanationRequest,\n): { ok: true; result: AiTextResult } | { ok: false; refusal: AiRefusal } {\n const read = readAiTextResult(raw);\n if (!read.ok) {\n return read;\n }\n if (read.result.verdict !== undefined && read.result.verdict !== request.grade.category) {\n return { ok: false, refusal: 'contradicts-grade' };\n }\n return read;\n}\n\n/**\n * Checks a hint a port returned for `request`. On top of\n * {@link readAiTextResult}: a hint that contains an answer is refused\n * (`reveals-answer`) — see {@link hintRevealsAnswer}.\n */\nexport function checkAiHint(\n raw: unknown,\n request: AiHintRequest,\n): { ok: true; result: AiTextResult } | { ok: false; refusal: AiRefusal } {\n const read = readAiTextResult(raw);\n if (!read.ok) {\n return read;\n }\n if (hintRevealsAnswer(request.facts, read.result.text)) {\n return { ok: false, refusal: 'reveals-answer' };\n }\n return read;\n}\n\n// ── The answer-leak guard ──────────────────────────────────────────────\n\n/**\n * Text folded for searching: compatibility forms read as what they stand for,\n * accents and other marks removed, lower-cased, and every run of anything but\n * letters and digits turned into one space. \"Está,\" and \"esta\" fold alike.\n */\nfunction fold(text: string): string[] {\n const folded = text\n .normalize('NFKD')\n .replace(/\\p{M}/gu, '')\n .toLowerCase()\n .replace(/[^\\p{L}\\p{N}]+/gu, ' ')\n .trim();\n return folded === '' ? [] : folded.split(' ');\n}\n\n/** Whether `needle` appears in `haystack` as a run of whole words. */\nfunction containsWords(haystack: readonly string[], needle: readonly string[]): boolean {\n if (needle.length === 0 || needle.length > haystack.length) {\n return false;\n }\n for (let start = 0; start + needle.length <= haystack.length; start += 1) {\n let match = true;\n for (let offset = 0; offset < needle.length; offset += 1) {\n if (haystack[start + offset] !== needle[offset]) {\n match = false;\n break;\n }\n }\n if (match) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * An answer too short to search for on its own: one word of fewer than four\n * characters — \"is\", \"the\", \"26\". A hint may use such a word freely; it\n * reveals the answer only when it writes it where the answer goes.\n */\nconst isShort = (words: readonly string[]): boolean =>\n words.length === 1 && [...(words[0] as string)].length < 4;\n\n/**\n * The words either side of the gap numbered `position` in a numbered\n * passage, other gaps left out.\n */\nfunction neighbours(passage: string, position: number): { before?: string; after?: string } {\n const marker = `[${position}]`;\n const at = passage.indexOf(marker);\n if (at === -1) {\n return {};\n }\n const strip = (text: string): string => text.replace(/\\[\\d+\\]/g, ' ');\n const left = fold(strip(passage.slice(0, at)));\n const right = fold(strip(passage.slice(at + marker.length)));\n const before = left[left.length - 1];\n const after = right[0];\n return {\n ...(before !== undefined ? { before } : {}),\n ...(after !== undefined ? { after } : {}),\n };\n}\n\n/**\n * Whether a hint gives away an answer, judged against the facts it was asked\n * for. It is a floor, not a proof: it finds an answer written out, not one\n * spelled letter by letter or described.\n *\n * - **Multiple choice:** the text of any correct option, as whole words.\n * - **Fill-in-the-blanks and gap select:** any accepted answer, as whole words.\n * An answer of one short word (\"is\", \"the\") counts only where the hint\n * writes it beside a neighbour it has in the passage — \"name is\", \"is\n * Rossi\" — so a hint may still use the word on its own.\n *\n * Case, accents and punctuation are ignored on both sides.\n */\nexport function hintRevealsAnswer(facts: AiItemFacts, hint: string): boolean {\n const words = fold(hint);\n const reveals = (answer: string, passage?: string, position?: number): boolean => {\n const needle = fold(answer);\n if (needle.length === 0) {\n return false;\n }\n if (!isShort(needle) || passage === undefined || position === undefined) {\n return containsWords(words, needle);\n }\n const { before, after } = neighbours(passage, position);\n if (before === undefined && after === undefined) {\n return containsWords(words, needle);\n }\n return (\n (before !== undefined && containsWords(words, [before, ...needle])) ||\n (after !== undefined && containsWords(words, [...needle, after]))\n );\n };\n switch (facts.activityType) {\n case 'multiple-choice':\n return facts.options.some((option) => option.correct === true && reveals(option.text));\n case 'fill-in-the-blanks':\n return facts.blanks.some((blank) =>\n (blank.accepted ?? []).some((answer) => reveals(answer, facts.passage, blank.position)),\n );\n case 'gap-select':\n return facts.gaps.some(\n (gap) => gap.answer !== null && reveals(gap.answer, facts.passage, gap.position),\n );\n case 'dictation':\n // Never asked: a dictation takes no AI hints (AI_HINT_TYPES).\n return false;\n default:\n return false;\n }\n}\n","import { aiAllowedByContent, aiSupports, readAiTextResult } from './ai.js';\nimport { cleanText } from './ai-text.js';\nimport { countWords } from './count-words.js';\nimport { gradeFromRubric } from './grading.js';\nimport type { LearnerResponse, WrittenResponseData } from './types/activity.js';\nimport type {\n AiActivityInput,\n AiRefusal,\n AiRubricCriterionFact,\n AiWritingFeedback,\n AiWritingFeedbackRequest,\n} from './types/ai.js';\nimport type { CriterionScore, InlineCorrection } from './types/grading.js';\n\n/** The most corrections one piece of writing feedback may carry. More is refused, not cut. */\nexport const AI_WRITING_MAX_CORRECTIONS = 20;\n\n/** The longest quote, correction, explanation or criterion comment, in code points. */\nexport const AI_WRITING_MAX_FIELD_LENGTH = 500;\n\n/** The longest `category` or `band`: a tag, not a sentence. */\nconst MAX_TAG_LENGTH = 40;\n\n/**\n * The request for feedback on a draft, or `null` when there is none to give:\n * not a written response, an author who switched explanations off (writing\n * feedback reads `ai.explanations`), a redacted item — feedback is for\n * practice, where the item is whole — or a draft with nothing in it.\n *\n * The facts are the task as the learner saw it, the draft verbatim with its\n * word count recomputed as the grader will count it, and the rubric the answer\n * will be graded on. `previousFeedback` is the text of the feedback already\n * shown on earlier drafts, so a model can speak to what changed.\n */\nexport function aiWritingFeedbackRequest(input: {\n data: AiActivityInput;\n response: LearnerResponse | null;\n previousFeedback?: readonly string[];\n learnerLocale?: string;\n}): AiWritingFeedbackRequest | null {\n const { data, response, learnerLocale } = input;\n if (\n !aiSupports(data.type, 'writing-feedback') ||\n !aiAllowedByContent(data, 'writing-feedback') ||\n (data as { redacted?: unknown }).redacted === true\n ) {\n return null;\n }\n const text = response?.type === 'written-response' ? response.text : '';\n if (typeof text !== 'string' || text.trim() === '') {\n return null;\n }\n const item = data as unknown as WrittenResponseData;\n const wordCount = countWords(text);\n const minWords = typeof item.minWords === 'number' ? item.minWords : 0;\n const maxWords = typeof item.maxWords === 'number' ? item.maxWords : Number.POSITIVE_INFINITY;\n const criteria = Array.isArray(item.rubric?.criteria) ? item.rubric.criteria : null;\n const rubric: AiRubricCriterionFact[] | null =\n criteria === null || criteria.length === 0\n ? null\n : criteria.map((criterion) => ({\n name: criterion.name,\n ...(typeof criterion.description === 'string'\n ? { description: criterion.description }\n : {}),\n weight: criterion.weight,\n }));\n const previousFeedback = [...(input.previousFeedback ?? [])];\n return {\n feature: 'writing-feedback',\n facts: {\n activityType: 'written-response',\n activityId: data.id,\n title: data.title,\n ...(typeof data.locale === 'string' ? { locale: data.locale } : {}),\n prompt: typeof item.prompt === 'string' ? item.prompt : '',\n text,\n wordCount,\n minWords,\n maxWords,\n withinWordBounds: wordCount >= minWords && wordCount <= maxWords,\n rubric,\n ...(typeof item.languageTarget === 'string' ? { languageTarget: item.languageTarget } : {}),\n },\n draftNumber: previousFeedback.length + 1,\n previousFeedback,\n ...(learnerLocale !== undefined ? { learnerLocale } : {}),\n };\n}\n\n// ── Finding a quote in the draft ───────────────────────────────────────\n\n/** Typographic quotes a model writes for the plain ones a learner typed, and back. */\nconst QUOTE_FOLD: Readonly<Record<string, string>> = {\n '‘': \"'\",\n '’': \"'\",\n '‛': \"'\",\n '′': \"'\",\n '“': '\"',\n '”': '\"',\n '„': '\"',\n '″': '\"',\n};\n\n/**\n * Text as a quote is matched against it: typographic quotes folded to plain\n * ones and every run of whitespace one space — the two liberties a model takes\n * when it copies words out — with, for each folded character, where it came\n * from, so a match maps back to the learner's own text. Case is kept: a\n * correction of \"i\" to \"I\" is about case.\n */\nfunction folded(text: string): { chars: string; from: number[] } {\n let chars = '';\n const from: number[] = [];\n let space = false;\n for (let at = 0; at < text.length; at += 1) {\n const char = text[at] as string;\n if (/\\s/u.test(char)) {\n if (!space) {\n chars += ' ';\n from.push(at);\n space = true;\n }\n continue;\n }\n space = false;\n chars += QUOTE_FOLD[char] ?? char;\n from.push(at);\n }\n return { chars, from };\n}\n\n/** A quote as it is searched for: folded, and without the spaces around it. */\nconst needle = (quote: string): string => folded(quote).chars.trim();\n\n/**\n * Where `quote` sits in the draft: at `claimed`, when the model named a range —\n * which must then hold the quote — or else at its first occurrence not already\n * taken by an identical quote, so a mistake made twice is anchored twice. A\n * quote corrected more often than it occurs takes its first occurrence again.\n * `null` when the draft does not contain it where claimed, or at all.\n */\nfunction anchor(\n draft: { text: string; chars: string; from: number[] },\n quote: string,\n claimed: { start: number; end: number } | undefined,\n taken: Set<string>,\n): { start: number; end: number } | null {\n const sought = needle(quote);\n if (sought === '') {\n return null;\n }\n if (claimed !== undefined) {\n const { start, end } = claimed;\n if (\n !Number.isSafeInteger(start) ||\n !Number.isSafeInteger(end) ||\n start < 0 ||\n end > draft.text.length ||\n start >= end\n ) {\n return null;\n }\n const span = draft.text.slice(start, end);\n if (needle(span) !== sought) {\n return null;\n }\n // The span, without whitespace the model's range took in at either end.\n const lead = span.length - span.trimStart().length;\n const trail = span.length - span.trimEnd().length;\n return { start: start + lead, end: end - trail };\n }\n let first: { start: number; end: number } | null = null;\n for (let at = draft.chars.indexOf(sought); at !== -1; at = draft.chars.indexOf(sought, at + 1)) {\n const start = draft.from[at] as number;\n const end = (draft.from[at + sought.length - 1] as number) + 1;\n const found = { start, end };\n first ??= found;\n const key = `${start}:${end}`;\n if (!taken.has(key)) {\n taken.add(key);\n return found;\n }\n }\n return first;\n}\n\n// ── Checking what comes back ───────────────────────────────────────────\n\n/** A field that must be a string, at most `max` code points once cleaned; `undefined` when absent. */\nfunction textField(\n value: unknown,\n max: number,\n): { ok: true; value: string | undefined } | { ok: false; refusal: AiRefusal } {\n if (value === undefined || value === null) {\n return { ok: true, value: undefined };\n }\n if (typeof value !== 'string') {\n return { ok: false, refusal: 'malformed' };\n }\n const cleaned = cleanText(value);\n if ([...cleaned].length > max) {\n return { ok: false, refusal: 'too-long' };\n }\n return { ok: true, value: cleaned === '' ? undefined : cleaned };\n}\n\nconst isRecord = (value: unknown): value is Record<string, unknown> =>\n typeof value === 'object' && value !== null && !Array.isArray(value);\n\n/** The corrections, each anchored in the draft, or why the reply is refused. */\nfunction checkCorrections(\n raw: unknown,\n text: string,\n): { ok: true; corrections: InlineCorrection[] } | { ok: false; refusal: AiRefusal } {\n if (raw === undefined || raw === null) {\n return { ok: true, corrections: [] };\n }\n if (!Array.isArray(raw)) {\n return { ok: false, refusal: 'malformed' };\n }\n if (raw.length > AI_WRITING_MAX_CORRECTIONS) {\n return { ok: false, refusal: 'too-long' };\n }\n const draft = { text, ...folded(text) };\n const taken = new Set<string>();\n const corrections: InlineCorrection[] = [];\n for (const entry of raw) {\n if (!isRecord(entry) || typeof entry.original !== 'string') {\n return { ok: false, refusal: 'malformed' };\n }\n if (typeof entry.corrected !== 'string') {\n return { ok: false, refusal: 'malformed' };\n }\n if (\n [...entry.original].length > AI_WRITING_MAX_FIELD_LENGTH ||\n [...entry.corrected].length > AI_WRITING_MAX_FIELD_LENGTH\n ) {\n return { ok: false, refusal: 'too-long' };\n }\n // A correction that changes nothing corrects nothing.\n if (needle(entry.original) === needle(entry.corrected)) {\n return { ok: false, refusal: 'malformed' };\n }\n const explanation = textField(entry.explanation, AI_WRITING_MAX_FIELD_LENGTH);\n const category = textField(entry.category, MAX_TAG_LENGTH);\n if (!explanation.ok) {\n return explanation;\n }\n if (!category.ok) {\n return category;\n }\n let claimed: { start: number; end: number } | undefined;\n if (entry.range !== undefined && entry.range !== null) {\n if (!isRecord(entry.range)) {\n return { ok: false, refusal: 'malformed' };\n }\n claimed = { start: entry.range.start as number, end: entry.range.end as number };\n }\n const at = anchor(draft, entry.original, claimed, taken);\n if (at === null) {\n return { ok: false, refusal: 'misquotes-answer' };\n }\n corrections.push({\n original: text.slice(at.start, at.end),\n corrected: cleanText(entry.corrected),\n ...(explanation.value !== undefined ? { explanation: explanation.value } : {}),\n ...(category.value !== undefined ? { category: category.value } : {}),\n range: at,\n });\n }\n return { ok: true, corrections };\n}\n\n/** A criterion score a grade could be computed from: finite, 0 or more, and not above its maximum. */\nfunction isJudgedScore(score: unknown, maxScore: unknown): boolean {\n if (score === undefined) {\n return maxScore === undefined || (typeof maxScore === 'number' && maxScore > 0);\n }\n const max = maxScore ?? 1;\n return (\n typeof score === 'number' &&\n typeof max === 'number' &&\n Number.isFinite(score) &&\n Number.isFinite(max) &&\n max > 0 &&\n score >= 0 &&\n score - max <= max * 1e-9\n );\n}\n\n/** The judgements, each on a criterion the author wrote and weighted as the author weighted it. */\nfunction checkCriteria(\n raw: unknown,\n rubric: readonly AiRubricCriterionFact[] | null,\n): { ok: true; criteria: CriterionScore[] } | { ok: false; refusal: AiRefusal } {\n if (raw === undefined || raw === null) {\n return { ok: true, criteria: [] };\n }\n if (!Array.isArray(raw)) {\n return { ok: false, refusal: 'malformed' };\n }\n if (raw.length === 0) {\n return { ok: true, criteria: [] };\n }\n // Judging a criterion the author did not write is judging a different task.\n if (rubric === null) {\n return { ok: false, refusal: 'malformed' };\n }\n const weights = new Map(rubric.map((criterion) => [criterion.name, criterion.weight]));\n const seen = new Set<string>();\n const criteria: CriterionScore[] = [];\n for (const entry of raw) {\n if (!isRecord(entry) || typeof entry.name !== 'string') {\n return { ok: false, refusal: 'malformed' };\n }\n const weight = weights.get(entry.name);\n if (weight === undefined || seen.has(entry.name)) {\n return { ok: false, refusal: 'malformed' };\n }\n seen.add(entry.name);\n if (!isJudgedScore(entry.score, entry.maxScore)) {\n return { ok: false, refusal: 'malformed' };\n }\n if (entry.notApplicable !== undefined && typeof entry.notApplicable !== 'boolean') {\n return { ok: false, refusal: 'malformed' };\n }\n const band = textField(entry.band, MAX_TAG_LENGTH);\n const comment = textField(entry.comment, AI_WRITING_MAX_FIELD_LENGTH);\n if (!band.ok) {\n return band;\n }\n if (!comment.ok) {\n return comment;\n }\n criteria.push({\n name: entry.name,\n ...(typeof entry.score === 'number' ? { score: entry.score } : {}),\n ...(typeof entry.maxScore === 'number' ? { maxScore: entry.maxScore } : {}),\n ...(band.value !== undefined ? { band: band.value } : {}),\n ...(comment.value !== undefined ? { comment: comment.value } : {}),\n ...(entry.notApplicable === true ? { notApplicable: true } : {}),\n weight,\n });\n }\n return { ok: true, criteria };\n}\n\n/**\n * Checks writing feedback a port returned for `request`, and turns it into what\n * a learner is shown. The SDK shows a model's feedback whole or not at all: it\n * never drops the part it doubts and shows the rest.\n *\n * - **The text** is read as every AI text is (`readAiTextResult`): plain text,\n * not empty, at most {@link AI_TEXT_MAX_LENGTH} code points.\n * - **Every correction must quote the draft** — the check only this SDK can run.\n * The SDK finds each quote in the draft itself, typographic quotes and runs of\n * whitespace aside, and anchors it there; a range the model claims must hold\n * the quote. A correction of words the learner did not write refuses the\n * whole reply as `misquotes-answer`, as a hint that gives the answer away\n * refuses the hint. The `original` shown is the draft's own text at the range.\n * At most {@link AI_WRITING_MAX_CORRECTIONS}; a correction that changes\n * nothing is `malformed`.\n * - **Criteria are judgements; the arithmetic is the SDK's.** Each names a\n * criterion of the item's rubric, once; its score, when it has one, is a\n * score out of its `maxScore`. The rubric's weights are attached, whatever\n * the model sent. Anything else is `malformed`, as is any criterion on an\n * item with no rubric.\n * - **`indicativeScore`** is the rubric's weighted total, computed as\n * `gradeFromRubric` computes a grade, when every criterion of the rubric was\n * judged; `null` otherwise. An indication, never a grade.\n */\nexport function checkAiWritingFeedback(\n raw: unknown,\n request: AiWritingFeedbackRequest,\n): { ok: true; feedback: AiWritingFeedback } | { ok: false; refusal: AiRefusal } {\n const read = readAiTextResult(raw);\n if (!read.ok) {\n return read;\n }\n const record = raw as Record<string, unknown>;\n const corrections = checkCorrections(record.corrections, request.facts.text);\n if (!corrections.ok) {\n return corrections;\n }\n const rubric = request.facts.rubric;\n const criteria = checkCriteria(record.criteria, rubric);\n if (!criteria.ok) {\n return criteria;\n }\n let indicativeScore: number | null = null;\n const judged = new Set(criteria.criteria.map((criterion) => criterion.name));\n if (rubric?.every((criterion) => judged.has(criterion.name))) {\n const grade = gradeFromRubric(criteria.criteria);\n indicativeScore = 'unscorable' in grade ? null : grade.score;\n }\n const { text, provenance, usage } = read.result;\n return {\n ok: true,\n feedback: {\n text,\n corrections: corrections.corrections,\n criteria: criteria.criteria,\n indicativeScore,\n ...(provenance !== undefined ? { provenance } : {}),\n ...(usage !== undefined ? { usage } : {}),\n },\n };\n}\n"]}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/schemas/item-group.ts","../src/timeline-limits.ts","../src/schemas/json-schema.ts","../src/schemas/index.ts"],"sourcesContent":["import { z } from 'zod/v4';\nimport { getActivityTypeDescriptor } from '../registry/index.js';\nimport {\n INTERACTIVE_VIDEO_ITEM_TYPES,\n isInteractiveVideoItemType,\n TIMELINE_MAX_CHAPTERS,\n TIMELINE_MAX_ITEMS,\n TIMELINE_MAX_QUIZZES,\n TIMELINE_MAX_TITLE_LENGTH,\n} from '../timeline-limits.js';\nimport type { ActivityData, ValidationError, ValidationResult } from '../types/activity.js';\nimport type { ItemGroup, StimulusKind } from '../types/item-group.js';\nimport { GROUP_CAPTIONS_REVEAL_DICTATION, groupCaptionsField } from './dictation.js';\nimport { MediaSchema, RedactedMediaSchema } from './media.js';\nimport { readSchema } from './read-schema.js';\nimport { maxUnits } from './text-length.js';\n\n/**\n * An authored slot key.\n *\n * A `.` is rejected here, not at render time: `flattenSequence` uses the first\n * `.` to separate a group from its item, so a key containing one would produce\n * an ambiguous slot id. `keyOf` already threw on it — this moves the rejection\n * to `validateItemGroup`, where an author finds it, instead of leaving it to\n * surface when a learner opens the paper. Content that would newly fail\n * validation already threw at flatten time, so it can never have been sat.\n */\nconst SlotKeySchema = z\n .string()\n .min(1)\n .refine((key) => !key.includes('.'), {\n error:\n 'slotKey must not contain \".\" — that character separates a group from its item in a slot id, so a key containing one would make the slot ambiguous.',\n });\n\nfunction hasBody(stimulus: { body?: string | undefined }): boolean {\n return typeof stimulus.body === 'string' && stimulus.body.trim().length > 0;\n}\n\n/** Which media types can carry a stimulus of each kind. `text`/`mixed` accept any. */\nfunction mediaFits(kind: StimulusKind, mediaType: string | undefined): boolean {\n switch (kind) {\n case 'audio':\n return mediaType === 'audio';\n case 'video':\n return mediaType === 'video' || mediaType === 'embed';\n case 'image':\n return mediaType === 'image';\n default:\n return true;\n }\n}\n\n/**\n * Zod schema for a {@link Stimulus}. Loose: unknown keys preserved.\n *\n * The semantic guards exist because a stimulus that does not carry what its\n * `kind` promises is an authoring error that must not reach an exam: an\n * \"audio\" stimulus with no recording renders as a blank panel above six\n * listening questions. Unrepresentable in JSON Schema; dropped from\n * `stimulusJsonSchema` by design.\n */\nexport const StimulusSchema = z\n .looseObject({\n id: z.string().min(1),\n kind: z.enum(['text', 'audio', 'video', 'image', 'mixed']),\n title: z.string().optional(),\n body: z.string().optional(),\n bodyHtml: z.string().optional(),\n media: MediaSchema.optional(),\n transcript: z.string().optional(),\n locale: z.string().optional(),\n attribution: z.string().optional(),\n })\n .refine((stimulus) => stimulus.bodyHtml === undefined || hasBody(stimulus), {\n error:\n 'bodyHtml requires a plain-text body: it is the accessible fallback rendered when no sanitiser is supplied.',\n path: ['body'],\n })\n .refine(\n (stimulus) => (stimulus.kind !== 'text' && stimulus.kind !== 'mixed') || hasBody(stimulus),\n {\n error: 'A text or mixed stimulus needs a non-empty body.',\n path: ['body'],\n },\n )\n .refine((stimulus) => stimulus.kind === 'text' || stimulus.media !== undefined, {\n error: 'An audio, video, image or mixed stimulus needs media.',\n path: ['media'],\n })\n .refine(\n (stimulus) => stimulus.media === undefined || mediaFits(stimulus.kind, stimulus.media.type),\n {\n error:\n 'media.type does not fit the stimulus kind: audio needs audio; video needs video or embed; image needs image.',\n path: ['media', 'type'],\n },\n );\n\nconst TimelineTitleSchema = maxUnits(z.string(), TIMELINE_MAX_TITLE_LENGTH).refine(\n (title) => title.trim().length > 0,\n { error: 'A title must not be empty.' },\n);\n\n/** Seconds from the start of the video. zod rejects NaN and ±Infinity itself. */\nconst TimelineTimeSchema = z.number().min(0, { error: 'A time is 0 seconds or more.' });\n\n/**\n * A quiz. STRICT, like every part of a timeline: a misspelt `requried` would\n * otherwise be kept and the quiz silently optional on a paper that believed it\n * was required.\n */\nexport const TimelineCueSchema = z.strictObject({\n id: maxUnits(z.string().min(1), 64),\n at: TimelineTimeSchema,\n itemIds: z.array(z.string().min(1)).min(1).max(TIMELINE_MAX_ITEMS),\n title: TimelineTitleSchema.optional(),\n required: z.boolean().optional(),\n});\n\nexport const TimelineChapterSchema = z.strictObject({\n at: TimelineTimeSchema,\n title: TimelineTitleSchema,\n});\n\n/**\n * A timeline on its own: its quizzes, chapters and navigation. The rules that\n * need the group — every item in exactly one quiz, a video stimulus, the five\n * item types — are {@link timelineIssues}, which both group schemas run.\n */\nexport const MediaTimelineSchema = z\n .strictObject({\n cues: z.array(TimelineCueSchema).max(TIMELINE_MAX_QUIZZES),\n chapters: z.array(TimelineChapterSchema).max(TIMELINE_MAX_CHAPTERS).optional(),\n navigation: z.enum(['free', 'no-skip-ahead']).optional(),\n })\n .check((ctx) => {\n const seen = new Set<string>();\n ctx.value.cues.forEach((cue, index) => {\n if (seen.has(cue.id)) {\n ctx.issues.push({\n code: 'custom',\n input: cue.id,\n message: `Quiz id \"${cue.id}\" is used twice: events, drafts and the contents panel name a quiz by its id.`,\n path: ['cues', index, 'id'],\n });\n }\n seen.add(cue.id);\n });\n // Strictly increasing, not merely sorted: two chapters starting at one\n // moment leave the first with no length, and the scrubber no room to draw it.\n const chapters = ctx.value.chapters ?? [];\n chapters.forEach((chapter, index) => {\n const previous = chapters[index - 1];\n if (previous !== undefined && chapter.at <= previous.at) {\n ctx.issues.push({\n code: 'custom',\n input: chapter.at,\n message: 'Chapter times must be strictly increasing.',\n path: ['chapters', index, 'at'],\n });\n }\n });\n });\n\n/** A URL only this document can resolve, or one that inlines the bytes. */\nfunction isLocalOnlyUrl(url: unknown): boolean {\n return typeof url === 'string' && /^(data|blob):/i.test(url);\n}\n\n/**\n * The rules of an interactive video that span the timeline, the stimulus and\n * the items. Run by the content schema and, for everything but the two\n * authoring-only rules, by the strict redacted schema — a projection built by\n * hand never passed through the content schema.\n *\n * Items are read defensively: the redacted schema leaves them opaque, and each\n * is proven against its own type's schema elsewhere.\n */\nfunction timelineIssues(\n group: {\n stimulus: {\n kind: string;\n media?:\n | {\n type: string;\n url: string;\n poster?: string | undefined;\n tracks?: readonly { src: string }[] | undefined;\n }\n | undefined;\n };\n items: readonly unknown[];\n shuffle?: string | undefined;\n timeline?: { cues: readonly { itemIds: readonly string[] }[] } | undefined;\n },\n scope: 'content' | 'redacted',\n): { path: (string | number)[]; message: string; input: unknown }[] {\n const timeline = group.timeline;\n if (timeline === undefined) {\n return [];\n }\n const issues: { path: (string | number)[]; message: string; input: unknown }[] = [];\n const media = group.stimulus.media;\n\n // Reported at the field that is wrong, so an editor's own check at that path\n // can stand in for it without hiding anything else about the stimulus.\n if (group.stimulus.kind !== 'video') {\n issues.push({\n path: ['stimulus', 'kind'],\n input: group.stimulus.kind,\n message:\n 'An interactive video needs a video stimulus: quizzes open at moments of a video, and nothing else has them.',\n });\n } else if (media !== undefined && media.type !== 'video') {\n issues.push({\n path: ['stimulus', 'media', 'type'],\n input: media.type,\n message:\n 'An interactive video needs a video file. An embedded provider player cannot be paused at the moment a quiz opens.',\n });\n }\n if (group.shuffle === 'within-group') {\n issues.push({\n path: ['shuffle'],\n input: group.shuffle,\n message:\n 'An interactive video presents its questions in the order its quizzes open; shuffle: \"within-group\" cannot apply to it.',\n });\n }\n if (group.items.length > TIMELINE_MAX_ITEMS) {\n issues.push({\n path: ['items'],\n input: group.items.length,\n message: `An interactive video holds at most ${TIMELINE_MAX_ITEMS} questions.`,\n });\n }\n\n const itemIds = new Map<string, number>();\n group.items.forEach((item, index) => {\n const {\n id,\n type,\n media: itemMedia,\n } = (item ?? {}) as { id?: unknown; type?: unknown; media?: unknown };\n if (typeof id === 'string') {\n itemIds.set(id, index);\n }\n if (!isInteractiveVideoItemType(type)) {\n issues.push({\n path: ['items', index, 'type'],\n input: type,\n message: `An interactive video may hold only ${INTERACTIVE_VIDEO_ITEM_TYPES.join(', ')} questions.`,\n });\n }\n // The \"play the stimulus\" fallback a dictation has in a listening group\n // means nothing halfway through a video.\n if (scope === 'content' && type === 'dictation' && itemMedia === undefined) {\n issues.push({\n path: ['items', index, 'media'],\n input: itemMedia,\n message: 'A dictation inside an interactive video needs its own recording.',\n });\n }\n });\n\n const placed = new Set<string>();\n timeline.cues.forEach((cue, cueIndex) => {\n cue.itemIds.forEach((itemId, position) => {\n const path = ['timeline', 'cues', cueIndex, 'itemIds', position];\n if (!itemIds.has(itemId)) {\n issues.push({\n path,\n input: itemId,\n message: `No item in this group has the id \"${itemId}\".`,\n });\n } else if (placed.has(itemId)) {\n issues.push({\n path,\n input: itemId,\n message: `Item \"${itemId}\" is placed twice: every question belongs to exactly one quiz.`,\n });\n }\n placed.add(itemId);\n });\n });\n for (const [itemId, index] of itemIds) {\n if (!placed.has(itemId)) {\n issues.push({\n path: ['items', index],\n input: itemId,\n message: `Item \"${itemId}\" is in no quiz, so the video would never show it.`,\n });\n }\n }\n\n // A `data:` video swells the payload and every fingerprint over it; a stored\n // `blob:` URL means nothing in another document.\n if (scope === 'content' && media !== undefined) {\n const urls: [unknown, (string | number)[]][] = [\n [media.url, ['stimulus', 'media', 'url']],\n [media.poster, ['stimulus', 'media', 'poster']],\n ...(media.tracks ?? []).map((track, index): [unknown, (string | number)[]] => [\n track.src,\n ['stimulus', 'media', 'tracks', index, 'src'],\n ]),\n ];\n for (const [url, path] of urls) {\n if (isLocalOnlyUrl(url)) {\n issues.push({\n path,\n input: url,\n message:\n 'An interactive video is stored and served: its URLs cannot be data: or blob: URLs.',\n });\n }\n }\n }\n return issues;\n}\n\n/**\n * The structural minimum of an item as seen by the CONTAINER schema. Each\n * item's own contract is checked against its registered schema by\n * {@link validateItemGroup} — a zod schema cannot dispatch on a registry\n * that consumers extend at runtime.\n */\nconst ItemShapeSchema = z.looseObject({\n type: z.string().min(1),\n id: z.string().min(1),\n slotKey: SlotKeySchema.optional(),\n});\n\n/**\n * Zod schema for an {@link ItemGroup} CONTAINER. Loose: unknown keys\n * preserved. Validates the group's own fields and the stimulus in full, and\n * each item only structurally (`type` and `id`); use {@link validateItemGroup}\n * to validate the items against their registered schemas as well.\n */\nexport const ItemGroupSchema = z\n .looseObject({\n schemaVersion: z.literal('1.0'),\n type: z.literal('item-group'),\n id: z.string().min(1),\n title: z.string().optional(),\n slotKey: SlotKeySchema.optional(),\n stimulus: StimulusSchema,\n items: z.array(ItemShapeSchema).min(1),\n shuffle: z.enum(['none', 'within-group']).optional(),\n timeline: MediaTimelineSchema.optional(),\n })\n .refine((group) => group.items.every((item) => item.type !== 'item-group'), {\n error: 'Item groups do not nest: every item must be an activity.',\n path: ['items'],\n })\n .refine((group) => new Set(group.items.map((item) => item.id)).size === group.items.length, {\n error: 'Item ids must be unique within a group.',\n path: ['items'],\n })\n .check((ctx) => {\n for (const issue of timelineIssues(ctx.value, 'content')) {\n ctx.issues.push({ code: 'custom', ...issue });\n }\n });\n\n/** Strict learner-safe stimulus: everything but the author-only `transcript`. */\nexport const RedactedStimulusSchema = z.strictObject({\n id: z.string().min(1),\n kind: z.enum(['text', 'audio', 'video', 'image', 'mixed']),\n title: z.string().optional(),\n body: z.string().optional(),\n bodyHtml: z.string().optional(),\n media: RedactedMediaSchema.optional(),\n locale: z.string().optional(),\n attribution: z.string().optional(),\n});\n\n/**\n * Strict learner-safe item group. Items are left opaque here — each is proven\n * learner-safe by `assertRedacted` against its OWN type's redacted schema,\n * which is the only place that knowledge lives. The one exception is the one\n * rule that spans the container and an item: a captioned stimulus recording\n * played to a dictation is not learner-safe, because the captions are the\n * dictation's answer.\n */\nexport const RedactedItemGroupSchema = z\n .strictObject({\n redacted: z.literal(true),\n schemaVersion: z.literal('1.0'),\n type: z.literal('item-group'),\n id: z.string().min(1),\n title: z.string().optional(),\n slotKey: SlotKeySchema.optional(),\n stimulus: RedactedStimulusSchema,\n items: z.array(z.unknown()).min(1),\n shuffle: z.enum(['none', 'within-group']).optional(),\n timeline: MediaTimelineSchema.optional(),\n })\n .check((ctx) => {\n for (const issue of timelineIssues(ctx.value, 'redacted')) {\n ctx.issues.push({ code: 'custom', ...issue });\n }\n const captions = groupCaptionsField(ctx.value);\n if (captions !== undefined) {\n ctx.issues.push({\n code: 'custom',\n input: ctx.value.stimulus.media?.[captions],\n message: GROUP_CAPTIONS_REVEAL_DICTATION,\n path: ['stimulus', 'media', captions],\n });\n }\n });\n\nfunction toValidationErrors(\n issues: readonly { path: readonly PropertyKey[]; message: string; code: string }[],\n prefix: string[],\n): ValidationError[] {\n return issues.map((issue) => ({\n path: [...prefix, ...issue.path.map(String)],\n message: issue.message,\n code: issue.code,\n }));\n}\n\n/**\n * Validates an item group in full: the container and stimulus against\n * {@link ItemGroupSchema}, then every item against the schema registered for\n * its `type`. Errors from items are reported at `items.<index>.…`.\n *\n * Unlike `validateActivity`, an item whose type is not registered is REPORTED\n * (code `unknown_activity_type`) rather than thrown: a group is validated as\n * a whole, and an author fixing a six-item group wants every problem listed,\n * not the first one that happened to throw.\n */\nexport function validateItemGroup(data: unknown): ValidationResult<ItemGroup> {\n const container = ItemGroupSchema.safeParse(data);\n if (!container.success) {\n return { success: false, errors: toValidationErrors(container.error.issues, []) };\n }\n\n const errors: ValidationError[] = [];\n const items: ActivityData[] = [];\n container.data.items.forEach((item, index) => {\n const descriptor = getActivityTypeDescriptor(item.type);\n if (descriptor === undefined) {\n errors.push({\n path: ['items', String(index), 'type'],\n message: `Activity type \"${item.type}\" is not registered`,\n code: 'unknown_activity_type',\n });\n return;\n }\n const parsed = readSchema(descriptor.schema, item, `Activity type \"${descriptor.type}\"`);\n if (!parsed.success) {\n errors.push(...toValidationErrors(parsed.issues, ['items', String(index)]));\n return;\n }\n items.push(parsed.data as ActivityData);\n });\n const captions = groupCaptionsField(container.data);\n if (captions !== undefined) {\n errors.push({\n path: ['stimulus', 'media', captions],\n message: GROUP_CAPTIONS_REVEAL_DICTATION,\n code: 'custom',\n });\n }\n\n if (errors.length > 0) {\n return { success: false, errors };\n }\n // zod4 optional outputs are `T | undefined`; the wire type uses exact\n // optionals. Structurally identical at runtime — the cast is type-level.\n return { success: true, data: { ...container.data, items } as unknown as ItemGroup };\n}\n","/**\n * The bounds of an interactive video — an item group with a `timeline`.\n *\n * A leaf module on purpose: the schemas, the authoring checks and the timeline\n * helpers all read these, and nothing here may import any of them back.\n */\n\n/**\n * The item types an interactive video may present. CLOSED on purpose: a type\n * added to the SDK later, or a custom type a host registers, is not silently\n * embeddable. Each one here was chosen, and each works inside a paused video —\n * a read-aloud's microphone included, because every quiz pauses the video\n * first.\n */\nexport const INTERACTIVE_VIDEO_ITEM_TYPES = [\n 'multiple-choice',\n 'fill-in-the-blanks',\n 'gap-select',\n 'dictation',\n 'read-aloud',\n] as const;\n\n/** One of {@link INTERACTIVE_VIDEO_ITEM_TYPES}. */\nexport type InteractiveVideoItemType = (typeof INTERACTIVE_VIDEO_ITEM_TYPES)[number];\n\n/** Whether `type` is one of the item types an interactive video may present. */\nexport function isInteractiveVideoItemType(type: unknown): type is InteractiveVideoItemType {\n return (INTERACTIVE_VIDEO_ITEM_TYPES as readonly unknown[]).includes(type);\n}\n\n/** The most quizzes one video may hold. */\nexport const TIMELINE_MAX_QUIZZES = 100;\n\n/**\n * The most questions one interactive video may hold, across all its quizzes.\n * The player keeps every one of them mounted, so an answer survives the\n * learner rewinding past its quiz.\n */\nexport const TIMELINE_MAX_ITEMS = 200;\n\n/** The most chapters one video may hold. */\nexport const TIMELINE_MAX_CHAPTERS = 100;\n\n/** The longest quiz or chapter title, in UTF-16 units. A title sits on one line of the player. */\nexport const TIMELINE_MAX_TITLE_LENGTH = 120;\n","import { z } from 'zod/v4';\nimport { UnknownActivityTypeError } from '../errors.js';\nimport { getActivityTypeDescriptor } from '../registry/index.js';\nimport { DictationDataSchema } from './dictation.js';\nimport { FillInTheBlanksDataSchema } from './fill-in-the-blanks.js';\nimport { GapSelectDataSchema } from './gap-select.js';\nimport { ItemGroupSchema, StimulusSchema } from './item-group.js';\nimport { MultipleChoiceDataSchema } from './multiple-choice.js';\nimport { ReadAloudDataSchema } from './read-aloud.js';\nimport { isOwnSchema, standardJsonSchemaOf } from './read-schema.js';\nimport { WrittenResponseDataSchema } from './written-response.js';\n\n/**\n * JSON Schema (Draft 7) for a `Stimulus`. Structural contract only — the\n * kind/media/body consistency guards are Zod-only.\n */\nexport const stimulusJsonSchema: Record<string, unknown> = z.toJSONSchema(StimulusSchema, {\n target: 'draft-7',\n});\n\n/**\n * JSON Schema (Draft 7) for an `ItemGroup` CONTAINER. Items appear as objects\n * with `type` and `id` only; each item's own contract is `jsonSchemaFor(type)`.\n * For an AI generation pipeline, ask for the group and each item separately\n * rather than a single nested schema — that keeps the per-type schema the\n * registry's, not a copy.\n */\nexport const itemGroupJsonSchema: Record<string, unknown> = z.toJSONSchema(ItemGroupSchema, {\n target: 'draft-7',\n});\n\n/**\n * JSON Schema (Draft 7) representation of the Multiple Choice activity data\n * contract, generated natively by Zod 4. Draft 7 is mandated by Requirement\n * 2.2 for the widest AI-prompt / OpenAPI tooling compatibility. The semantic\n * `.refine()` guards are not representable in JSON Schema and are\n * intentionally omitted — the export captures the *structural* contract only.\n * Since v0.3 the source schemas are loose, so these no longer emit\n * `additionalProperties: false` — the JSON Schema and `validateActivity` now\n * agree on unknown-key handling.\n */\n/**\n * JSON Schema (Draft 7) representation of the Gap Select activity data\n * contract. Structural contract only: the six semantic guards — the\n * passage/gap bijection, id uniqueness, the one-choice-source rule, and an\n * answer key that names a choice the gap offers — are Zod-only, as they are\n * for the other types.\n */\nexport const gapSelectJsonSchema: Record<string, unknown> = z.toJSONSchema(GapSelectDataSchema, {\n target: 'draft-7',\n});\n\n/**\n * JSON Schema (Draft 7) representation of the Dictation activity data\n * contract. Structural contract, plus the raw length caps JSON Schema can\n * state in code points as zod counts them — `maxLength` 2000 on a transcript\n * and an accepted transcript, 200 on a rule's `from` and `to`. The twelve\n * semantic guards — a transcript that survives normalisation, the caps after\n * equivalences are applied, distinct candidates, audio only, the\n * slow-recording rules, no captions, no transcript in the title — are\n * Zod-only, as they are for the other types.\n */\nexport const dictationJsonSchema: Record<string, unknown> = z.toJSONSchema(DictationDataSchema, {\n target: 'draft-7',\n});\n\n/**\n * JSON Schema (Draft 7) representation of the Read Aloud activity data\n * contract. Structural contract, plus the raw cap JSON Schema can state in code\n * points as zod counts them — `maxLength` 2000 on the reference text — and the\n * canonical locale pattern. The ten semantic guards — the cap after\n * normalisation, a text that survives it, the spaced-script rule, the\n * model-recording rules, unique dimensions, a weight above 0, and the take\n * bounds — are Zod-only, as they are for the other types.\n */\nexport const readAloudJsonSchema: Record<string, unknown> = z.toJSONSchema(ReadAloudDataSchema, {\n target: 'draft-7',\n});\n\nexport const multipleChoiceJsonSchema: Record<string, unknown> = z.toJSONSchema(\n MultipleChoiceDataSchema,\n {\n target: 'draft-7',\n },\n);\n\n/**\n * JSON Schema (Draft 7) representation of the Fill-in-the-Blanks activity data\n * contract, generated natively by Zod 4. Structural contract only (semantic\n * `.refine()` guards are Zod-only and not representable in JSON Schema).\n */\nexport const fillInTheBlanksJsonSchema: Record<string, unknown> = z.toJSONSchema(\n FillInTheBlanksDataSchema,\n {\n target: 'draft-7',\n },\n);\n\n/**\n * JSON Schema (Draft 7) representation of the Written Response activity data\n * contract. Structural contract only.\n */\nexport const writtenResponseJsonSchema: Record<string, unknown> = z.toJSONSchema(\n WrittenResponseDataSchema,\n {\n target: 'draft-7',\n },\n);\n\n/**\n * Derives the JSON Schema (Draft 7) for any REGISTERED activity type — the\n * live, registry-backed replacement for the static per-type exports above,\n * and the building block for AI generation pipelines (R6.1): pass the result\n * as a structured-output schema so a model can only emit valid items.\n *\n * For a type you registered, it is the descriptor's `jsonSchema` when you gave\n * one, or else what the schema produces through the Standard JSON Schema\n * converter (`'~standard'.jsonSchema`) — a zod 4.6 schema has one. A fresh copy\n * every call.\n *\n * @throws UnknownActivityTypeError when `type` has no registered descriptor.\n * @throws Error when a registered type has neither a `jsonSchema` nor a schema\n * that can produce one.\n */\nexport function jsonSchemaFor(type: string): Record<string, unknown> {\n const descriptor = getActivityTypeDescriptor(type);\n if (descriptor === undefined) {\n throw new UnknownActivityTypeError(type);\n }\n if (isOwnSchema(descriptor.schema)) {\n return z.toJSONSchema(descriptor.schema as never, { target: 'draft-7' }) as Record<\n string,\n unknown\n >;\n }\n if (descriptor.jsonSchema !== undefined) {\n return structuredClone(descriptor.jsonSchema) as Record<string, unknown>;\n }\n const generated = standardJsonSchemaOf(descriptor.schema);\n if (generated === undefined) {\n throw new Error(\n `Activity type \"${descriptor.type}\" has no JSON Schema: its schema implements no Standard JSON Schema converter ('~standard'.jsonSchema). Give its descriptor a \\`jsonSchema\\`.`,\n );\n }\n return generated;\n}\n","import { UnknownActivityTypeError } from '../errors.js';\nimport { getActivityTypeDescriptor } from '../registry/index.js';\nimport type {\n ActivityDataMap,\n ActivityMedia,\n ActivityType,\n MultipleChoiceOptionMedia,\n ValidationResult,\n} from '../types/activity.js';\nimport { MediaSchema } from './media.js';\nimport { MultipleChoiceOptionMediaSchema } from './multiple-choice.js';\nimport { readSchema, type SchemaReading } from './read-schema.js';\n\nexport type {\n RedactedActivity,\n RedactedBlankConfig,\n RedactedDictationData,\n RedactedDictationSlowMedia,\n RedactedFillInTheBlanksData,\n RedactedGapSelectBank,\n RedactedGapSelectChoice,\n RedactedGapSelectData,\n RedactedGapSelectGap,\n RedactedMultipleChoiceData,\n RedactedMultipleChoiceOption,\n RedactedMultipleChoiceOptionMedia,\n RedactedReadAloudData,\n RedactedStimulus,\n RedactedWrittenResponseData,\n} from '../types/redacted.js';\nexport { validateItemGroup } from './item-group.js';\nexport {\n dictationJsonSchema,\n fillInTheBlanksJsonSchema,\n gapSelectJsonSchema,\n itemGroupJsonSchema,\n jsonSchemaFor,\n multipleChoiceJsonSchema,\n readAloudJsonSchema,\n stimulusJsonSchema,\n writtenResponseJsonSchema,\n} from './json-schema.js';\n\n/**\n * Checks a piece of activity media — an item's `media`, a stimulus's, a\n * dictation's `slowMedia` — on its own, the way `validateActivity` checks it\n * inside an item: its kind, an address in the allowed schemes, a playback\n * policy only on audio, captions and tracks only where they can play. For an\n * editor's media picker, which holds the media before the item is whole.\n *\n * @returns `{ success: true, data }`, or `{ success: false, errors }` with the\n * same codes, paths and messages `validateActivity` reports.\n */\nexport function validateMedia(value: unknown): ValidationResult<ActivityMedia> {\n return asValidation(readSchema(MediaSchema as never, value, 'Media'));\n}\n\n/**\n * Checks a multiple-choice option's `media` on its own: a picture or a\n * recording, at an address in the allowed schemes, with no playback policy.\n *\n * @returns `{ success: true, data }`, or `{ success: false, errors }` with the\n * same codes, paths and messages `validateActivity` reports.\n */\nexport function validateOptionMedia(value: unknown): ValidationResult<MultipleChoiceOptionMedia> {\n return asValidation(readSchema(MultipleChoiceOptionMediaSchema as never, value, 'Option media'));\n}\n\nfunction asValidation<T>(reading: SchemaReading<unknown>): ValidationResult<T> {\n if (reading.success) {\n return { success: true, data: reading.data as T };\n }\n return {\n success: false,\n errors: reading.issues.map((issue) => ({\n path: issue.path.map(String),\n message: issue.message,\n code: issue.code,\n })),\n };\n}\n\n/**\n * Validates raw activity data against the schema registered for the given\n * activity type (built-in or consumer-registered via `registerActivityType`).\n *\n * Unknown keys are PRESERVED, not stripped: every built-in schema is loose,\n * so consumer sidecar fields and forward-version fields survive validation\n * verbatim in the returned `data`.\n *\n * @returns `{ success: true, data }` with the typed, validated data, or\n * `{ success: false, errors }` with one entry per failed constraint.\n * @throws UnknownActivityTypeError when `type` has no registered descriptor.\n */\nexport function validateActivity<T extends ActivityType>(\n type: T,\n data: unknown,\n): ValidationResult<ActivityDataMap[T]> {\n const descriptor = getActivityTypeDescriptor(type);\n if (descriptor === undefined) {\n throw new UnknownActivityTypeError(String(type));\n }\n\n return asValidation(readSchema(descriptor.schema, data, `Activity type \"${descriptor.type}\"`));\n}\n"],"mappings":"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","names":["z","z"]}
|
|
File without changes
|
|
File without changes
|