@intellectif/lk-core 1.3.0 → 1.4.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 (48) hide show
  1. package/CHANGELOG.md +14 -0
  2. package/dist/{ai-B222dtHH.d.ts → ai-CnmLPMzd.d.cts} +265 -2
  3. package/dist/ai-CnmLPMzd.d.cts.map +1 -0
  4. package/dist/{ai-B222dtHH.d.cts → ai-CnmLPMzd.d.ts} +265 -2
  5. package/dist/ai-CnmLPMzd.d.ts.map +1 -0
  6. package/dist/ai-check.cjs +101 -8
  7. package/dist/ai-check.cjs.map +1 -1
  8. package/dist/ai-check.d.cts +1 -1
  9. package/dist/ai-check.d.cts.map +1 -1
  10. package/dist/ai-check.d.ts +1 -1
  11. package/dist/ai-check.d.ts.map +1 -1
  12. package/dist/ai-check.js +101 -8
  13. package/dist/ai-check.js.map +1 -1
  14. package/dist/{ai-writing-CCBjTOM3.js → ai-writing-CPpH9Qxq.js} +126 -21
  15. package/dist/ai-writing-CPpH9Qxq.js.map +1 -0
  16. package/dist/{ai-writing-DCVkv4Zj.cjs → ai-writing-G6tnCGzw.cjs} +114 -3
  17. package/dist/ai-writing-G6tnCGzw.cjs.map +1 -0
  18. package/dist/{index-BWPRPIXL.d.ts → index-2nigSf4N.d.cts} +3 -217
  19. package/dist/index-2nigSf4N.d.cts.map +1 -0
  20. package/dist/{index-O4_ExlAD.d.cts → index-B54baFUA.d.ts} +3 -217
  21. package/dist/index-B54baFUA.d.ts.map +1 -0
  22. package/dist/{index-Dyu66R4-.d.cts → index-BAfEHCnD.d.cts} +2 -2
  23. package/dist/{index-Dyu66R4-.d.cts.map → index-BAfEHCnD.d.cts.map} +1 -1
  24. package/dist/{index-CXyOV8sm.d.cts → index-BqMXWuNC.d.cts} +2 -2
  25. package/dist/{index-CXyOV8sm.d.cts.map → index-BqMXWuNC.d.cts.map} +1 -1
  26. package/dist/{index-UGxRSopE.d.ts → index-CVWvymVb.d.ts} +2 -2
  27. package/dist/{index-UGxRSopE.d.ts.map → index-CVWvymVb.d.ts.map} +1 -1
  28. package/dist/{index-CegM8o15.d.ts → index-CcHDTxIZ.d.ts} +2 -2
  29. package/dist/{index-CegM8o15.d.ts.map → index-CcHDTxIZ.d.ts.map} +1 -1
  30. package/dist/index.cjs +2 -1
  31. package/dist/index.d.cts +35 -7
  32. package/dist/index.d.cts.map +1 -1
  33. package/dist/index.d.ts +35 -7
  34. package/dist/index.d.ts.map +1 -1
  35. package/dist/index.js +2 -2
  36. package/dist/schemas.d.cts +1 -1
  37. package/dist/schemas.d.ts +1 -1
  38. package/dist/scoring.d.cts +2 -2
  39. package/dist/scoring.d.ts +2 -2
  40. package/dist/xapi.d.cts +1 -1
  41. package/dist/xapi.d.ts +1 -1
  42. package/package.json +1 -1
  43. package/dist/ai-B222dtHH.d.cts.map +0 -1
  44. package/dist/ai-B222dtHH.d.ts.map +0 -1
  45. package/dist/ai-writing-CCBjTOM3.js.map +0 -1
  46. package/dist/ai-writing-DCVkv4Zj.cjs.map +0 -1
  47. package/dist/index-BWPRPIXL.d.ts.map +0 -1
  48. package/dist/index-O4_ExlAD.d.cts.map +0 -1
@@ -1,6 +1,95 @@
1
1
  const require_registry = require("./registry-DVi0LR_i.cjs");
2
2
  const require_scoring = require("./scoring-B2_HEhMT.cjs");
3
3
  const require_item_group = require("./item-group-DroFXgLb.cjs");
4
+ //#region src/ai-material.ts
5
+ /**
6
+ * What a model is told about the group a question sits in: the material the
7
+ * learner reads and sees beside it.
8
+ *
9
+ * Internal: the request builders in `ai.ts` and `ai-writing.ts` are its public
10
+ * face, through their `group` input.
11
+ */
12
+ /**
13
+ * The longest material text a model is given, in code points. A longer one is
14
+ * cut and marked `truncated`: a long reading passage on an exam paper runs to
15
+ * 4,000–7,000.
16
+ */
17
+ const AI_MATERIAL_MAX_LENGTH = 12e3;
18
+ const KINDS$2 = {
19
+ text: true,
20
+ audio: true,
21
+ video: true,
22
+ image: true,
23
+ mixed: true
24
+ };
25
+ const MEDIA_TYPES = {
26
+ image: true,
27
+ audio: true,
28
+ video: true,
29
+ embed: true
30
+ };
31
+ const isRecord$4 = (value) => typeof value === "object" && value !== null && !Array.isArray(value);
32
+ /** A string with something in it, as written; otherwise nothing. */
33
+ const filled = (value) => typeof value === "string" && value.trim() !== "" ? value : void 0;
34
+ /**
35
+ * `text` cut to {@link AI_MATERIAL_MAX_LENGTH} code points. The cut falls at
36
+ * the last space in its second half, so no word is broken; in a script written
37
+ * without spaces, at the limit itself.
38
+ */
39
+ function cut(text) {
40
+ const points = [...text];
41
+ if (points.length <= 12e3) return {
42
+ text,
43
+ truncated: false
44
+ };
45
+ let end = AI_MATERIAL_MAX_LENGTH;
46
+ for (let at = AI_MATERIAL_MAX_LENGTH; at >= AI_MATERIAL_MAX_LENGTH / 2; at -= 1) if (/\s/u.test(points[at])) {
47
+ end = at;
48
+ break;
49
+ }
50
+ return {
51
+ text: points.slice(0, end).join("").trimEnd(),
52
+ truncated: true
53
+ };
54
+ }
55
+ /**
56
+ * The facts of `group`'s material, or `null` without a group or a stimulus it
57
+ * can read: not an object, or of a kind the SDK does not know.
58
+ *
59
+ * Only what the learner sees reaches a model. The `transcript` is author-only
60
+ * and never read, so the facts are the same for a whole group and a redacted
61
+ * one; a media address is never read either, since a model cannot open one
62
+ * and a signed address must not end up in a prompt. Each field is read once.
63
+ */
64
+ function materialFacts(group) {
65
+ if (!isRecord$4(group)) return null;
66
+ const stimulus = group.stimulus;
67
+ if (!isRecord$4(stimulus)) return null;
68
+ const kind = stimulus.kind;
69
+ if (typeof kind !== "string" || !Object.hasOwn(KINDS$2, kind)) return null;
70
+ const title = filled(stimulus.title) ?? filled(group.title);
71
+ const body = filled(stimulus.body);
72
+ const text = body === void 0 ? void 0 : cut(body);
73
+ const rawMedia = stimulus.media;
74
+ const mediaType = isRecord$4(rawMedia) ? rawMedia.type : void 0;
75
+ const alt = isRecord$4(rawMedia) ? filled(rawMedia.alt) : void 0;
76
+ const media = typeof mediaType === "string" && Object.hasOwn(MEDIA_TYPES, mediaType) ? {
77
+ type: mediaType,
78
+ ...alt !== void 0 ? { alt } : {}
79
+ } : void 0;
80
+ const attribution = filled(stimulus.attribution);
81
+ const locale = filled(stimulus.locale);
82
+ return {
83
+ kind,
84
+ ...title !== void 0 ? { title } : {},
85
+ ...text !== void 0 ? { text: text.text } : {},
86
+ ...text?.truncated === true ? { truncated: true } : {},
87
+ ...media !== void 0 ? { media } : {},
88
+ ...attribution !== void 0 ? { attribution } : {},
89
+ ...locale !== void 0 ? { locale } : {}
90
+ };
91
+ }
92
+ //#endregion
4
93
  //#region src/ai-text.ts
5
94
  /**
6
95
  * How the SDK reads text a model wrote, before a learner does. Internal: shared
@@ -341,6 +430,10 @@ function gradeLocally(data, response) {
341
430
  * positive and finite, `score` finite from 0 to it) gets no explanation at all:
342
431
  * explaining 85 "out of 1" would tell the model a wrong answer was correct, and
343
432
  * grading locally instead would speak to a grade the screen does not show.
433
+ *
434
+ * `group` is the item group the question sits in: its material — the passage,
435
+ * or the instructions the group's questions share — goes with the request as
436
+ * `material`, as the learner sees it.
344
437
  */
345
438
  function aiExplanationRequest(input) {
346
439
  const { data, response, outcome, learnerLocale } = input;
@@ -366,10 +459,12 @@ function aiExplanationRequest(input) {
366
459
  if (grade === null) return null;
367
460
  const facts = buildAiFacts(data, response, details);
368
461
  if (facts === null) return null;
462
+ const material = materialFacts(input.group);
369
463
  return {
370
464
  feature: "explanation",
371
465
  facts,
372
466
  grade,
467
+ ...material !== null ? { material } : {},
373
468
  ...learnerLocale !== void 0 ? { learnerLocale } : {}
374
469
  };
375
470
  }
@@ -380,7 +475,11 @@ function aiExplanationRequest(input) {
380
475
  *
381
476
  * The facts carry the key, and which parts the learner has right so far, so a
382
477
  * model can hint where it helps. The learner never sees them; a hint that
383
- * contains an answer is refused by {@link checkAiHint}.
478
+ * contains an answer is refused by {@link checkAiHint}, whatever it quotes —
479
+ * the group's material included.
480
+ *
481
+ * `group` is the item group the question sits in, as for
482
+ * {@link aiExplanationRequest}.
384
483
  */
385
484
  function aiHintRequest(input) {
386
485
  const { data, previousHints, learnerLocale } = input;
@@ -388,11 +487,13 @@ function aiHintRequest(input) {
388
487
  const response = input.response ?? emptyResponse(data.type);
389
488
  const facts = buildAiFacts(data, response, (response === null ? null : gradeLocally(data, response))?.details ?? null);
390
489
  if (facts === null) return null;
490
+ const material = materialFacts(input.group);
391
491
  return {
392
492
  feature: "hint",
393
493
  facts,
394
494
  hintNumber: previousHints.length + 1,
395
495
  previousHints: [...previousHints],
496
+ ...material !== null ? { material } : {},
396
497
  ...learnerLocale !== void 0 ? { learnerLocale } : {}
397
498
  };
398
499
  }
@@ -2204,7 +2305,9 @@ const MAX_TAG_LENGTH = 40;
2204
2305
  * The facts are the task as the learner saw it, the draft verbatim with its
2205
2306
  * word count recomputed as the grader will count it, and the rubric the answer
2206
2307
  * will be graded on. `previousFeedback` is the text of the feedback already
2207
- * shown on earlier drafts, so a model can speak to what changed.
2308
+ * shown on earlier drafts, so a model can speak to what changed. `group` is the
2309
+ * item group the task sits in: its material, the text a summary is of, goes
2310
+ * with the request as `material`.
2208
2311
  */
2209
2312
  function aiWritingFeedbackRequest(input) {
2210
2313
  const { data, response, learnerLocale } = input;
@@ -2222,6 +2325,7 @@ function aiWritingFeedbackRequest(input) {
2222
2325
  weight: criterion.weight
2223
2326
  }));
2224
2327
  const previousFeedback = [...input.previousFeedback ?? []];
2328
+ const material = materialFacts(input.group);
2225
2329
  return {
2226
2330
  feature: "writing-feedback",
2227
2331
  facts: {
@@ -2240,6 +2344,7 @@ function aiWritingFeedbackRequest(input) {
2240
2344
  },
2241
2345
  draftNumber: previousFeedback.length + 1,
2242
2346
  previousFeedback,
2347
+ ...material !== null ? { material } : {},
2243
2348
  ...learnerLocale !== void 0 ? { learnerLocale } : {}
2244
2349
  };
2245
2350
  }
@@ -2539,6 +2644,12 @@ Object.defineProperty(exports, "AI_HINT_TYPES", {
2539
2644
  return AI_HINT_TYPES;
2540
2645
  }
2541
2646
  });
2647
+ Object.defineProperty(exports, "AI_MATERIAL_MAX_LENGTH", {
2648
+ enumerable: true,
2649
+ get: function() {
2650
+ return AI_MATERIAL_MAX_LENGTH;
2651
+ }
2652
+ });
2542
2653
  Object.defineProperty(exports, "AI_TEXT_MAX_LENGTH", {
2543
2654
  enumerable: true,
2544
2655
  get: function() {
@@ -2732,4 +2843,4 @@ Object.defineProperty(exports, "validateItemGroupDraft", {
2732
2843
  }
2733
2844
  });
2734
2845
 
2735
- //# sourceMappingURL=ai-writing-DCVkv4Zj.cjs.map
2846
+ //# sourceMappingURL=ai-writing-G6tnCGzw.cjs.map