@intellectif/lk-core 0.21.0 → 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/CHANGELOG.md +31 -0
  2. package/README.md +6 -5
  3. package/dist/{activity-xhGV-Aeh.d.cts → activity-DgpBJeBc.d.cts} +137 -22
  4. package/dist/{activity-xhGV-Aeh.d.ts → activity-DgpBJeBc.d.ts} +137 -22
  5. package/dist/ai-check.cjs +104 -16
  6. package/dist/ai-check.cjs.map +1 -1
  7. package/dist/ai-check.d.cts +9 -5
  8. package/dist/ai-check.d.ts +9 -5
  9. package/dist/ai-check.js +103 -15
  10. package/dist/ai-check.js.map +1 -1
  11. package/dist/{chunk-2CV6NU32.cjs → chunk-2JT2WUQ2.cjs} +77 -39
  12. package/dist/chunk-2JT2WUQ2.cjs.map +1 -0
  13. package/dist/{chunk-D4TOPSHV.cjs → chunk-DSDXL3JO.cjs} +1216 -1105
  14. package/dist/chunk-DSDXL3JO.cjs.map +1 -0
  15. package/dist/{chunk-D3GP5MET.js → chunk-FBKTION6.js} +1093 -982
  16. package/dist/chunk-FBKTION6.js.map +1 -0
  17. package/dist/{chunk-Q7MV3IXJ.js → chunk-IARLJ5MW.js} +15 -16
  18. package/dist/chunk-IARLJ5MW.js.map +1 -0
  19. package/dist/{chunk-IHOEP4EB.js → chunk-RCZCP5OE.js} +311 -25
  20. package/dist/chunk-RCZCP5OE.js.map +1 -0
  21. package/dist/{chunk-X5DAXBJI.js → chunk-SJVRUPJT.js} +2 -2
  22. package/dist/{chunk-EOFWSGLU.cjs → chunk-TJJFKKH2.cjs} +4 -4
  23. package/dist/{chunk-EOFWSGLU.cjs.map → chunk-TJJFKKH2.cjs.map} +1 -1
  24. package/dist/{chunk-WQVZPIN7.cjs → chunk-VSH7ECQL.cjs} +44 -45
  25. package/dist/chunk-VSH7ECQL.cjs.map +1 -0
  26. package/dist/{chunk-NRTP7WCW.cjs → chunk-W5KB3DNT.cjs} +315 -29
  27. package/dist/chunk-W5KB3DNT.cjs.map +1 -0
  28. package/dist/{chunk-Z7QQZ53L.js → chunk-XS6U2ARZ.js} +70 -32
  29. package/dist/chunk-XS6U2ARZ.js.map +1 -0
  30. package/dist/index-BVNeSCWC.d.ts +548 -0
  31. package/dist/index-BlOLlwOi.d.cts +548 -0
  32. package/dist/index.cjs +129 -198
  33. package/dist/index.cjs.map +1 -1
  34. package/dist/index.d.cts +175 -18
  35. package/dist/index.d.ts +175 -18
  36. package/dist/index.js +34 -103
  37. package/dist/index.js.map +1 -1
  38. package/dist/schemas.cjs +3 -94
  39. package/dist/schemas.cjs.map +1 -1
  40. package/dist/schemas.d.cts +2 -3
  41. package/dist/schemas.d.ts +2 -3
  42. package/dist/schemas.js +6 -97
  43. package/dist/scoring.cjs +3 -3
  44. package/dist/scoring.d.cts +2 -2
  45. package/dist/scoring.d.ts +2 -2
  46. package/dist/scoring.js +2 -2
  47. package/dist/xapi.cjs +3 -3
  48. package/dist/xapi.d.cts +1 -1
  49. package/dist/xapi.d.ts +1 -1
  50. package/dist/xapi.js +2 -2
  51. package/package.json +4 -4
  52. package/vectors/README.md +32 -2
  53. package/vectors/scoring.json +1 -498
  54. package/vectors/validation.json +6742 -0
  55. package/vectors/validation.mjs +195 -0
  56. package/dist/chunk-2CV6NU32.cjs.map +0 -1
  57. package/dist/chunk-D3GP5MET.js.map +0 -1
  58. package/dist/chunk-D4TOPSHV.cjs.map +0 -1
  59. package/dist/chunk-IHOEP4EB.js.map +0 -1
  60. package/dist/chunk-NRTP7WCW.cjs.map +0 -1
  61. package/dist/chunk-Q7MV3IXJ.js.map +0 -1
  62. package/dist/chunk-WQVZPIN7.cjs.map +0 -1
  63. package/dist/chunk-Z7QQZ53L.js.map +0 -1
  64. package/dist/index-BuD8Hc8o.d.cts +0 -2303
  65. package/dist/index-DnJ_PI4d.d.ts +0 -2303
  66. /package/dist/{chunk-X5DAXBJI.js.map → chunk-SJVRUPJT.js.map} +0 -0
@@ -1 +1 @@
1
- {"version":3,"sources":["/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/chunk-EOFWSGLU.cjs","../src/xapi/validators.ts","../src/xapi/verbs.ts","../src/xapi/builder.ts"],"names":[],"mappings":"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ACF,EAAA;AAEA,EAAA;AACE,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AACL,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,EAAA;AACE,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AACL,IAAA;AACH,EAAA;AAEA,EAAA;AACE,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AACL,IAAA;AACH,EAAA;AACF;AAgBgB;AACR,EAAA;AACA,EAAA;AACF,EAAA;AACF,IAAA;AACF,EAAA;AACM,EAAA;AACC,EAAA;AACD,IAAA;AACA,IAAA;AAGA,IAAA;AACN,EAAA;AACF;AHLU;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/chunk-EOFWSGLU.cjs","sourcesContent":[null,"import { z } from 'zod/v4';\nimport { ActivitySchemaError } from '../errors.js';\nimport type { ValidationError } from '../types/activity.js';\nimport type { XAPIStatement } from '../types/xapi.js';\n\nconst UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n// Minimal IRI/URI check: a scheme followed by ':'.\nconst IRI = /^[a-z][a-z0-9+.-]*:/i;\n\nconst langMap = z.record(z.string(), z.string());\nconst extensions = z.record(z.string(), z.unknown());\n\nconst actorSchema = z\n .object({\n objectType: z.literal('Agent'),\n name: z.string().optional(),\n mbox: z\n .string()\n .regex(/^mailto:/, 'mbox must be a mailto IRI')\n .optional(),\n account: z.object({ homePage: z.string(), name: z.string() }).optional(),\n })\n .refine((actor) => actor.mbox !== undefined || actor.account !== undefined, {\n error: 'actor must be identified by an mbox or an account',\n });\n\nconst statementSchema = z.object({\n id: z.string().regex(UUID_V4, 'id must be a UUID v4'),\n actor: actorSchema,\n verb: z.object({\n id: z.string().regex(IRI, 'verb.id must be an IRI'),\n display: langMap,\n }),\n object: z.object({\n objectType: z.literal('Activity'),\n id: z.string().regex(IRI, 'object.id must be an IRI'),\n definition: z\n .object({\n name: langMap.optional(),\n description: langMap.optional(),\n type: z.string().optional(),\n interactionType: z.string().optional(),\n correctResponsesPattern: z.array(z.string()).optional(),\n choices: z.array(z.object({ id: z.string(), description: langMap.optional() })).optional(),\n extensions: extensions.optional(),\n })\n .optional(),\n }),\n result: z\n .object({\n // xAPI 1.0.3 permits scaled in [-1, 1]; the SDK only emits [0, 1].\n score: z\n .object({\n scaled: z.number().min(-1).max(1),\n raw: z.number().optional(),\n min: z.number().optional(),\n max: z.number().optional(),\n })\n .optional(),\n success: z.boolean().optional(),\n completion: z.boolean().optional(),\n duration: z.string().regex(/^P/, 'duration must be an ISO 8601 duration').optional(),\n response: z.string().optional(),\n extensions: extensions.optional(),\n })\n .optional(),\n context: z\n .object({\n platform: z.string().optional(),\n language: z.string().optional(),\n contextActivities: z\n .object({\n parent: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n grouping: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n category: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n other: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n })\n .optional(),\n extensions: extensions.optional(),\n })\n .optional(),\n timestamp: z\n .string()\n .refine((value) => !Number.isNaN(Date.parse(value)), 'timestamp must be ISO 8601'),\n version: z.literal('1.0.3'),\n});\n\n/**\n * The one global this module reads by name. Declared here, not globally: this\n * package compiles without Node's types on purpose, and nothing else in it may\n * come to rely on `process`.\n */\ndeclare const process: { env: { NODE_ENV?: string } };\n\n/**\n * Whether this is a production build.\n *\n * **The literal `process.env.NODE_ENV`, spelled exactly so.** It is the one\n * expression bundlers replace at build time, and a browser has no `process` to\n * read at run time. The reading this replaces,\n * `globalThis.process?.env?.NODE_ENV`, is not that expression, so no bundler\n * touched it, and in a browser it found no `process` and answered \"not\n * production\" in every production app — so a malformed statement threw there\n * instead of being logged and sent. Tests running in Node never saw it,\n * because Node has a `process`.\n *\n * This package's own build must leave the literal in its output, for the\n * consumer's bundler to replace. The `try` covers code that reaches a runtime\n * unbundled, with no `process` at all: that is not production, as it always\n * was.\n */\nfunction isProduction(): boolean {\n try {\n return process.env.NODE_ENV === 'production';\n } catch {\n return false;\n }\n}\n\n/**\n * Validates a constructed {@link XAPIStatement} against the xAPI 1.0.3\n * structural contract.\n *\n * In development a structural failure throws (caught early); in production it\n * logs a warning and returns (the statement is still sent — see the design's\n * Error Handling table). Uses a `zod/v4` schema rather than `ajv` + an\n * external JSON Schema to keep `lk-core` dependency-free.\n *\n * NOTE: `ActivitySchemaError` is reused here per the task spec; its\n * `activityType` field carries the sentinel `'xAPIStatement'`. A dedicated\n * `XAPIValidationError` would be semantically cleaner — flagged for review.\n */\nexport function validateXAPIStatement(statement: XAPIStatement): void {\n const result = statementSchema.safeParse(statement);\n if (result.success) {\n return;\n }\n\n const errors: ValidationError[] = result.error.issues.map((issue) => ({\n path: issue.path.map(String),\n message: issue.message,\n code: issue.code,\n }));\n\n if (isProduction()) {\n console.warn('[learning-kit] Invalid xAPI statement (sent anyway):', errors);\n return;\n }\n\n throw new ActivitySchemaError('xAPIStatement', errors);\n}\n","/**\n * The set of xAPI verbs emitted by SDK activities, keyed by a stable\n * identifier mapped to its canonical xAPI verb IRI (xAPI 1.0.3 / ADL registry).\n */\nexport const XAPIVerb = {\n ANSWERED: 'http://adlnet.gov/expapi/verbs/answered',\n COMPLETED: 'http://adlnet.gov/expapi/verbs/completed',\n EXPERIENCED: 'http://adlnet.gov/expapi/verbs/experienced',\n INTERACTED: 'http://adlnet.gov/expapi/verbs/interacted',\n ATTEMPTED: 'http://adlnet.gov/expapi/verbs/attempted',\n PASSED: 'http://adlnet.gov/expapi/verbs/passed',\n FAILED: 'http://adlnet.gov/expapi/verbs/failed',\n WATCHED: 'https://w3id.org/xapi/video/verbs/watched',\n /**\n * Emitted for deferred-grading submissions (e.g. written-response): the\n * learner has submitted work whose grade does not exist yet, so `answered`\n * (which implies a scored response) would be wrong. xAPI 1.0.3 defines no\n * canonical \"submit\" verb; the Activity Streams 1.0 IRI is the established\n * community choice (design decision recorded per Task 25.4).\n */\n SUBMITTED: 'http://activitystrea.ms/schema/1.0/submit',\n /**\n * Emitted when an asynchronous grader produces a grade for work that was\n * previously only SUBMITTED. Distinct from `answered`, which asserts the\n * grade existed at submission time — here the learner acted earlier and the\n * grade arrived later, often from a different actor (an AI or a teacher).\n */\n SCORED: 'http://adlnet.gov/expapi/verbs/scored',\n} as const;\n\n/** Union of the valid `XAPIVerb` keys. */\nexport type XAPIVerbKey = keyof typeof XAPIVerb;\n\n/**\n * Default `en-US` display label for each verb, used to populate\n * `XAPIVerbObject.display` when the builder resolves a verb key.\n */\nexport const XAPI_VERB_DISPLAY: Record<XAPIVerbKey, Record<string, string>> = {\n ANSWERED: { 'en-US': 'answered' },\n COMPLETED: { 'en-US': 'completed' },\n EXPERIENCED: { 'en-US': 'experienced' },\n INTERACTED: { 'en-US': 'interacted' },\n ATTEMPTED: { 'en-US': 'attempted' },\n PASSED: { 'en-US': 'passed' },\n FAILED: { 'en-US': 'failed' },\n WATCHED: { 'en-US': 'watched' },\n SUBMITTED: { 'en-US': 'submitted' },\n SCORED: { 'en-US': 'scored' },\n};\n","import { getActivityTypeDescriptor } from '../registry/index.js';\nimport type { ScoringResult } from '../types/activity.js';\nimport type {\n XAPIActor,\n XAPIContext,\n XAPIObject,\n XAPIResult,\n XAPIStatement,\n} from '../types/xapi.js';\nimport { validateXAPIStatement } from './validators.js';\nimport { XAPI_VERB_DISPLAY, XAPIVerb, type XAPIVerbKey } from './verbs.js';\n\n/** Caller-supplied activity object descriptor (mapped to an xAPI Activity). */\nexport interface XAPIObjectParams {\n /** Activity IRI. */\n id: string;\n name?: Record<string, string>;\n description?: Record<string, string>;\n /** Activity type IRI. */\n type?: string;\n /** xAPI cmi.interaction type (e.g. `choice`, `fill-in`, `long-fill-in`). */\n interactionType?: string;\n /** Correct-responses patterns, per the xAPI CRP format. */\n correctResponsesPattern?: string[];\n /** For choice-family interactions: the available components. */\n choices?: Array<{ id: string; description?: Record<string, string> }>;\n}\n\n/** Parameters for the generic {@link xAPIBuilder.buildStatement}. */\nexport interface XAPIStatementParams {\n actor: XAPIActor;\n verb: XAPIVerbKey;\n object: XAPIObjectParams;\n result?: XAPIResult;\n context?: XAPIContext;\n}\n\n/** Parameters for {@link xAPIBuilder.buildAnsweredStatement} (verb = ANSWERED). */\nexport interface AnsweredStatementParams {\n actor: XAPIActor;\n object: XAPIObjectParams;\n scoringResult: ScoringResult;\n timeSpentMs: number;\n /** Serialized learner response string. */\n response?: string;\n context?: XAPIContext;\n resultExtensions?: Record<string, unknown>;\n}\n\n/**\n * Parameters for {@link xAPIBuilder.buildSubmittedStatement} (verb =\n * SUBMITTED — deferred-grading submissions). Carries NO score, success, or\n * completion: the grade does not exist yet (Req 22.7).\n */\nexport interface SubmittedStatementParams {\n actor: XAPIActor;\n object: XAPIObjectParams;\n timeSpentMs: number;\n /** Serialized learner response string (e.g. the submitted text). */\n response?: string;\n context?: XAPIContext;\n resultExtensions?: Record<string, unknown>;\n}\n\n/** Parameters for {@link xAPIBuilder.buildCompletedStatement} (verb = COMPLETED). */\nexport interface CompletedStatementParams {\n actor: XAPIActor;\n object: XAPIObjectParams;\n scoringResult?: ScoringResult;\n timeSpentMs: number;\n context?: XAPIContext;\n resultExtensions?: Record<string, unknown>;\n}\n\n/**\n * Converts a millisecond duration to an ISO 8601 seconds string with\n * centisecond precision (`PT1.23S`), per the xAPI 1.0.3 recommendation of\n * 0.01-second accuracy. Sub-second durations are preserved (previously any\n * duration under 500 ms collapsed to `PT0S`). Negative inputs (clock skew)\n * clamp to zero — a negative ISO duration is invalid.\n */\nfunction msToIsoDuration(ms: number): string {\n return `PT${(Math.round(Math.max(0, ms) / 10) / 100).toFixed(2)}S`;\n}\n\n/**\n * UUID v4 that works outside secure contexts. `crypto.randomUUID` is\n * SecureContext-gated (undefined on plain-http LAN/staging origins), and a\n * statement is built at SUBMIT time — throwing here would lose the learner's\n * answer. `crypto.getRandomValues` is NOT gated, so the fallback still emits\n * a spec-valid v4 UUID (the statement validator enforces the v4 format).\n */\nfunction uuidv4(): string {\n const c = (\n globalThis as {\n crypto?: { randomUUID?: () => string; getRandomValues?: (a: Uint8Array) => Uint8Array };\n }\n ).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n const bytes = new Uint8Array(16);\n if (c?.getRandomValues) {\n c.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i += 1) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n bytes[6] = ((bytes[6] as number) & 0x0f) | 0x40;\n bytes[8] = ((bytes[8] as number) & 0x3f) | 0x80;\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\n/** Builds the xAPI Activity object, including `definition` only when populated. */\nfunction buildObject(params: XAPIObjectParams): XAPIObject {\n const definition: NonNullable<XAPIObject['definition']> = {\n ...(params.name !== undefined ? { name: params.name } : {}),\n ...(params.description !== undefined ? { description: params.description } : {}),\n ...(params.type !== undefined ? { type: params.type } : {}),\n ...(params.interactionType !== undefined ? { interactionType: params.interactionType } : {}),\n ...(params.correctResponsesPattern !== undefined\n ? { correctResponsesPattern: params.correctResponsesPattern }\n : {}),\n ...(params.choices !== undefined ? { choices: params.choices } : {}),\n };\n return {\n objectType: 'Activity',\n id: params.id,\n ...(Object.keys(definition).length > 0 ? { definition } : {}),\n };\n}\n\n/**\n * Maps a {@link ScoringResult} + timing to an {@link XAPIResult} per the\n * normative mapping in the design document.\n */\nfunction buildResult(\n timeSpentMs: number,\n scoringResult: ScoringResult | undefined,\n resultExtensions: Record<string, unknown> | undefined,\n response: string | undefined,\n): XAPIResult {\n return {\n completion: true,\n duration: msToIsoDuration(timeSpentMs),\n ...(scoringResult !== undefined\n ? {\n score: {\n scaled: scoringResult.score,\n raw: scoringResult.score,\n min: 0,\n max: scoringResult.maxScore,\n },\n success: scoringResult.passed,\n }\n : {}),\n ...(response !== undefined ? { response } : {}),\n ...(resultExtensions !== undefined ? { extensions: resultExtensions } : {}),\n };\n}\n\n/**\n * Constructs xAPI 1.0.3 Statements. Every call stamps a fresh UUID v4 `id`,\n * an ISO 8601 `timestamp`, and `version: '1.0.3'`. Not pure by design —\n * statements are unique events.\n */\nexport const xAPIBuilder = {\n buildStatement(params: XAPIStatementParams): XAPIStatement {\n const statement: XAPIStatement = {\n id: uuidv4(),\n actor: params.actor,\n verb: {\n id: XAPIVerb[params.verb],\n display: XAPI_VERB_DISPLAY[params.verb],\n },\n object: buildObject(params.object),\n ...(params.result !== undefined ? { result: params.result } : {}),\n ...(params.context !== undefined ? { context: params.context } : {}),\n timestamp: new Date().toISOString(),\n version: '1.0.3',\n };\n // Design xAPIBuilder step 4: validate every statement (throws in dev,\n // warns in prod). All build*Statement helpers route through here.\n validateXAPIStatement(statement);\n return statement;\n },\n\n buildAnsweredStatement(params: AnsweredStatementParams): XAPIStatement {\n return this.buildStatement({\n actor: params.actor,\n verb: 'ANSWERED',\n object: params.object,\n result: buildResult(\n params.timeSpentMs,\n params.scoringResult,\n params.resultExtensions,\n params.response,\n ),\n ...(params.context !== undefined ? { context: params.context } : {}),\n });\n },\n\n /**\n * Builds a statement for a deferred-grading submission (e.g. a written\n * response). Verb is SUBMITTED and the result deliberately omits `score`,\n * `success`, and `completion` — none of them exist until the asynchronous\n * grader runs; only `duration`, `response`, and extensions are recorded.\n */\n buildSubmittedStatement(params: SubmittedStatementParams): XAPIStatement {\n return this.buildStatement({\n actor: params.actor,\n verb: 'SUBMITTED',\n object: params.object,\n result: {\n duration: msToIsoDuration(params.timeSpentMs),\n ...(params.response !== undefined ? { response: params.response } : {}),\n ...(params.resultExtensions !== undefined ? { extensions: params.resultExtensions } : {}),\n },\n ...(params.context !== undefined ? { context: params.context } : {}),\n });\n },\n\n buildCompletedStatement(params: CompletedStatementParams): XAPIStatement {\n return this.buildStatement({\n actor: params.actor,\n verb: 'COMPLETED',\n object: params.object,\n result: buildResult(\n params.timeSpentMs,\n params.scoringResult,\n params.resultExtensions,\n undefined,\n ),\n ...(params.context !== undefined ? { context: params.context } : {}),\n });\n },\n};\n\n/**\n * Builds the xAPI `object.definition` interop fields for an activity from its\n * REGISTERED descriptor, rather than having every renderer hand-roll them.\n *\n * `ActivityTypeDescriptor.interop` declares the activity-type IRI, the\n * cmi.interaction type and how to derive `correctResponsesPattern`; before\n * this, those fields had no reader anywhere and each component rebuilt the\n * same strings inline — the same \"declared but never used\" defect the SDK\n * fixed elsewhere. Reading them here also means a consumer-registered type\n * gets correct interop for free.\n *\n * Returns an empty object for an unregistered type or one that declares no\n * interop, so it is always safe to spread.\n */\nexport function xapiDefinitionFor(data: { type: string }): Partial<XAPIObjectParams> {\n const descriptor = getActivityTypeDescriptor(data.type);\n const interop = descriptor?.interop;\n if (interop === undefined) {\n return {};\n }\n const pattern = interop.correctResponsesPattern?.(data);\n return {\n ...(interop.xapiActivityTypeIri !== undefined ? { type: interop.xapiActivityTypeIri } : {}),\n ...(interop.xapiInteractionType !== undefined\n ? { interactionType: interop.xapiInteractionType }\n : {}),\n ...(pattern !== undefined && pattern.length > 0 ? { correctResponsesPattern: pattern } : {}),\n };\n}\n"]}
1
+ {"version":3,"sources":["/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/chunk-TJJFKKH2.cjs","../src/xapi/validators.ts","../src/xapi/verbs.ts","../src/xapi/builder.ts"],"names":[],"mappings":"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ACF,EAAA;AAEA,EAAA;AACE,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AACL,IAAA;AACH,EAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAQA,EAAA;AACE,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AACL,IAAA;AACH,EAAA;AAEA,EAAA;AACE,IAAA;AACE,MAAA;AACA,MAAA;AACA,MAAA;AACA,MAAA;AACE,QAAA;AACA,QAAA;AACA,QAAA;AACA,QAAA;AACF,MAAA;AACI,MAAA;AACL,IAAA;AACH,EAAA;AACF;AAgBgB;AACR,EAAA;AACA,EAAA;AACF,EAAA;AACF,IAAA;AACF,EAAA;AACM,EAAA;AACC,EAAA;AACD,IAAA;AACA,IAAA;AAGA,IAAA;AACN,EAAA;AACF;AHLU;AACA;AACA;AACA;AACA;AACA;AACA;AACA","file":"/home/runner/work/learning-kit/learning-kit/packages/lk-core/dist/chunk-TJJFKKH2.cjs","sourcesContent":[null,"import { z } from 'zod/v4';\nimport { ActivitySchemaError } from '../errors.js';\nimport type { ValidationError } from '../types/activity.js';\nimport type { XAPIStatement } from '../types/xapi.js';\n\nconst UUID_V4 = /^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n// Minimal IRI/URI check: a scheme followed by ':'.\nconst IRI = /^[a-z][a-z0-9+.-]*:/i;\n\nconst langMap = z.record(z.string(), z.string());\nconst extensions = z.record(z.string(), z.unknown());\n\nconst actorSchema = z\n .object({\n objectType: z.literal('Agent'),\n name: z.string().optional(),\n mbox: z\n .string()\n .regex(/^mailto:/, 'mbox must be a mailto IRI')\n .optional(),\n account: z.object({ homePage: z.string(), name: z.string() }).optional(),\n })\n .refine((actor) => actor.mbox !== undefined || actor.account !== undefined, {\n error: 'actor must be identified by an mbox or an account',\n });\n\nconst statementSchema = z.object({\n id: z.string().regex(UUID_V4, 'id must be a UUID v4'),\n actor: actorSchema,\n verb: z.object({\n id: z.string().regex(IRI, 'verb.id must be an IRI'),\n display: langMap,\n }),\n object: z.object({\n objectType: z.literal('Activity'),\n id: z.string().regex(IRI, 'object.id must be an IRI'),\n definition: z\n .object({\n name: langMap.optional(),\n description: langMap.optional(),\n type: z.string().optional(),\n interactionType: z.string().optional(),\n correctResponsesPattern: z.array(z.string()).optional(),\n choices: z.array(z.object({ id: z.string(), description: langMap.optional() })).optional(),\n extensions: extensions.optional(),\n })\n .optional(),\n }),\n result: z\n .object({\n // xAPI 1.0.3 permits scaled in [-1, 1]; the SDK only emits [0, 1].\n score: z\n .object({\n scaled: z.number().min(-1).max(1),\n raw: z.number().optional(),\n min: z.number().optional(),\n max: z.number().optional(),\n })\n .optional(),\n success: z.boolean().optional(),\n completion: z.boolean().optional(),\n duration: z.string().regex(/^P/, 'duration must be an ISO 8601 duration').optional(),\n response: z.string().optional(),\n extensions: extensions.optional(),\n })\n .optional(),\n context: z\n .object({\n platform: z.string().optional(),\n language: z.string().optional(),\n contextActivities: z\n .object({\n parent: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n grouping: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n category: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n other: z\n .array(z.object({ objectType: z.literal('Activity'), id: z.string() }))\n .optional(),\n })\n .optional(),\n extensions: extensions.optional(),\n })\n .optional(),\n timestamp: z\n .string()\n .refine((value) => !Number.isNaN(Date.parse(value)), 'timestamp must be ISO 8601'),\n version: z.literal('1.0.3'),\n});\n\n/**\n * The one global this module reads by name. Declared here, not globally: this\n * package compiles without Node's types on purpose, and nothing else in it may\n * come to rely on `process`.\n */\ndeclare const process: { env: { NODE_ENV?: string } };\n\n/**\n * Whether this is a production build.\n *\n * **The literal `process.env.NODE_ENV`, spelled exactly so.** It is the one\n * expression bundlers replace at build time, and a browser has no `process` to\n * read at run time. The reading this replaces,\n * `globalThis.process?.env?.NODE_ENV`, is not that expression, so no bundler\n * touched it, and in a browser it found no `process` and answered \"not\n * production\" in every production app — so a malformed statement threw there\n * instead of being logged and sent. Tests running in Node never saw it,\n * because Node has a `process`.\n *\n * This package's own build must leave the literal in its output, for the\n * consumer's bundler to replace. The `try` covers code that reaches a runtime\n * unbundled, with no `process` at all: that is not production, as it always\n * was.\n */\nfunction isProduction(): boolean {\n try {\n return process.env.NODE_ENV === 'production';\n } catch {\n return false;\n }\n}\n\n/**\n * Validates a constructed {@link XAPIStatement} against the xAPI 1.0.3\n * structural contract.\n *\n * In development a structural failure throws (caught early); in production it\n * logs a warning and returns (the statement is still sent — see the design's\n * Error Handling table). Uses a `zod/v4` schema rather than `ajv` + an\n * external JSON Schema to keep `lk-core` dependency-free.\n *\n * NOTE: `ActivitySchemaError` is reused here per the task spec; its\n * `activityType` field carries the sentinel `'xAPIStatement'`. A dedicated\n * `XAPIValidationError` would be semantically cleaner — flagged for review.\n */\nexport function validateXAPIStatement(statement: XAPIStatement): void {\n const result = statementSchema.safeParse(statement);\n if (result.success) {\n return;\n }\n\n const errors: ValidationError[] = result.error.issues.map((issue) => ({\n path: issue.path.map(String),\n message: issue.message,\n code: issue.code,\n }));\n\n if (isProduction()) {\n console.warn('[learning-kit] Invalid xAPI statement (sent anyway):', errors);\n return;\n }\n\n throw new ActivitySchemaError('xAPIStatement', errors);\n}\n","/**\n * The set of xAPI verbs emitted by SDK activities, keyed by a stable\n * identifier mapped to its canonical xAPI verb IRI (xAPI 1.0.3 / ADL registry).\n */\nexport const XAPIVerb = {\n ANSWERED: 'http://adlnet.gov/expapi/verbs/answered',\n COMPLETED: 'http://adlnet.gov/expapi/verbs/completed',\n EXPERIENCED: 'http://adlnet.gov/expapi/verbs/experienced',\n INTERACTED: 'http://adlnet.gov/expapi/verbs/interacted',\n ATTEMPTED: 'http://adlnet.gov/expapi/verbs/attempted',\n PASSED: 'http://adlnet.gov/expapi/verbs/passed',\n FAILED: 'http://adlnet.gov/expapi/verbs/failed',\n WATCHED: 'https://w3id.org/xapi/video/verbs/watched',\n /**\n * Emitted for deferred-grading submissions (e.g. written-response): the\n * learner has submitted work whose grade does not exist yet, so `answered`\n * (which implies a scored response) would be wrong. xAPI 1.0.3 defines no\n * canonical \"submit\" verb; the Activity Streams 1.0 IRI is the established\n * community choice (design decision recorded per Task 25.4).\n */\n SUBMITTED: 'http://activitystrea.ms/schema/1.0/submit',\n /**\n * Emitted when an asynchronous grader produces a grade for work that was\n * previously only SUBMITTED. Distinct from `answered`, which asserts the\n * grade existed at submission time — here the learner acted earlier and the\n * grade arrived later, often from a different actor (an AI or a teacher).\n */\n SCORED: 'http://adlnet.gov/expapi/verbs/scored',\n} as const;\n\n/** Union of the valid `XAPIVerb` keys. */\nexport type XAPIVerbKey = keyof typeof XAPIVerb;\n\n/**\n * Default `en-US` display label for each verb, used to populate\n * `XAPIVerbObject.display` when the builder resolves a verb key.\n */\nexport const XAPI_VERB_DISPLAY: Record<XAPIVerbKey, Record<string, string>> = {\n ANSWERED: { 'en-US': 'answered' },\n COMPLETED: { 'en-US': 'completed' },\n EXPERIENCED: { 'en-US': 'experienced' },\n INTERACTED: { 'en-US': 'interacted' },\n ATTEMPTED: { 'en-US': 'attempted' },\n PASSED: { 'en-US': 'passed' },\n FAILED: { 'en-US': 'failed' },\n WATCHED: { 'en-US': 'watched' },\n SUBMITTED: { 'en-US': 'submitted' },\n SCORED: { 'en-US': 'scored' },\n};\n","import { getActivityTypeDescriptor } from '../registry/index.js';\nimport type { ScoringResult } from '../types/activity.js';\nimport type {\n XAPIActor,\n XAPIContext,\n XAPIObject,\n XAPIResult,\n XAPIStatement,\n} from '../types/xapi.js';\nimport { validateXAPIStatement } from './validators.js';\nimport { XAPI_VERB_DISPLAY, XAPIVerb, type XAPIVerbKey } from './verbs.js';\n\n/** Caller-supplied activity object descriptor (mapped to an xAPI Activity). */\nexport interface XAPIObjectParams {\n /** Activity IRI. */\n id: string;\n name?: Record<string, string>;\n description?: Record<string, string>;\n /** Activity type IRI. */\n type?: string;\n /** xAPI cmi.interaction type (e.g. `choice`, `fill-in`, `long-fill-in`). */\n interactionType?: string;\n /** Correct-responses patterns, per the xAPI CRP format. */\n correctResponsesPattern?: string[];\n /** For choice-family interactions: the available components. */\n choices?: Array<{ id: string; description?: Record<string, string> }>;\n}\n\n/** Parameters for the generic {@link xAPIBuilder.buildStatement}. */\nexport interface XAPIStatementParams {\n actor: XAPIActor;\n verb: XAPIVerbKey;\n object: XAPIObjectParams;\n result?: XAPIResult;\n context?: XAPIContext;\n}\n\n/** Parameters for {@link xAPIBuilder.buildAnsweredStatement} (verb = ANSWERED). */\nexport interface AnsweredStatementParams {\n actor: XAPIActor;\n object: XAPIObjectParams;\n scoringResult: ScoringResult;\n timeSpentMs: number;\n /** Serialized learner response string. */\n response?: string;\n context?: XAPIContext;\n resultExtensions?: Record<string, unknown>;\n}\n\n/**\n * Parameters for {@link xAPIBuilder.buildSubmittedStatement} (verb =\n * SUBMITTED — deferred-grading submissions). Carries NO score, success, or\n * completion: the grade does not exist yet (Req 22.7).\n */\nexport interface SubmittedStatementParams {\n actor: XAPIActor;\n object: XAPIObjectParams;\n timeSpentMs: number;\n /** Serialized learner response string (e.g. the submitted text). */\n response?: string;\n context?: XAPIContext;\n resultExtensions?: Record<string, unknown>;\n}\n\n/** Parameters for {@link xAPIBuilder.buildCompletedStatement} (verb = COMPLETED). */\nexport interface CompletedStatementParams {\n actor: XAPIActor;\n object: XAPIObjectParams;\n scoringResult?: ScoringResult;\n timeSpentMs: number;\n context?: XAPIContext;\n resultExtensions?: Record<string, unknown>;\n}\n\n/**\n * Converts a millisecond duration to an ISO 8601 seconds string with\n * centisecond precision (`PT1.23S`), per the xAPI 1.0.3 recommendation of\n * 0.01-second accuracy. Sub-second durations are preserved (previously any\n * duration under 500 ms collapsed to `PT0S`). Negative inputs (clock skew)\n * clamp to zero — a negative ISO duration is invalid.\n */\nfunction msToIsoDuration(ms: number): string {\n return `PT${(Math.round(Math.max(0, ms) / 10) / 100).toFixed(2)}S`;\n}\n\n/**\n * UUID v4 that works outside secure contexts. `crypto.randomUUID` is\n * SecureContext-gated (undefined on plain-http LAN/staging origins), and a\n * statement is built at SUBMIT time — throwing here would lose the learner's\n * answer. `crypto.getRandomValues` is NOT gated, so the fallback still emits\n * a spec-valid v4 UUID (the statement validator enforces the v4 format).\n */\nfunction uuidv4(): string {\n const c = (\n globalThis as {\n crypto?: { randomUUID?: () => string; getRandomValues?: (a: Uint8Array) => Uint8Array };\n }\n ).crypto;\n if (c?.randomUUID) {\n return c.randomUUID();\n }\n const bytes = new Uint8Array(16);\n if (c?.getRandomValues) {\n c.getRandomValues(bytes);\n } else {\n for (let i = 0; i < 16; i += 1) {\n bytes[i] = Math.floor(Math.random() * 256);\n }\n }\n bytes[6] = ((bytes[6] as number) & 0x0f) | 0x40;\n bytes[8] = ((bytes[8] as number) & 0x3f) | 0x80;\n const hex = [...bytes].map((b) => b.toString(16).padStart(2, '0')).join('');\n return `${hex.slice(0, 8)}-${hex.slice(8, 12)}-${hex.slice(12, 16)}-${hex.slice(16, 20)}-${hex.slice(20)}`;\n}\n\n/** Builds the xAPI Activity object, including `definition` only when populated. */\nfunction buildObject(params: XAPIObjectParams): XAPIObject {\n const definition: NonNullable<XAPIObject['definition']> = {\n ...(params.name !== undefined ? { name: params.name } : {}),\n ...(params.description !== undefined ? { description: params.description } : {}),\n ...(params.type !== undefined ? { type: params.type } : {}),\n ...(params.interactionType !== undefined ? { interactionType: params.interactionType } : {}),\n ...(params.correctResponsesPattern !== undefined\n ? { correctResponsesPattern: params.correctResponsesPattern }\n : {}),\n ...(params.choices !== undefined ? { choices: params.choices } : {}),\n };\n return {\n objectType: 'Activity',\n id: params.id,\n ...(Object.keys(definition).length > 0 ? { definition } : {}),\n };\n}\n\n/**\n * Maps a {@link ScoringResult} + timing to an {@link XAPIResult} per the\n * normative mapping in the design document.\n */\nfunction buildResult(\n timeSpentMs: number,\n scoringResult: ScoringResult | undefined,\n resultExtensions: Record<string, unknown> | undefined,\n response: string | undefined,\n): XAPIResult {\n return {\n completion: true,\n duration: msToIsoDuration(timeSpentMs),\n ...(scoringResult !== undefined\n ? {\n score: {\n scaled: scoringResult.score,\n raw: scoringResult.score,\n min: 0,\n max: scoringResult.maxScore,\n },\n success: scoringResult.passed,\n }\n : {}),\n ...(response !== undefined ? { response } : {}),\n ...(resultExtensions !== undefined ? { extensions: resultExtensions } : {}),\n };\n}\n\n/**\n * Constructs xAPI 1.0.3 Statements. Every call stamps a fresh UUID v4 `id`,\n * an ISO 8601 `timestamp`, and `version: '1.0.3'`. Not pure by design —\n * statements are unique events.\n */\nexport const xAPIBuilder = {\n buildStatement(params: XAPIStatementParams): XAPIStatement {\n const statement: XAPIStatement = {\n id: uuidv4(),\n actor: params.actor,\n verb: {\n id: XAPIVerb[params.verb],\n display: XAPI_VERB_DISPLAY[params.verb],\n },\n object: buildObject(params.object),\n ...(params.result !== undefined ? { result: params.result } : {}),\n ...(params.context !== undefined ? { context: params.context } : {}),\n timestamp: new Date().toISOString(),\n version: '1.0.3',\n };\n // Design xAPIBuilder step 4: validate every statement (throws in dev,\n // warns in prod). All build*Statement helpers route through here.\n validateXAPIStatement(statement);\n return statement;\n },\n\n buildAnsweredStatement(params: AnsweredStatementParams): XAPIStatement {\n return this.buildStatement({\n actor: params.actor,\n verb: 'ANSWERED',\n object: params.object,\n result: buildResult(\n params.timeSpentMs,\n params.scoringResult,\n params.resultExtensions,\n params.response,\n ),\n ...(params.context !== undefined ? { context: params.context } : {}),\n });\n },\n\n /**\n * Builds a statement for a deferred-grading submission (e.g. a written\n * response). Verb is SUBMITTED and the result deliberately omits `score`,\n * `success`, and `completion` — none of them exist until the asynchronous\n * grader runs; only `duration`, `response`, and extensions are recorded.\n */\n buildSubmittedStatement(params: SubmittedStatementParams): XAPIStatement {\n return this.buildStatement({\n actor: params.actor,\n verb: 'SUBMITTED',\n object: params.object,\n result: {\n duration: msToIsoDuration(params.timeSpentMs),\n ...(params.response !== undefined ? { response: params.response } : {}),\n ...(params.resultExtensions !== undefined ? { extensions: params.resultExtensions } : {}),\n },\n ...(params.context !== undefined ? { context: params.context } : {}),\n });\n },\n\n buildCompletedStatement(params: CompletedStatementParams): XAPIStatement {\n return this.buildStatement({\n actor: params.actor,\n verb: 'COMPLETED',\n object: params.object,\n result: buildResult(\n params.timeSpentMs,\n params.scoringResult,\n params.resultExtensions,\n undefined,\n ),\n ...(params.context !== undefined ? { context: params.context } : {}),\n });\n },\n};\n\n/**\n * Builds the xAPI `object.definition` interop fields for an activity from its\n * REGISTERED descriptor, rather than having every renderer hand-roll them.\n *\n * `ActivityTypeDescriptor.interop` declares the activity-type IRI, the\n * cmi.interaction type and how to derive `correctResponsesPattern`; before\n * this, those fields had no reader anywhere and each component rebuilt the\n * same strings inline — the same \"declared but never used\" defect the SDK\n * fixed elsewhere. Reading them here also means a consumer-registered type\n * gets correct interop for free.\n *\n * Returns an empty object for an unregistered type or one that declares no\n * interop, so it is always safe to spread.\n */\nexport function xapiDefinitionFor(data: { type: string }): Partial<XAPIObjectParams> {\n const descriptor = getActivityTypeDescriptor(data.type);\n const interop = descriptor?.interop;\n if (interop === undefined) {\n return {};\n }\n const pattern = interop.correctResponsesPattern?.(data);\n return {\n ...(interop.xapiActivityTypeIri !== undefined ? { type: interop.xapiActivityTypeIri } : {}),\n ...(interop.xapiInteractionType !== undefined\n ? { interactionType: interop.xapiInteractionType }\n : {}),\n ...(pattern !== undefined && pattern.length > 0 ? { correctResponsesPattern: pattern } : {}),\n };\n}\n"]}
@@ -14,7 +14,8 @@
14
14
 
15
15
 
16
16
 
17
- var _chunkD4TOPSHVcjs = require('./chunk-D4TOPSHV.cjs');
17
+
18
+ var _chunkDSDXL3JOcjs = require('./chunk-DSDXL3JO.cjs');
18
19
 
19
20
  // src/is-redacted.ts
20
21
  function isRedacted(data) {
@@ -450,12 +451,12 @@ function composeAssessmentScore(sections, policy) {
450
451
  function diffDictationChars(reference, attempt) {
451
452
  const referencePoints = Array.from(reference);
452
453
  const attemptPoints = Array.from(attempt);
453
- return _chunkD4TOPSHVcjs.alignSequences.call(void 0, referencePoints, attemptPoints).map(
454
+ return _chunkDSDXL3JOcjs.alignSequences.call(void 0, referencePoints, attemptPoints).map(
454
455
  ({ step, referenceIndex, attemptIndex }) => {
455
- if (step === _chunkD4TOPSHVcjs.STEP.missing) {
456
+ if (step === _chunkDSDXL3JOcjs.STEP.missing) {
456
457
  return { op: "missing", reference: referencePoints[referenceIndex], attempt: "" };
457
458
  }
458
- if (step === _chunkD4TOPSHVcjs.STEP.extra) {
459
+ if (step === _chunkDSDXL3JOcjs.STEP.extra) {
459
460
  return { op: "extra", reference: "", attempt: attemptPoints[attemptIndex] };
460
461
  }
461
462
  const referencePoint = referencePoints[referenceIndex];
@@ -477,14 +478,14 @@ function heardTokens(words) {
477
478
  const tokens = [];
478
479
  let length = 0;
479
480
  for (const [wordIndex, word] of words.entries()) {
480
- const normalized = _chunkD4TOPSHVcjs.normalizeDictationText.call(void 0, word.text);
481
+ const normalized = _chunkDSDXL3JOcjs.normalizeDictationText.call(void 0, word.text);
481
482
  if (normalized === "") {
482
483
  continue;
483
484
  }
484
485
  const inserted = word.error === "insertion";
485
486
  for (const text of normalized.split(" ")) {
486
- length += _chunkD4TOPSHVcjs.codePointLength.call(void 0, text) + (length === 0 ? 0 : 1);
487
- if (!inserted && length <= _chunkD4TOPSHVcjs.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH) {
487
+ length += _chunkDSDXL3JOcjs.codePointLength.call(void 0, text) + (length === 0 ? 0 : 1);
488
+ if (!inserted && length <= _chunkDSDXL3JOcjs.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH) {
488
489
  tokens.push({ text, wordIndex });
489
490
  }
490
491
  }
@@ -497,28 +498,28 @@ var Score = _v4.z.number().min(0).max(100);
497
498
  var Confidence = _v4.z.number().min(0).max(1);
498
499
  var Milliseconds = _v4.z.number().min(0);
499
500
  var PhonemeCandidateSchema = _v4.z.strictObject({
500
- symbol: _v4.z.string().min(1).max(16),
501
+ symbol: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string().min(1), 16),
501
502
  score: Score
502
503
  });
503
504
  var PhonemeSchema = _v4.z.strictObject({
504
- symbol: _v4.z.string().min(1).max(16).optional(),
505
+ symbol: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string().min(1), 16).optional(),
505
506
  accuracy: Score.optional(),
506
507
  startMs: Milliseconds.optional(),
507
508
  durationMs: Milliseconds.optional(),
508
509
  heardAs: _v4.z.array(PhonemeCandidateSchema).max(10).optional()
509
510
  });
510
511
  var SyllableSchema = _v4.z.strictObject({
511
- text: _v4.z.string().min(1).max(64),
512
- grapheme: _v4.z.string().max(64).optional(),
512
+ text: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string().min(1), 64),
513
+ grapheme: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string(), 64).optional(),
513
514
  accuracy: Score.optional(),
514
515
  startMs: Milliseconds.optional(),
515
516
  durationMs: Milliseconds.optional()
516
517
  });
517
518
  var WordSchema = _v4.z.strictObject({
518
- text: _v4.z.string().min(1).max(200),
519
+ text: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string().min(1), 200),
519
520
  accuracy: Score.optional(),
520
521
  error: _v4.z.enum(["none", "mispronunciation", "omission", "insertion"]),
521
- vendorError: _v4.z.string().max(64).optional(),
522
+ vendorError: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string(), 64).optional(),
522
523
  startMs: Milliseconds.optional(),
523
524
  durationMs: Milliseconds.optional(),
524
525
  syllables: _v4.z.array(SyllableSchema).max(50).optional(),
@@ -527,17 +528,17 @@ var WordSchema = _v4.z.strictObject({
527
528
  });
528
529
  var AssessorSchema = _v4.z.strictObject({
529
530
  kind: _v4.z.enum(["auto", "ai", "human"]),
530
- id: _v4.z.string().max(256).optional(),
531
- model: _v4.z.string().max(256).optional(),
532
- promptHash: _v4.z.string().max(256).optional()
531
+ id: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string(), 256).optional(),
532
+ model: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string(), 256).optional(),
533
+ promptHash: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string(), 256).optional()
533
534
  });
534
535
  var SpeechAssessmentSchema = _v4.z.strictObject({
535
536
  assessmentVersion: _v4.z.literal("1.0"),
536
537
  status: _v4.z.enum(["assessed", "no_speech"]),
537
538
  task: _v4.z.enum(["scripted", "unscripted"]),
538
- locale: _v4.z.string().regex(_chunkD4TOPSHVcjs.CANONICAL_LOCALE_RE),
539
- referenceText: _v4.z.string().max(8e3).optional(),
540
- recordingKey: _v4.z.string().min(1).max(1024).optional(),
539
+ locale: _v4.z.string().regex(_chunkDSDXL3JOcjs.CANONICAL_LOCALE_RE),
540
+ referenceText: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string(), 8e3).optional(),
541
+ recordingKey: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string().min(1), 1024).optional(),
541
542
  assessor: AssessorSchema,
542
543
  scale: _v4.z.literal(100),
543
544
  scores: _v4.z.strictObject({
@@ -547,10 +548,10 @@ var SpeechAssessmentSchema = _v4.z.strictObject({
547
548
  prosody: Score.optional(),
548
549
  overall: Score.optional()
549
550
  }),
550
- recognizedText: _v4.z.string().max(8e3).optional(),
551
+ recognizedText: _chunkDSDXL3JOcjs.maxUnits.call(void 0, _v4.z.string(), 8e3).optional(),
551
552
  miscue: _v4.z.enum(["assessor", "none"]),
552
553
  phonemeAlphabet: _v4.z.enum(["ipa", "sapi"]).optional(),
553
- words: _v4.z.array(WordSchema).max(_chunkD4TOPSHVcjs.SPEECH_ASSESSMENT_MAX_WORDS),
554
+ words: _v4.z.array(WordSchema).max(_chunkDSDXL3JOcjs.SPEECH_ASSESSMENT_MAX_WORDS),
554
555
  prosody: _v4.z.strictObject({ monotoneConfidence: Confidence.optional() }).optional(),
555
556
  signal: _v4.z.strictObject({ snrDb: _v4.z.number().optional() }).optional()
556
557
  });
@@ -572,21 +573,21 @@ function rawTextLength(words) {
572
573
  }
573
574
  function totalTextErrors(words) {
574
575
  const raw = rawTextLength(words);
575
- if (raw > _chunkD4TOPSHVcjs.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH) {
576
+ if (raw > _chunkDSDXL3JOcjs.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH) {
576
577
  return [
577
578
  {
578
579
  path: ["words"],
579
- message: `The words of an assessment carry ${raw} characters between them, and at most ${_chunkD4TOPSHVcjs.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH} can be aligned against the text of an item.`,
580
+ message: `The words of an assessment carry ${raw} characters between them, and at most ${_chunkDSDXL3JOcjs.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH} can be aligned against the text of an item.`,
580
581
  code: "too_big"
581
582
  }
582
583
  ];
583
584
  }
584
585
  const normalized = heardTokens(words).length;
585
- if (normalized > _chunkD4TOPSHVcjs.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH) {
586
+ if (normalized > _chunkDSDXL3JOcjs.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH) {
586
587
  return [
587
588
  {
588
589
  path: ["words"],
589
- message: `The words of an assessment spell ${normalized} characters between them once they are normalised, and at most ${_chunkD4TOPSHVcjs.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH} can be aligned against the text of an item. One character can stand for several.`,
590
+ message: `The words of an assessment spell ${normalized} characters between them once they are normalised, and at most ${_chunkDSDXL3JOcjs.SPEECH_ASSESSMENT_MAX_TEXT_LENGTH} can be aligned against the text of an item. One character can stand for several.`,
590
591
  code: "too_big"
591
592
  }
592
593
  ];
@@ -656,16 +657,16 @@ function alignReadAloud(data, assessment) {
656
657
  return alignValidated(data, checked.data);
657
658
  }
658
659
  function alignValidated(data, assessment) {
659
- const reference = _chunkD4TOPSHVcjs.dictationReferenceWords.call(void 0, {
660
+ const reference = _chunkDSDXL3JOcjs.dictationReferenceWords.call(void 0, {
660
661
  transcript: data.referenceText
661
662
  })[0];
662
663
  const heard = heardTokens(assessment.words).tokens;
663
664
  const entries = [];
664
- for (const { step, referenceIndex, attemptIndex } of _chunkD4TOPSHVcjs.alignSequences.call(void 0,
665
+ for (const { step, referenceIndex, attemptIndex } of _chunkDSDXL3JOcjs.alignSequences.call(void 0,
665
666
  reference.map((word) => word.word),
666
667
  heard.map((token) => token.text)
667
668
  )) {
668
- if (step === _chunkD4TOPSHVcjs.STEP.extra) {
669
+ if (step === _chunkDSDXL3JOcjs.STEP.extra) {
669
670
  const token2 = heard[attemptIndex];
670
671
  entries.push({
671
672
  reference: "",
@@ -677,7 +678,7 @@ function alignValidated(data, assessment) {
677
678
  continue;
678
679
  }
679
680
  const referenceWord = reference[referenceIndex];
680
- if (step === _chunkD4TOPSHVcjs.STEP.missing) {
681
+ if (step === _chunkDSDXL3JOcjs.STEP.missing) {
681
682
  entries.push({
682
683
  itemId: referenceWord.itemId,
683
684
  reference: referenceWord.word,
@@ -730,7 +731,7 @@ function placeInsertions(assessment, entries) {
730
731
  reference: "",
731
732
  // Every insertion is accounted for, including one whose text normalises
732
733
  // to nothing: a reader of `wordIndex` must find each word it looks for.
733
- heard: _chunkD4TOPSHVcjs.normalizeDictationText.call(void 0, word.text),
734
+ heard: _chunkDSDXL3JOcjs.normalizeDictationText.call(void 0, word.text),
734
735
  state: "inserted",
735
736
  ...accuracyOf(word),
736
737
  wordIndex
@@ -767,9 +768,9 @@ function readResponseRecording(value) {
767
768
  function spokenWordCount(assessment) {
768
769
  const recognized = assessment.recognizedText;
769
770
  if (recognized !== void 0 && recognized.trim() !== "") {
770
- return _chunkD4TOPSHVcjs.countWords.call(void 0, recognized);
771
+ return _chunkDSDXL3JOcjs.countWords.call(void 0, recognized);
771
772
  }
772
- return _chunkD4TOPSHVcjs.countWords.call(void 0,
773
+ return _chunkDSDXL3JOcjs.countWords.call(void 0,
773
774
  assessment.words.filter((word) => word.error !== "omission" && word.error !== "insertion").map((word) => word.text).join(" ")
774
775
  );
775
776
  }
@@ -793,9 +794,9 @@ function gradeReadAloud(data, response, assessment, options) {
793
794
  );
794
795
  }
795
796
  const rounding = roundingPolicyOf(_optionalChain([options, 'optionalAccess', _6 => _6.rounding]));
796
- const parsed = _chunkD4TOPSHVcjs.ReadAloudDataSchema.safeParse(data);
797
+ const parsed = _chunkDSDXL3JOcjs.ReadAloudDataSchema.safeParse(data);
797
798
  if (!parsed.success) {
798
- throw new (0, _chunkD4TOPSHVcjs.ActivitySchemaError)(
799
+ throw new (0, _chunkDSDXL3JOcjs.ActivitySchemaError)(
799
800
  "read-aloud",
800
801
  parsed.error.issues.map((issue) => ({
801
802
  path: issue.path.map(String),
@@ -805,7 +806,7 @@ function gradeReadAloud(data, response, assessment, options) {
805
806
  );
806
807
  }
807
808
  if (isRedacted(data) || isRedacted(parsed.data)) {
808
- throw new (0, _chunkD4TOPSHVcjs.RedactedScoringError)("read-aloud");
809
+ throw new (0, _chunkDSDXL3JOcjs.RedactedScoringError)("read-aloud");
809
810
  }
810
811
  const item = parsed.data;
811
812
  const checkedResponse = readResponseRecording(response);
@@ -827,7 +828,6 @@ function gradeReadAloud(data, response, assessment, options) {
827
828
  // there is no assessment to read, and no grader to credit.
828
829
  details: referenceWordsOf(item).map(({ itemId, word }) => ({
829
830
  itemId,
830
- correct: false,
831
831
  outcome: "incorrect-omission",
832
832
  learnerResponse: "",
833
833
  correctResponse: word,
@@ -940,7 +940,6 @@ function gradeReadAloud(data, response, assessment, options) {
940
940
  }
941
941
  details.push({
942
942
  itemId: entry.itemId,
943
- correct: entry.state === "correct",
944
943
  outcome: entry.state === "correct" ? "correct" : entry.state === "mispronounced" ? "incorrect" : "incorrect-omission",
945
944
  learnerResponse: entry.heard,
946
945
  correctResponse: entry.reference,
@@ -958,7 +957,7 @@ function gradeReadAloud(data, response, assessment, options) {
958
957
  };
959
958
  }
960
959
  function referenceWordsOf(data) {
961
- return _chunkD4TOPSHVcjs.dictationReferenceWords.call(void 0, { transcript: data.referenceText })[0];
960
+ return _chunkDSDXL3JOcjs.dictationReferenceWords.call(void 0, { transcript: data.referenceText })[0];
962
961
  }
963
962
 
964
963
  // src/scoring/speech/wav.ts
@@ -1100,19 +1099,19 @@ function outcomeFromUnscorable(result) {
1100
1099
  // src/scoring/index.ts
1101
1100
  function score(activityType, activityData, learnerResponse, options) {
1102
1101
  const rounding = roundingPolicyOf(_optionalChain([options, 'optionalAccess', _9 => _9.rounding]));
1103
- const descriptor = _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, activityType);
1102
+ const descriptor = _chunkDSDXL3JOcjs.getActivityTypeDescriptor.call(void 0, activityType);
1104
1103
  if (descriptor === void 0) {
1105
- throw new (0, _chunkD4TOPSHVcjs.UnknownActivityTypeError)(String(activityType));
1104
+ throw new (0, _chunkDSDXL3JOcjs.UnknownActivityTypeError)(String(activityType));
1106
1105
  }
1107
1106
  if (descriptor.scoring.kind === "deferred") {
1108
- throw new (0, _chunkD4TOPSHVcjs.DeferredScoringError)(descriptor.type);
1107
+ throw new (0, _chunkDSDXL3JOcjs.DeferredScoringError)(descriptor.type);
1109
1108
  }
1110
1109
  if (isRedacted(activityData)) {
1111
- throw new (0, _chunkD4TOPSHVcjs.RedactedScoringError)(descriptor.type);
1110
+ throw new (0, _chunkDSDXL3JOcjs.RedactedScoringError)(descriptor.type);
1112
1111
  }
1113
1112
  const result = descriptor.scoring.score(activityData, learnerResponse);
1114
1113
  if (!Number.isFinite(result.score)) {
1115
- throw new (0, _chunkD4TOPSHVcjs.RedactedScoringError)(descriptor.type);
1114
+ throw new (0, _chunkDSDXL3JOcjs.RedactedScoringError)(descriptor.type);
1116
1115
  }
1117
1116
  const passed = computePassThreshold(activityData, result.score, rounding);
1118
1117
  return { ...result, passed, feedback: _nullishCoalesce(result.feedback, () => ( selectFeedback(activityData, passed))) };
@@ -1129,7 +1128,7 @@ function evaluate(data, response, options) {
1129
1128
  }
1130
1129
  function evaluateAnswer(data, response, rounding) {
1131
1130
  const type = data.type;
1132
- const descriptor = typeof type === "string" ? _chunkD4TOPSHVcjs.getActivityTypeDescriptor.call(void 0, type) : void 0;
1131
+ const descriptor = typeof type === "string" ? _chunkDSDXL3JOcjs.getActivityTypeDescriptor.call(void 0, type) : void 0;
1133
1132
  if (descriptor === void 0) {
1134
1133
  return {
1135
1134
  status: "unscorable",
@@ -1254,4 +1253,4 @@ function costed(data, opening, graded, rules, rounding) {
1254
1253
 
1255
1254
 
1256
1255
  exports.isGradeInRange = isGradeInRange; exports.DEFAULT_ITEM_SCORING_POLICY = DEFAULT_ITEM_SCORING_POLICY; exports.ITEM_SCORING_MAX_RETRIES = ITEM_SCORING_MAX_RETRIES; exports.validateItemScoringPolicy = validateItemScoringPolicy; exports.resolveItemScoringPolicy = resolveItemScoringPolicy; exports.scoreTries = scoreTries; exports.roundGrade = roundGrade; exports.gte = gte; exports.classifyBand = classifyBand; exports.DEFAULT_PASS_THRESHOLD = DEFAULT_PASS_THRESHOLD; exports.computePassThreshold = computePassThreshold; exports.gradeFromRubric = gradeFromRubric; exports.outcomeFromGrade = outcomeFromGrade; exports.hasGrade = hasGrade; exports.composeAssessmentScore = composeAssessmentScore; exports.diffDictationChars = diffDictationChars; exports.validateSpeechAssessment = validateSpeechAssessment; exports.alignReadAloud = alignReadAloud; exports.gradeReadAloud = gradeReadAloud; exports.inspectWav = inspectWav; exports.outcomeFromUnscorable = outcomeFromUnscorable; exports.score = score; exports.evaluate = evaluate; exports.evaluateTries = evaluateTries;
1257
- //# sourceMappingURL=chunk-WQVZPIN7.cjs.map
1256
+ //# sourceMappingURL=chunk-VSH7ECQL.cjs.map