@intellectif/lk-core 0.2.1 → 0.3.1

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 (59) hide show
  1. package/dist/activity-zdcAMtFB.d.cts +626 -0
  2. package/dist/activity-zdcAMtFB.d.ts +626 -0
  3. package/dist/chunk-3YAVDV5F.js +47 -0
  4. package/dist/chunk-3YAVDV5F.js.map +1 -0
  5. package/dist/chunk-55O4M45K.js +57 -0
  6. package/dist/chunk-55O4M45K.js.map +1 -0
  7. package/dist/chunk-5GJJHGY5.js +576 -0
  8. package/dist/chunk-5GJJHGY5.js.map +1 -0
  9. package/dist/{chunk-ZHOX6TO4.js → chunk-HS7BYCGE.js} +65 -7
  10. package/dist/chunk-HS7BYCGE.js.map +1 -0
  11. package/dist/chunk-PIMX4B4D.cjs +47 -0
  12. package/dist/chunk-PIMX4B4D.cjs.map +1 -0
  13. package/dist/chunk-QOAORTA4.cjs +576 -0
  14. package/dist/chunk-QOAORTA4.cjs.map +1 -0
  15. package/dist/chunk-QSVBYTNM.js +94 -0
  16. package/dist/chunk-QSVBYTNM.js.map +1 -0
  17. package/dist/{chunk-PJFDAP54.cjs → chunk-RUGIOQZY.cjs} +66 -8
  18. package/dist/chunk-RUGIOQZY.cjs.map +1 -0
  19. package/dist/chunk-THSZMZND.cjs +94 -0
  20. package/dist/chunk-THSZMZND.cjs.map +1 -0
  21. package/dist/chunk-YNTYWHZI.cjs +57 -0
  22. package/dist/chunk-YNTYWHZI.cjs.map +1 -0
  23. package/dist/index.cjs +185 -6
  24. package/dist/index.cjs.map +1 -1
  25. package/dist/index.d.cts +253 -7
  26. package/dist/index.d.ts +253 -7
  27. package/dist/index.js +188 -9
  28. package/dist/index.js.map +1 -1
  29. package/dist/schemas.cjs +29 -2
  30. package/dist/schemas.cjs.map +1 -1
  31. package/dist/schemas.d.cts +310 -29
  32. package/dist/schemas.d.ts +310 -29
  33. package/dist/schemas.js +32 -5
  34. package/dist/scoring.cjs +13 -3
  35. package/dist/scoring.cjs.map +1 -1
  36. package/dist/scoring.d.cts +29 -5
  37. package/dist/scoring.d.ts +29 -5
  38. package/dist/scoring.js +12 -2
  39. package/dist/xapi.cjs +3 -3
  40. package/dist/xapi.d.cts +40 -2
  41. package/dist/xapi.d.ts +40 -2
  42. package/dist/xapi.js +2 -2
  43. package/package.json +7 -2
  44. package/dist/activity-D5tqgx8A.d.cts +0 -330
  45. package/dist/activity-D5tqgx8A.d.ts +0 -330
  46. package/dist/chunk-2T3IL7VL.js +0 -147
  47. package/dist/chunk-2T3IL7VL.js.map +0 -1
  48. package/dist/chunk-3JMLUUFS.cjs +0 -124
  49. package/dist/chunk-3JMLUUFS.cjs.map +0 -1
  50. package/dist/chunk-6VOCV4EX.js +0 -25
  51. package/dist/chunk-6VOCV4EX.js.map +0 -1
  52. package/dist/chunk-DCDOTQNH.cjs +0 -147
  53. package/dist/chunk-DCDOTQNH.cjs.map +0 -1
  54. package/dist/chunk-DV466SBJ.cjs +0 -25
  55. package/dist/chunk-DV466SBJ.cjs.map +0 -1
  56. package/dist/chunk-GZ73G2TS.js +0 -124
  57. package/dist/chunk-GZ73G2TS.js.map +0 -1
  58. package/dist/chunk-PJFDAP54.cjs.map +0 -1
  59. package/dist/chunk-ZHOX6TO4.js.map +0 -1
package/dist/xapi.cjs CHANGED
@@ -3,12 +3,12 @@
3
3
 
4
4
 
5
5
 
6
- var _chunkPJFDAP54cjs = require('./chunk-PJFDAP54.cjs');
7
- require('./chunk-DV466SBJ.cjs');
6
+ var _chunkRUGIOQZYcjs = require('./chunk-RUGIOQZY.cjs');
7
+ require('./chunk-PIMX4B4D.cjs');
8
8
 
9
9
 
10
10
 
11
11
 
12
12
 
13
- exports.XAPIVerb = _chunkPJFDAP54cjs.XAPIVerb; exports.XAPI_VERB_DISPLAY = _chunkPJFDAP54cjs.XAPI_VERB_DISPLAY; exports.validateXAPIStatement = _chunkPJFDAP54cjs.validateXAPIStatement; exports.xAPIBuilder = _chunkPJFDAP54cjs.xAPIBuilder;
13
+ exports.XAPIVerb = _chunkRUGIOQZYcjs.XAPIVerb; exports.XAPI_VERB_DISPLAY = _chunkRUGIOQZYcjs.XAPI_VERB_DISPLAY; exports.validateXAPIStatement = _chunkRUGIOQZYcjs.validateXAPIStatement; exports.xAPIBuilder = _chunkRUGIOQZYcjs.xAPIBuilder;
14
14
  //# sourceMappingURL=xapi.cjs.map
package/dist/xapi.d.cts CHANGED
@@ -1,4 +1,4 @@
1
- import { X as XAPIActor, i as ScoringResult, l as XAPIContext, o as XAPIResult, q as XAPIStatement } from './activity-D5tqgx8A.cjs';
1
+ import { X as XAPIActor, m as ScoringResult, t as XAPIContext, x as XAPIResult, z as XAPIStatement } from './activity-zdcAMtFB.cjs';
2
2
 
3
3
  /**
4
4
  * The set of xAPI verbs emitted by SDK activities, keyed by a stable
@@ -13,6 +13,14 @@ declare const XAPIVerb: {
13
13
  readonly PASSED: "http://adlnet.gov/expapi/verbs/passed";
14
14
  readonly FAILED: "http://adlnet.gov/expapi/verbs/failed";
15
15
  readonly WATCHED: "https://w3id.org/xapi/video/verbs/watched";
16
+ /**
17
+ * Emitted for deferred-grading submissions (e.g. written-response): the
18
+ * learner has submitted work whose grade does not exist yet, so `answered`
19
+ * (which implies a scored response) would be wrong. xAPI 1.0.3 defines no
20
+ * canonical "submit" verb; the Activity Streams 1.0 IRI is the established
21
+ * community choice (design decision recorded per Task 25.4).
22
+ */
23
+ readonly SUBMITTED: "http://activitystrea.ms/schema/1.0/submit";
16
24
  };
17
25
  /** Union of the valid `XAPIVerb` keys. */
18
26
  type XAPIVerbKey = keyof typeof XAPIVerb;
@@ -30,6 +38,15 @@ interface XAPIObjectParams {
30
38
  description?: Record<string, string>;
31
39
  /** Activity type IRI. */
32
40
  type?: string;
41
+ /** xAPI cmi.interaction type (e.g. `choice`, `fill-in`, `long-fill-in`). */
42
+ interactionType?: string;
43
+ /** Correct-responses patterns, per the xAPI CRP format. */
44
+ correctResponsesPattern?: string[];
45
+ /** For choice-family interactions: the available components. */
46
+ choices?: Array<{
47
+ id: string;
48
+ description?: Record<string, string>;
49
+ }>;
33
50
  }
34
51
  /** Parameters for the generic {@link xAPIBuilder.buildStatement}. */
35
52
  interface XAPIStatementParams {
@@ -50,6 +67,20 @@ interface AnsweredStatementParams {
50
67
  context?: XAPIContext;
51
68
  resultExtensions?: Record<string, unknown>;
52
69
  }
70
+ /**
71
+ * Parameters for {@link xAPIBuilder.buildSubmittedStatement} (verb =
72
+ * SUBMITTED — deferred-grading submissions). Carries NO score, success, or
73
+ * completion: the grade does not exist yet (Req 22.7).
74
+ */
75
+ interface SubmittedStatementParams {
76
+ actor: XAPIActor;
77
+ object: XAPIObjectParams;
78
+ timeSpentMs: number;
79
+ /** Serialized learner response string (e.g. the submitted text). */
80
+ response?: string;
81
+ context?: XAPIContext;
82
+ resultExtensions?: Record<string, unknown>;
83
+ }
53
84
  /** Parameters for {@link xAPIBuilder.buildCompletedStatement} (verb = COMPLETED). */
54
85
  interface CompletedStatementParams {
55
86
  actor: XAPIActor;
@@ -67,6 +98,13 @@ interface CompletedStatementParams {
67
98
  declare const xAPIBuilder: {
68
99
  buildStatement(params: XAPIStatementParams): XAPIStatement;
69
100
  buildAnsweredStatement(params: AnsweredStatementParams): XAPIStatement;
101
+ /**
102
+ * Builds a statement for a deferred-grading submission (e.g. a written
103
+ * response). Verb is SUBMITTED and the result deliberately omits `score`,
104
+ * `success`, and `completion` — none of them exist until the asynchronous
105
+ * grader runs; only `duration`, `response`, and extensions are recorded.
106
+ */
107
+ buildSubmittedStatement(params: SubmittedStatementParams): XAPIStatement;
70
108
  buildCompletedStatement(params: CompletedStatementParams): XAPIStatement;
71
109
  };
72
110
 
@@ -85,4 +123,4 @@ declare const xAPIBuilder: {
85
123
  */
86
124
  declare function validateXAPIStatement(statement: XAPIStatement): void;
87
125
 
88
- export { type AnsweredStatementParams, type CompletedStatementParams, type XAPIObjectParams, type XAPIStatementParams, XAPIVerb, type XAPIVerbKey, XAPI_VERB_DISPLAY, validateXAPIStatement, xAPIBuilder };
126
+ export { type AnsweredStatementParams, type CompletedStatementParams, type SubmittedStatementParams, type XAPIObjectParams, type XAPIStatementParams, XAPIVerb, type XAPIVerbKey, XAPI_VERB_DISPLAY, validateXAPIStatement, xAPIBuilder };
package/dist/xapi.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { X as XAPIActor, i as ScoringResult, l as XAPIContext, o as XAPIResult, q as XAPIStatement } from './activity-D5tqgx8A.js';
1
+ import { X as XAPIActor, m as ScoringResult, t as XAPIContext, x as XAPIResult, z as XAPIStatement } from './activity-zdcAMtFB.js';
2
2
 
3
3
  /**
4
4
  * The set of xAPI verbs emitted by SDK activities, keyed by a stable
@@ -13,6 +13,14 @@ declare const XAPIVerb: {
13
13
  readonly PASSED: "http://adlnet.gov/expapi/verbs/passed";
14
14
  readonly FAILED: "http://adlnet.gov/expapi/verbs/failed";
15
15
  readonly WATCHED: "https://w3id.org/xapi/video/verbs/watched";
16
+ /**
17
+ * Emitted for deferred-grading submissions (e.g. written-response): the
18
+ * learner has submitted work whose grade does not exist yet, so `answered`
19
+ * (which implies a scored response) would be wrong. xAPI 1.0.3 defines no
20
+ * canonical "submit" verb; the Activity Streams 1.0 IRI is the established
21
+ * community choice (design decision recorded per Task 25.4).
22
+ */
23
+ readonly SUBMITTED: "http://activitystrea.ms/schema/1.0/submit";
16
24
  };
17
25
  /** Union of the valid `XAPIVerb` keys. */
18
26
  type XAPIVerbKey = keyof typeof XAPIVerb;
@@ -30,6 +38,15 @@ interface XAPIObjectParams {
30
38
  description?: Record<string, string>;
31
39
  /** Activity type IRI. */
32
40
  type?: string;
41
+ /** xAPI cmi.interaction type (e.g. `choice`, `fill-in`, `long-fill-in`). */
42
+ interactionType?: string;
43
+ /** Correct-responses patterns, per the xAPI CRP format. */
44
+ correctResponsesPattern?: string[];
45
+ /** For choice-family interactions: the available components. */
46
+ choices?: Array<{
47
+ id: string;
48
+ description?: Record<string, string>;
49
+ }>;
33
50
  }
34
51
  /** Parameters for the generic {@link xAPIBuilder.buildStatement}. */
35
52
  interface XAPIStatementParams {
@@ -50,6 +67,20 @@ interface AnsweredStatementParams {
50
67
  context?: XAPIContext;
51
68
  resultExtensions?: Record<string, unknown>;
52
69
  }
70
+ /**
71
+ * Parameters for {@link xAPIBuilder.buildSubmittedStatement} (verb =
72
+ * SUBMITTED — deferred-grading submissions). Carries NO score, success, or
73
+ * completion: the grade does not exist yet (Req 22.7).
74
+ */
75
+ interface SubmittedStatementParams {
76
+ actor: XAPIActor;
77
+ object: XAPIObjectParams;
78
+ timeSpentMs: number;
79
+ /** Serialized learner response string (e.g. the submitted text). */
80
+ response?: string;
81
+ context?: XAPIContext;
82
+ resultExtensions?: Record<string, unknown>;
83
+ }
53
84
  /** Parameters for {@link xAPIBuilder.buildCompletedStatement} (verb = COMPLETED). */
54
85
  interface CompletedStatementParams {
55
86
  actor: XAPIActor;
@@ -67,6 +98,13 @@ interface CompletedStatementParams {
67
98
  declare const xAPIBuilder: {
68
99
  buildStatement(params: XAPIStatementParams): XAPIStatement;
69
100
  buildAnsweredStatement(params: AnsweredStatementParams): XAPIStatement;
101
+ /**
102
+ * Builds a statement for a deferred-grading submission (e.g. a written
103
+ * response). Verb is SUBMITTED and the result deliberately omits `score`,
104
+ * `success`, and `completion` — none of them exist until the asynchronous
105
+ * grader runs; only `duration`, `response`, and extensions are recorded.
106
+ */
107
+ buildSubmittedStatement(params: SubmittedStatementParams): XAPIStatement;
70
108
  buildCompletedStatement(params: CompletedStatementParams): XAPIStatement;
71
109
  };
72
110
 
@@ -85,4 +123,4 @@ declare const xAPIBuilder: {
85
123
  */
86
124
  declare function validateXAPIStatement(statement: XAPIStatement): void;
87
125
 
88
- export { type AnsweredStatementParams, type CompletedStatementParams, type XAPIObjectParams, type XAPIStatementParams, XAPIVerb, type XAPIVerbKey, XAPI_VERB_DISPLAY, validateXAPIStatement, xAPIBuilder };
126
+ export { type AnsweredStatementParams, type CompletedStatementParams, type SubmittedStatementParams, type XAPIObjectParams, type XAPIStatementParams, XAPIVerb, type XAPIVerbKey, XAPI_VERB_DISPLAY, validateXAPIStatement, xAPIBuilder };
package/dist/xapi.js CHANGED
@@ -3,8 +3,8 @@ import {
3
3
  XAPI_VERB_DISPLAY,
4
4
  validateXAPIStatement,
5
5
  xAPIBuilder
6
- } from "./chunk-ZHOX6TO4.js";
7
- import "./chunk-6VOCV4EX.js";
6
+ } from "./chunk-HS7BYCGE.js";
7
+ import "./chunk-3YAVDV5F.js";
8
8
  export {
9
9
  XAPIVerb,
10
10
  XAPI_VERB_DISPLAY,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intellectif/lk-core",
3
- "version": "0.2.1",
3
+ "version": "0.3.1",
4
4
  "description": "Schemas, scoring engine, and xAPI builder for learning-kit",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,7 +34,8 @@
34
34
  "module": "./dist/index.js",
35
35
  "types": "./dist/index.d.ts",
36
36
  "files": [
37
- "dist"
37
+ "dist",
38
+ "LICENSE"
38
39
  ],
39
40
  "dependencies": {
40
41
  "zod": "^3.25.0"
@@ -46,6 +47,10 @@
46
47
  "vitest": "^4.1.6"
47
48
  },
48
49
  "license": "MIT",
50
+ "sideEffects": false,
51
+ "engines": {
52
+ "node": ">=20"
53
+ },
49
54
  "scripts": {
50
55
  "build": "tsup",
51
56
  "test": "vitest run",
@@ -1,330 +0,0 @@
1
- /**
2
- * An xAPI Activity object — the thing a statement is about.
3
- * This SDK only builds Activity-type objects (xAPI 1.0.3 §4.1.4.1).
4
- */
5
- interface XAPIObject {
6
- objectType: 'Activity';
7
- /** IRI uniquely identifying the activity. */
8
- id: string;
9
- definition?: {
10
- /** Language-map of human-readable names for the activity. */
11
- name?: Record<string, string>;
12
- /** Language-map of human-readable descriptions. */
13
- description?: Record<string, string>;
14
- /** IRI identifying the activity type. */
15
- type?: string;
16
- extensions?: Record<string, unknown>;
17
- };
18
- }
19
- /**
20
- * An xAPI Agent (person or system) that performed the statement's verb.
21
- * Exactly one of `mbox` or `account` must be present.
22
- */
23
- interface XAPIActor {
24
- objectType: 'Agent';
25
- /** Display name for the actor. */
26
- name?: string;
27
- /** Mailto IRI uniquely identifying the actor (e.g. `mailto:user@example.com`). */
28
- mbox?: string;
29
- /** Account-based actor identifier. */
30
- account?: {
31
- /** IRI of the home page of the account's service provider. */
32
- homePage: string;
33
- /** The actor's unique name on that service. */
34
- name: string;
35
- };
36
- }
37
- /** An xAPI Verb — the action performed in the statement. */
38
- interface XAPIVerbObject {
39
- /** IRI uniquely identifying this verb (e.g. from adlnet.gov/expapi/verbs). */
40
- id: string;
41
- /** Language-map of human-readable verb labels. */
42
- display: Record<string, string>;
43
- }
44
- /** Score sub-object within an xAPI Result. */
45
- interface XAPIScore {
46
- /** Normalized score in the range [0, 1]. */
47
- scaled: number;
48
- /** Raw score in the instrument's native scale. */
49
- raw?: number;
50
- /** Minimum possible raw score. */
51
- min?: number;
52
- /** Maximum possible raw score. */
53
- max?: number;
54
- }
55
- /** Result information attached to an xAPI Statement. */
56
- interface XAPIResult {
57
- score?: XAPIScore;
58
- /** Whether the actor's performance was successful. */
59
- success?: boolean;
60
- /** Whether the activity was completed. */
61
- completion?: boolean;
62
- /** ISO 8601 duration string representing time spent (e.g. `PT5M30S`). */
63
- duration?: string;
64
- /** A string representation of the learner's response. */
65
- response?: string;
66
- extensions?: Record<string, unknown>;
67
- }
68
- /** Context information attached to an xAPI Statement. */
69
- interface XAPIContext {
70
- /** Name of the software used to record the statement. */
71
- platform?: string;
72
- /** BCP 47 language tag for the activity content. */
73
- language?: string;
74
- extensions?: Record<string, unknown>;
75
- }
76
- /** A complete xAPI 1.0.3 Statement. */
77
- interface XAPIStatement {
78
- /** UUID v4 uniquely identifying this statement. */
79
- id: string;
80
- actor: XAPIActor;
81
- verb: XAPIVerbObject;
82
- object: XAPIObject;
83
- result?: XAPIResult;
84
- context?: XAPIContext;
85
- /** ISO 8601 timestamp of when the statement occurred. */
86
- timestamp: string;
87
- version: '1.0.3';
88
- }
89
- /**
90
- * Configuration passed to `useXAPI` to connect to an LRS endpoint.
91
- * The `auth` field supports both HTTP Basic and Bearer token authentication.
92
- */
93
- interface XAPIConfig {
94
- /** Full URL of the LRS statements endpoint. */
95
- endpoint: string;
96
- /** Authentication credentials for the LRS. */
97
- auth: {
98
- type: 'basic';
99
- username: string;
100
- password: string;
101
- } | {
102
- type: 'bearer';
103
- token: string;
104
- };
105
- /** IRI identifying the activity in all statements sent by this hook instance. */
106
- activityId: string;
107
- actor: XAPIActor;
108
- /** Called after all retry attempts are exhausted. */
109
- onError?: (err: XAPIError) => void;
110
- }
111
- /** Error payload delivered to `XAPIConfig.onError` after retries are exhausted. */
112
- interface XAPIError {
113
- /** The statement that failed to send. */
114
- statement: XAPIStatement;
115
- /** The 1-based attempt number on which the final failure occurred. */
116
- attempt: number;
117
- /** HTTP status code from the LRS, if a response was received. */
118
- statusCode?: number;
119
- /** Human-readable error description. */
120
- message: string;
121
- }
122
-
123
- /** The set of activity types supported by learning-kit. */
124
- type ActivityType = 'multiple-choice' | 'fill-in-the-blanks';
125
- /** Maps each ActivityType string to its corresponding data shape. */
126
- interface ActivityDataMap {
127
- 'multiple-choice': MultipleChoiceData;
128
- 'fill-in-the-blanks': FillInTheBlanksData;
129
- }
130
- /** Union of all valid activity data shapes. */
131
- type ActivityData = MultipleChoiceData | FillInTheBlanksData;
132
- /**
133
- * Optional media (image/audio/video) shown above a question or passage.
134
- * URL-only: hosting/delivery is the consuming application's responsibility.
135
- */
136
- interface ActivityMedia {
137
- /** The kind of media; selects the rendered element. `embed` → sandboxed iframe. */
138
- type: 'image' | 'audio' | 'video' | 'embed';
139
- /**
140
- * Source URL. For `embed` this MUST be the provider's embeddable URL
141
- * (e.g. `https://www.youtube.com/embed/<id>`), not the watch page.
142
- */
143
- url: string;
144
- /** Alternative text. Required for `image` and `embed`; optional label for audio/video. */
145
- alt?: string;
146
- /** Optional WebVTT captions track URL for `audio`/`video`. */
147
- captionsUrl?: string;
148
- }
149
- /**
150
- * Optional authored "overall feedback" shown after submission, chosen by
151
- * whether the learner passed (h5p-style overall feedback). Distinct from
152
- * per-option feedback; either field may be omitted.
153
- */
154
- interface ActivityFeedback {
155
- /** Shown when the learner passes (score ≥ pass threshold). */
156
- correct?: string;
157
- /** Shown when the learner does not pass. */
158
- incorrect?: string;
159
- }
160
- /** A single selectable option within a Multiple Choice activity. */
161
- interface MultipleChoiceOption {
162
- /** Unique identifier for this option within the activity. */
163
- id: string;
164
- /** Display text shown to the learner. */
165
- text: string;
166
- /** Whether this option is part of the correct answer. */
167
- isCorrect: boolean;
168
- /** Optional per-option feedback shown after submission. */
169
- feedback?: string;
170
- }
171
- /** Data contract for a Multiple Choice activity. */
172
- interface MultipleChoiceData {
173
- schemaVersion: '1.0';
174
- type: 'multiple-choice';
175
- /** Unique identifier for this activity. */
176
- id: string;
177
- /** Human-readable title used in xAPI statements and error boundaries. */
178
- title: string;
179
- /** The question stem presented to the learner. */
180
- question: string;
181
- /** `single` allows one selection; `multi` allows multiple. */
182
- mode: 'single' | 'multi';
183
- /** Ordered list of answer options. */
184
- options: MultipleChoiceOption[];
185
- /** Scoring algorithm applied when the learner submits. */
186
- scoringStrategy: 'all-or-nothing' | 'partial';
187
- /** Optional media shown above the question. */
188
- media?: ActivityMedia;
189
- /** Optional authored overall feedback shown after submission. */
190
- feedback?: ActivityFeedback;
191
- /** Minimum scaled score [0–1] required to pass. Defaults to 0.6 when absent. */
192
- passThreshold?: number;
193
- /** When true, options are shuffled deterministically per session. */
194
- shuffle?: boolean;
195
- /** BCP 47 language tag for the activity content. */
196
- locale?: string;
197
- /** IRI references to learning objectives addressed by this activity. */
198
- learningObjectives?: string[];
199
- /** Subjective difficulty on a 1–5 scale. */
200
- difficultyLevel?: 1 | 2 | 3 | 4 | 5;
201
- }
202
- /** Configuration for a single fill-in-the-blank slot. */
203
- interface BlankConfig {
204
- /** Unique identifier matching the `{{blank_id}}` placeholder in the passage. */
205
- id: string;
206
- /** List of strings accepted as correct answers for this blank. */
207
- acceptedAnswers: string[];
208
- /** Whether answer matching is case-sensitive. Defaults to false. */
209
- caseSensitive?: boolean;
210
- /** Whether leading/trailing whitespace is stripped before matching. Defaults to true. */
211
- trimWhitespace?: boolean;
212
- /** Optional hint text revealed on learner request. */
213
- hint?: string;
214
- /** Optional feedback shown inline next to this blank after submission. */
215
- feedback?: string;
216
- }
217
- /** Data contract for a Fill-in-the-Blanks activity. */
218
- interface FillInTheBlanksData {
219
- schemaVersion: '1.0';
220
- type: 'fill-in-the-blanks';
221
- /** Unique identifier for this activity. */
222
- id: string;
223
- /** Human-readable title used in xAPI statements and error boundaries. */
224
- title: string;
225
- /** Passage text containing `{{blank_id}}` placeholders. */
226
- passage: string;
227
- /** Configuration for each blank in the passage. */
228
- blanks: BlankConfig[];
229
- /** Scoring algorithm applied when the learner submits. */
230
- scoringStrategy: 'all-or-nothing' | 'partial';
231
- /** Optional media shown above the passage. */
232
- media?: ActivityMedia;
233
- /** Optional authored overall feedback shown after submission. */
234
- feedback?: ActivityFeedback;
235
- /** Minimum scaled score [0–1] required to pass. Defaults to 0.6 when absent. */
236
- passThreshold?: number;
237
- /** BCP 47 language tag for the activity content. */
238
- locale?: string;
239
- /** IRI references to learning objectives addressed by this activity. */
240
- learningObjectives?: string[];
241
- /** Subjective difficulty on a 1–5 scale. */
242
- difficultyLevel?: 1 | 2 | 3 | 4 | 5;
243
- }
244
- /** Union of all learner response shapes. */
245
- type LearnerResponse = MultipleChoiceLearnerResponse | FillInTheBlanksLearnerResponse;
246
- /** Learner response for a Multiple Choice activity. */
247
- interface MultipleChoiceLearnerResponse {
248
- type: 'multiple-choice';
249
- /** IDs of the options the learner selected. */
250
- selectedOptionIds: string[];
251
- }
252
- /** Learner response for a Fill-in-the-Blanks activity. */
253
- interface FillInTheBlanksLearnerResponse {
254
- type: 'fill-in-the-blanks';
255
- /** Map of blank ID to the learner's typed answer. */
256
- answers: Record<string, string>;
257
- }
258
- /** Per-item scoring breakdown returned by the scoring engine. */
259
- interface ScoringDetail {
260
- /** ID of the option or blank this detail refers to. */
261
- itemId: string;
262
- /** Whether the learner's response for this item was correct. */
263
- correct: boolean;
264
- /** The learner's actual response for this item. */
265
- learnerResponse: string | string[];
266
- /** The expected correct response(s) for this item. */
267
- correctResponse: string | string[];
268
- /** Optional weight applied to this item's contribution to the overall score. */
269
- weight?: number;
270
- }
271
- /** Full scoring result returned by the scoring engine. */
272
- interface ScoringResult {
273
- /** Scaled score in the range [0, 1]. */
274
- score: number;
275
- /** Maximum possible scaled score (always 1). */
276
- maxScore: number;
277
- /** Whether the score meets or exceeds the activity's pass threshold. */
278
- passed: boolean;
279
- /** Optional top-level feedback message, or null when absent. */
280
- feedback: string | null;
281
- /** Per-item scoring breakdown. */
282
- details: ScoringDetail[];
283
- }
284
- /** A single validation error produced by `validateActivity`. */
285
- interface ValidationError {
286
- /** JSON-path-style location of the invalid field. */
287
- path: string[];
288
- /** Human-readable description of the validation failure. */
289
- message: string;
290
- /** Machine-readable error code. */
291
- code: string;
292
- }
293
- /**
294
- * Result of a `validateActivity` call.
295
- * On success, `data` is the validated and typed activity data.
296
- * On failure, `errors` contains one entry per violated constraint.
297
- */
298
- type ValidationResult<T> = {
299
- success: true;
300
- data: T;
301
- } | {
302
- success: false;
303
- errors: ValidationError[];
304
- };
305
- /** The payload delivered to an activity's `onComplete` callback. */
306
- interface ActivityResult {
307
- /** Scaled score in the range [0, 1]. */
308
- score: number;
309
- /** Maximum possible scaled score (always 1). */
310
- maxScore: number;
311
- /** Whether the learner passed based on the activity's pass threshold. */
312
- passed: boolean;
313
- /** Time in milliseconds from first interaction to submission. */
314
- timeSpent: number;
315
- /** The xAPI statement built and (optionally) sent for this attempt. */
316
- xapiStatement: XAPIStatement;
317
- }
318
- /** Fired by activity components on every discrete learner interaction. */
319
- interface InteractionEvent {
320
- /** The kind of interaction that occurred. */
321
- type: 'option-selected' | 'option-deselected' | 'blank-filled' | 'hint-requested' | 'submitted';
322
- /** ID of the activity that produced the event. */
323
- activityId: string;
324
- /** Unix timestamp (ms) of when the interaction occurred. */
325
- timestamp: number;
326
- /** Additional event-specific data. */
327
- payload: Record<string, unknown>;
328
- }
329
-
330
- export type { ActivityData as A, BlankConfig as B, FillInTheBlanksData as F, InteractionEvent as I, LearnerResponse as L, MultipleChoiceData as M, ScoringDetail as S, ValidationError as V, XAPIActor as X, ActivityDataMap as a, ActivityFeedback as b, ActivityMedia as c, ActivityResult as d, ActivityType as e, FillInTheBlanksLearnerResponse as f, MultipleChoiceLearnerResponse as g, MultipleChoiceOption as h, ScoringResult as i, ValidationResult as j, XAPIConfig as k, XAPIContext as l, XAPIError as m, XAPIObject as n, XAPIResult as o, XAPIScore as p, XAPIStatement as q, XAPIVerbObject as r };