@happyvertical/smrt-education 0.57.47 → 0.57.49
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +9 -0
- package/README.md +23 -2
- package/agents/course-authoring-service.md +44 -1
- package/agents/course-bundle-import.md +148 -0
- package/agents/group-sharing.md +20 -0
- package/agents/learner-service.md +35 -0
- package/agents/question-extraction.md +4 -1
- package/agents/tutor-context.md +62 -0
- package/dist/catalog.d.ts +12 -0
- package/dist/catalog.d.ts.map +1 -1
- package/dist/chunks/{workbook-photo-service-B7Tujv__.js → workbook-photo-service-WwDDC5GF.js} +692 -18
- package/dist/chunks/workbook-photo-service-WwDDC5GF.js.map +1 -0
- package/dist/course-authoring-contracts.d.ts +26 -3
- package/dist/course-authoring-contracts.d.ts.map +1 -1
- package/dist/course-authoring-models.d.ts +44 -1
- package/dist/course-authoring-models.d.ts.map +1 -1
- package/dist/course-authoring-service.d.ts +39 -0
- package/dist/course-authoring-service.d.ts.map +1 -1
- package/dist/course-bundle-contracts.d.ts +93 -0
- package/dist/course-bundle-contracts.d.ts.map +1 -0
- package/dist/course-bundle-models.d.ts +66 -0
- package/dist/course-bundle-models.d.ts.map +1 -0
- package/dist/course-bundle-service.d.ts +126 -0
- package/dist/course-bundle-service.d.ts.map +1 -0
- package/dist/course-bundle-zip.d.ts +48 -0
- package/dist/course-bundle-zip.d.ts.map +1 -0
- package/dist/course-bundle.d.ts +135 -0
- package/dist/course-bundle.d.ts.map +1 -0
- package/dist/course-visibility.d.ts +22 -0
- package/dist/course-visibility.d.ts.map +1 -0
- package/dist/group-sharing-reader.d.ts.map +1 -1
- package/dist/index.d.ts +17 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2563 -510
- package/dist/index.js.map +1 -1
- package/dist/ingestion.js +1 -1
- package/dist/learner-history.d.ts +50 -1
- package/dist/learner-history.d.ts.map +1 -1
- package/dist/learner-plan-service.d.ts.map +1 -1
- package/dist/learner-service.d.ts +91 -2
- package/dist/learner-service.d.ts.map +1 -1
- package/dist/learners.d.ts +2 -0
- package/dist/learners.d.ts.map +1 -1
- package/dist/manifest.json +11774 -7626
- package/dist/question-response-service.d.ts +21 -3
- package/dist/question-response-service.d.ts.map +1 -1
- package/dist/smrt-knowledge.json +3507 -2008
- package/dist/tutor-context-service.d.ts +34 -0
- package/dist/tutor-context-service.d.ts.map +1 -0
- package/dist/tutor-contracts.d.ts +123 -0
- package/dist/tutor-contracts.d.ts.map +1 -0
- package/dist/tutor-models.d.ts +77 -0
- package/dist/tutor-models.d.ts.map +1 -0
- package/dist/tutor-session-service.d.ts +115 -0
- package/dist/tutor-session-service.d.ts.map +1 -0
- package/package.json +8 -8
- package/dist/chunks/workbook-photo-service-B7Tujv__.js.map +0 -1
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { DatabaseInterface } from '@happyvertical/sql';
|
|
2
|
+
import { type LearnerRequest } from './learner-service.js';
|
|
3
|
+
import { QuestionResponseService } from './question-response-service.js';
|
|
4
|
+
import { type TutorAudience, type TutorContext } from './tutor-contracts.js';
|
|
5
|
+
export type TutorContextRequest = LearnerRequest & {
|
|
6
|
+
audience: TutorAudience;
|
|
7
|
+
enrollmentId?: string;
|
|
8
|
+
lessonId?: string;
|
|
9
|
+
/** Focus one question of the lesson (a question revision id). */
|
|
10
|
+
questionRevisionId?: string;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Composes the bounded `TutorContext` for one learner. Pure data: no AI call,
|
|
14
|
+
* no prompt text. Every read uses this service's executor and the
|
|
15
|
+
* `education.tutor.read` decision of the host authorizer, with the same
|
|
16
|
+
* actor/tenant/relationship checks as `LearnerService`.
|
|
17
|
+
*/
|
|
18
|
+
export declare class TutorContextService extends QuestionResponseService {
|
|
19
|
+
protected createTransactionService(db: DatabaseInterface): this;
|
|
20
|
+
compose(request: TutorContextRequest): Promise<TutorContext>;
|
|
21
|
+
/** The released lesson revision and ordered question refs, or null if none. */
|
|
22
|
+
private releasedLesson;
|
|
23
|
+
private objectiveStatements;
|
|
24
|
+
/** Count and latest status only: no notes, intake ids or files. */
|
|
25
|
+
private submissionSummary;
|
|
26
|
+
/**
|
|
27
|
+
* Learner audience: the newest assessment revision a guardian explicitly
|
|
28
|
+
* released, its feedback text only (no score, concept labels or per-question
|
|
29
|
+
* detail). Guardian audience: the newest guardian-confirmed revision, else
|
|
30
|
+
* the newest one.
|
|
31
|
+
*/
|
|
32
|
+
private releasedFeedback;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=tutor-context-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tutor-context-service.d.ts","sourceRoot":"","sources":["../src/tutor-context-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,oBAAoB,CAAC;AAG5D,OAAO,EAEL,KAAK,cAAc,EAEpB,MAAM,sBAAsB,CAAC;AAI9B,OAAO,EACL,uBAAuB,EAExB,MAAM,gCAAgC,CAAC;AACxC,OAAO,EAYL,KAAK,aAAa,EAClB,KAAK,YAAY,EAElB,MAAM,sBAAsB,CAAC;AAI9B,MAAM,MAAM,mBAAmB,GAAG,cAAc,GAAG;IACjD,QAAQ,EAAE,aAAa,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,iEAAiE;IACjE,kBAAkB,CAAC,EAAE,MAAM,CAAC;CAC7B,CAAC;AAEF;;;;;GAKG;AACH,qBAAa,mBAAoB,SAAQ,uBAAuB;cAC3C,wBAAwB,CAAC,EAAE,EAAE,iBAAiB,GAAG,IAAI;IAQlE,OAAO,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,YAAY,CAAC;IA0UlE,+EAA+E;YACjE,cAAc;YAwBd,mBAAmB;IA0BjC,mEAAmE;YACrD,iBAAiB;IAmB/B;;;;;OAKG;YACW,gBAAgB;CA4D/B"}
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
import { LearnerValidationError } from './learner-service.js';
|
|
2
|
+
export declare const TUTOR_AUDIENCES: readonly ["learner", "guardian"];
|
|
3
|
+
export type TutorAudience = (typeof TUTOR_AUDIENCES)[number];
|
|
4
|
+
export declare const TUTOR_SESSION_MODES: readonly ["chat", "voice"];
|
|
5
|
+
export type TutorSessionMode = (typeof TUTOR_SESSION_MODES)[number];
|
|
6
|
+
export declare const TUTOR_EXCHANGE_ROLES: readonly ["learner", "tutor", "system"];
|
|
7
|
+
export type TutorExchangeRole = (typeof TUTOR_EXCHANGE_ROLES)[number];
|
|
8
|
+
/** Host content/safety classification of one exchange; `none` is unclassified. */
|
|
9
|
+
export declare const TUTOR_EXCHANGE_MARKERS: readonly ["none", "filtered", "redacted", "flagged"];
|
|
10
|
+
export type TutorExchangeMarker = (typeof TUTOR_EXCHANGE_MARKERS)[number];
|
|
11
|
+
/** Longest lesson body, in characters; longer text is cut and `truncated` set. */
|
|
12
|
+
export declare const MAX_TUTOR_BODY_CHARS = 8000;
|
|
13
|
+
/** Longest question prompt, subpart prompt or choice label, in characters. */
|
|
14
|
+
export declare const MAX_TUTOR_PROMPT_CHARS = 2000;
|
|
15
|
+
/** Longest answer key or rubric text (guardian audience), in characters. */
|
|
16
|
+
export declare const MAX_TUTOR_KEY_CHARS = 2000;
|
|
17
|
+
/** Longest released-feedback text, in characters. */
|
|
18
|
+
export declare const MAX_TUTOR_FEEDBACK_CHARS = 2000;
|
|
19
|
+
/** Longest title or objective statement, in characters. */
|
|
20
|
+
export declare const MAX_TUTOR_TITLE_CHARS = 300;
|
|
21
|
+
export declare const MAX_TUTOR_QUESTIONS = 30;
|
|
22
|
+
export declare const MAX_TUTOR_CHOICES = 12;
|
|
23
|
+
export declare const MAX_TUTOR_SUBPARTS = 12;
|
|
24
|
+
export declare const MAX_TUTOR_OBJECTIVES = 10;
|
|
25
|
+
/** Serialized size ceiling of a whole context; trailing questions drop first. */
|
|
26
|
+
export declare const MAX_TUTOR_CONTEXT_CHARS = 48000;
|
|
27
|
+
/** Longest exchange text, in characters. Over-cap or empty text is refused. */
|
|
28
|
+
export declare const MAX_TUTOR_EXCHANGE_TEXT_CHARS = 4000;
|
|
29
|
+
export declare const MAX_TUTOR_TOOL_SUMMARY_CHARS = 1000;
|
|
30
|
+
export declare const DEFAULT_TUTOR_SESSION_PAGE = 20;
|
|
31
|
+
export declare const MAX_TUTOR_SESSION_PAGE = 50;
|
|
32
|
+
export declare const DEFAULT_TUTOR_EXCHANGE_PAGE = 50;
|
|
33
|
+
export declare const MAX_TUTOR_EXCHANGE_PAGE = 200;
|
|
34
|
+
export type TutorQuestionItem = Readonly<{
|
|
35
|
+
ordinal: number;
|
|
36
|
+
questionRevisionId: string;
|
|
37
|
+
prompt: string;
|
|
38
|
+
responseType: string;
|
|
39
|
+
choices: ReadonlyArray<{
|
|
40
|
+
id: string;
|
|
41
|
+
label: string;
|
|
42
|
+
}>;
|
|
43
|
+
subparts: ReadonlyArray<{
|
|
44
|
+
partKey: string;
|
|
45
|
+
prompt: string;
|
|
46
|
+
}>;
|
|
47
|
+
pointsPossible: number | null;
|
|
48
|
+
/** Guardian audience only: answer key as capped JSON text. */
|
|
49
|
+
answerKey?: string | null;
|
|
50
|
+
/** Guardian audience only: rubric as capped JSON text. */
|
|
51
|
+
rubric?: string | null;
|
|
52
|
+
}>;
|
|
53
|
+
/**
|
|
54
|
+
* Bounded, data-only view a host may turn into tutor prompts. For the learner
|
|
55
|
+
* audience it holds no answer key, rubric, guardian note, storage locator,
|
|
56
|
+
* asset id, other learner's data or grading internals; only
|
|
57
|
+
* `answerKeyAvailable` says that a key exists.
|
|
58
|
+
*/
|
|
59
|
+
export type TutorContext = Readonly<{
|
|
60
|
+
version: 1;
|
|
61
|
+
audience: TutorAudience;
|
|
62
|
+
learner: Readonly<{
|
|
63
|
+
id: string;
|
|
64
|
+
displayName: string;
|
|
65
|
+
level: number;
|
|
66
|
+
}>;
|
|
67
|
+
enrollment: Readonly<{
|
|
68
|
+
id: string;
|
|
69
|
+
courseId: string;
|
|
70
|
+
status: string;
|
|
71
|
+
lessonsPerWeek: number | null;
|
|
72
|
+
}> | null;
|
|
73
|
+
course: Readonly<{
|
|
74
|
+
id: string;
|
|
75
|
+
title: string;
|
|
76
|
+
}> | null;
|
|
77
|
+
section: Readonly<{
|
|
78
|
+
title: string;
|
|
79
|
+
}> | null;
|
|
80
|
+
lesson: Readonly<{
|
|
81
|
+
id: string;
|
|
82
|
+
title: string;
|
|
83
|
+
kind: string;
|
|
84
|
+
/** Learner-facing lesson text; empty when withheld or absent. */
|
|
85
|
+
body: string;
|
|
86
|
+
bodyWithheld: boolean;
|
|
87
|
+
estimatedMinutes: number;
|
|
88
|
+
}> | null;
|
|
89
|
+
objectives: ReadonlyArray<string>;
|
|
90
|
+
progress: Readonly<{
|
|
91
|
+
status: string;
|
|
92
|
+
completedAt: string | null;
|
|
93
|
+
}> | null;
|
|
94
|
+
questions: ReadonlyArray<TutorQuestionItem>;
|
|
95
|
+
/** The question the tutor is asked about, when one was requested. */
|
|
96
|
+
focusQuestionRevisionId: string | null;
|
|
97
|
+
submissions: Readonly<{
|
|
98
|
+
count: number;
|
|
99
|
+
latestStatus: string | null;
|
|
100
|
+
}>;
|
|
101
|
+
/** Latest explicitly released feedback text for the lesson, if any. */
|
|
102
|
+
feedback: Readonly<{
|
|
103
|
+
text: string;
|
|
104
|
+
}> | null;
|
|
105
|
+
answerKeyAvailable: boolean;
|
|
106
|
+
/** True when any text or list was cut to fit a bound. */
|
|
107
|
+
truncated: boolean;
|
|
108
|
+
/** Digest of this context; sessions store it instead of the text. */
|
|
109
|
+
contextHash: string;
|
|
110
|
+
}>;
|
|
111
|
+
export declare class TutorSessionClosedError extends LearnerValidationError {
|
|
112
|
+
constructor();
|
|
113
|
+
}
|
|
114
|
+
export declare class TutorRequestKeyConflictError extends LearnerValidationError {
|
|
115
|
+
constructor();
|
|
116
|
+
}
|
|
117
|
+
export declare class TutorConsentRequiredError extends LearnerValidationError {
|
|
118
|
+
constructor();
|
|
119
|
+
}
|
|
120
|
+
export declare class TutorExchangeError extends LearnerValidationError {
|
|
121
|
+
constructor(message: string);
|
|
122
|
+
}
|
|
123
|
+
//# sourceMappingURL=tutor-contracts.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tutor-contracts.d.ts","sourceRoot":"","sources":["../src/tutor-contracts.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
import { SmrtCollection, SmrtObject, type SmrtSaveOptions } from '@happyvertical/smrt-core';
|
|
2
|
+
import { type TutorAudience, type TutorExchangeMarker, type TutorExchangeRole, type TutorSessionMode } from './tutor-contracts.js';
|
|
3
|
+
/**
|
|
4
|
+
* Append-only record that a tutor session was opened for one learner. It holds
|
|
5
|
+
* identifiers and a context digest only: never context text, and never answer
|
|
6
|
+
* material. "Open" is the absence of a `TutorSessionClosure`.
|
|
7
|
+
*/
|
|
8
|
+
export declare class TutorSession extends SmrtObject {
|
|
9
|
+
tenantId: string;
|
|
10
|
+
learnerId: string;
|
|
11
|
+
enrollmentId: string | null;
|
|
12
|
+
lessonId: string | null;
|
|
13
|
+
audience: TutorAudience;
|
|
14
|
+
mode: TutorSessionMode;
|
|
15
|
+
/** Voice consent the host recorded for this learner before a voice session. */
|
|
16
|
+
voiceConsent: boolean;
|
|
17
|
+
openedByUserId: string;
|
|
18
|
+
/** Idempotency key for `open`, unique per learner. */
|
|
19
|
+
requestKey: string;
|
|
20
|
+
/** Digest of the request, so a changed replay is refused. */
|
|
21
|
+
requestDigest: string;
|
|
22
|
+
/** Digest of the `TutorContext` given to the tutor; never the context itself. */
|
|
23
|
+
contextHash: string | null;
|
|
24
|
+
openedAt: Date;
|
|
25
|
+
constructor(options?: Record<string, unknown>);
|
|
26
|
+
delete(): Promise<void>;
|
|
27
|
+
save(options?: SmrtSaveOptions): Promise<this>;
|
|
28
|
+
}
|
|
29
|
+
export declare class TutorSessionCollection extends SmrtCollection<TutorSession> {
|
|
30
|
+
static readonly _itemClass: typeof TutorSession;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Append-only close record, at most one per session. A session is closed once
|
|
34
|
+
* this row exists; the session row itself is never rewritten.
|
|
35
|
+
*/
|
|
36
|
+
export declare class TutorSessionClosure extends SmrtObject {
|
|
37
|
+
tenantId: string;
|
|
38
|
+
sessionId: string;
|
|
39
|
+
learnerId: string;
|
|
40
|
+
actorUserId: string;
|
|
41
|
+
closedAt: Date;
|
|
42
|
+
constructor(options?: Record<string, unknown>);
|
|
43
|
+
delete(): Promise<void>;
|
|
44
|
+
save(options?: SmrtSaveOptions): Promise<this>;
|
|
45
|
+
}
|
|
46
|
+
export declare class TutorSessionClosureCollection extends SmrtCollection<TutorSessionClosure> {
|
|
47
|
+
static readonly _itemClass: typeof TutorSessionClosure;
|
|
48
|
+
}
|
|
49
|
+
/** Append-only message in a tutor session, ordered by `sequence` from 1. */
|
|
50
|
+
export declare class TutorExchange extends SmrtObject {
|
|
51
|
+
tenantId: string;
|
|
52
|
+
sessionId: string;
|
|
53
|
+
learnerId: string;
|
|
54
|
+
sequence: number;
|
|
55
|
+
role: TutorExchangeRole;
|
|
56
|
+
text: string;
|
|
57
|
+
actorUserId: string;
|
|
58
|
+
/** Optional context reference: ids only. */
|
|
59
|
+
lessonId: string | null;
|
|
60
|
+
questionRevisionId: string | null;
|
|
61
|
+
/** Host content/safety classification of this text. */
|
|
62
|
+
marker: TutorExchangeMarker;
|
|
63
|
+
/** Short host-written summary of tool calls; never raw arguments. */
|
|
64
|
+
toolSummary: string;
|
|
65
|
+
inputTokens: number;
|
|
66
|
+
outputTokens: number;
|
|
67
|
+
requestKey: string;
|
|
68
|
+
requestDigest: string;
|
|
69
|
+
recordedAt: Date;
|
|
70
|
+
constructor(options?: Record<string, unknown>);
|
|
71
|
+
delete(): Promise<void>;
|
|
72
|
+
save(options?: SmrtSaveOptions): Promise<this>;
|
|
73
|
+
}
|
|
74
|
+
export declare class TutorExchangeCollection extends SmrtCollection<TutorExchange> {
|
|
75
|
+
static readonly _itemClass: typeof TutorExchange;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=tutor-models.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tutor-models.d.ts","sourceRoot":"","sources":["../src/tutor-models.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,cAAc,EACd,UAAU,EACV,KAAK,eAAe,EAErB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAOL,KAAK,aAAa,EAClB,KAAK,mBAAmB,EACxB,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACtB,MAAM,sBAAsB,CAAC;AA4B9B;;;;GAIG;AACH,qBAMa,YAAa,SAAQ,UAAU;IAC9B,QAAQ,SAAM;IACiB,SAAS,SAAM;IACjB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAQ;IACnC,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IACxE,QAAQ,EAAE,aAAa,CAAa;IACpC,IAAI,EAAE,gBAAgB,CAAU;IAChC,+EAA+E;IAC/E,YAAY,UAAS;IACrB,cAAc,SAAM;IACpB,sDAAsD;IACtD,UAAU,SAAM;IAChB,6DAA6D;IAC7D,aAAa,SAAM;IACnB,iFAAiF;IACxC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC3E,QAAQ,OAAc;gBACV,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAGvB,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAmC9D;AACD,qBAAa,sBAAuB,SAAQ,cAAc,CAAC,YAAY,CAAC;IACtE,MAAM,CAAC,QAAQ,CAAC,UAAU,sBAAgB;CAC3C;AAED;;;GAGG;AACH,qBAMa,mBAAoB,SAAQ,UAAU;IACrC,QAAQ,SAAM;IACsB,SAAS,SAAM;IACpB,SAAS,SAAM;IAC1D,WAAW,SAAM;IACjB,QAAQ,OAAc;gBACV,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAGvB,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAe9D;AACD,qBAAa,6BAA8B,SAAQ,cAAc,CAAC,mBAAmB,CAAC;IACpF,MAAM,CAAC,QAAQ,CAAC,UAAU,6BAAuB;CAClD;AAED,4EAA4E;AAC5E,qBAaa,aAAc,SAAQ,UAAU;IAC/B,QAAQ,SAAM;IACsB,SAAS,SAAM;IACpB,SAAS,SAAM;IAC1D,QAAQ,SAAK;IACb,IAAI,EAAE,iBAAiB,CAAa;IACX,IAAI,SAAM;IACnC,WAAW,SAAM;IACjB,4CAA4C;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAQ;IAC/B,kBAAkB,EAAE,MAAM,GAAG,IAAI,CACnE;IACP,uDAAuD;IACvD,MAAM,EAAE,mBAAmB,CAAU;IACrC,qEAAqE;IAC5C,WAAW,SAAM;IAC1C,WAAW,SAAK;IAChB,YAAY,SAAK;IACjB,UAAU,SAAM;IAChB,aAAa,SAAM;IACnB,UAAU,OAAc;gBACZ,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM;IAIlC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC;IAGvB,IAAI,CAAC,OAAO,CAAC,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC;CAqC9D;AACD,qBAAa,uBAAwB,SAAQ,cAAc,CAAC,aAAa,CAAC;IACxE,MAAM,CAAC,QAAQ,CAAC,UAAU,uBAAiB;CAC5C"}
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import type { DatabaseInterface } from '@happyvertical/sql';
|
|
2
|
+
import { type LearnerRequest, LearnerService } from './learner-service.js';
|
|
3
|
+
import { type TutorAudience, type TutorExchangeMarker, type TutorExchangeRole, type TutorSessionMode } from './tutor-contracts.js';
|
|
4
|
+
export type TutorExchangeView = Readonly<{
|
|
5
|
+
id: string;
|
|
6
|
+
sessionId: string;
|
|
7
|
+
sequence: number;
|
|
8
|
+
role: TutorExchangeRole;
|
|
9
|
+
text: string;
|
|
10
|
+
actorUserId: string;
|
|
11
|
+
lessonId: string | null;
|
|
12
|
+
questionRevisionId: string | null;
|
|
13
|
+
marker: TutorExchangeMarker;
|
|
14
|
+
toolSummary: string;
|
|
15
|
+
inputTokens: number;
|
|
16
|
+
outputTokens: number;
|
|
17
|
+
recordedAt: string;
|
|
18
|
+
}>;
|
|
19
|
+
export type TutorSessionView = Readonly<{
|
|
20
|
+
id: string;
|
|
21
|
+
learnerId: string;
|
|
22
|
+
enrollmentId: string | null;
|
|
23
|
+
lessonId: string | null;
|
|
24
|
+
audience: TutorAudience;
|
|
25
|
+
mode: TutorSessionMode;
|
|
26
|
+
voiceConsent: boolean;
|
|
27
|
+
openedByUserId: string;
|
|
28
|
+
/** Digest of the context the tutor was given; never the context itself. */
|
|
29
|
+
contextHash: string | null;
|
|
30
|
+
openedAt: string;
|
|
31
|
+
closedAt: string | null;
|
|
32
|
+
}>;
|
|
33
|
+
export type TutorSessionWithExchanges = TutorSessionView & Readonly<{
|
|
34
|
+
exchanges: ReadonlyArray<TutorExchangeView>;
|
|
35
|
+
/** True when more exchanges exist after the returned ones. */
|
|
36
|
+
exchangesTruncated: boolean;
|
|
37
|
+
}>;
|
|
38
|
+
export type OpenTutorSessionRequest = LearnerRequest & {
|
|
39
|
+
requestKey: string;
|
|
40
|
+
audience?: TutorAudience;
|
|
41
|
+
mode?: TutorSessionMode;
|
|
42
|
+
/** The host's recorded voice consent for this learner; required for voice. */
|
|
43
|
+
voiceConsent?: boolean;
|
|
44
|
+
enrollmentId?: string;
|
|
45
|
+
lessonId?: string;
|
|
46
|
+
/** `TutorContext.contextHash` of the context given to the tutor. */
|
|
47
|
+
contextHash?: string;
|
|
48
|
+
};
|
|
49
|
+
export type AppendTutorExchangeRequest = LearnerRequest & {
|
|
50
|
+
sessionId: string;
|
|
51
|
+
requestKey: string;
|
|
52
|
+
role: TutorExchangeRole;
|
|
53
|
+
text: string;
|
|
54
|
+
lessonId?: string;
|
|
55
|
+
questionRevisionId?: string;
|
|
56
|
+
marker?: TutorExchangeMarker;
|
|
57
|
+
toolSummary?: string;
|
|
58
|
+
inputTokens?: number;
|
|
59
|
+
outputTokens?: number;
|
|
60
|
+
};
|
|
61
|
+
export type ListTutorSessionsRequest = LearnerRequest & {
|
|
62
|
+
enrollmentId?: string;
|
|
63
|
+
lessonId?: string;
|
|
64
|
+
/** Restrict to one session and page its exchanges with `afterSequence`. */
|
|
65
|
+
sessionId?: string;
|
|
66
|
+
afterSequence?: number;
|
|
67
|
+
limit?: number;
|
|
68
|
+
cursor?: string;
|
|
69
|
+
exchangeLimit?: number;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Append-only tutor transcripts. No AI call happens here: the host owns the
|
|
73
|
+
* model call and the spend ceiling, and records what was said. Actions:
|
|
74
|
+
* `education.tutor.exchange` (open, append, close) and `education.tutor.read`
|
|
75
|
+
* (listForLearner), decided by the host authorizer with the same actor, tenant
|
|
76
|
+
* and guardian-relationship checks as `LearnerService`.
|
|
77
|
+
*/
|
|
78
|
+
export declare class TutorSessionService extends LearnerService {
|
|
79
|
+
protected createTransactionService(db: DatabaseInterface): this;
|
|
80
|
+
private requireTables;
|
|
81
|
+
private session;
|
|
82
|
+
private closure;
|
|
83
|
+
/** Opens a session; a replay of the same request key returns the same one. */
|
|
84
|
+
open(request: OpenTutorSessionRequest): Promise<TutorSessionView & {
|
|
85
|
+
changed: boolean;
|
|
86
|
+
}>;
|
|
87
|
+
/**
|
|
88
|
+
* Appends one exchange. `role: 'learner'` is accepted only from the learner
|
|
89
|
+
* themself; a guardian may append `tutor` or `system` rows. Text must be
|
|
90
|
+
* non-empty and at most `MAX_TUTOR_EXCHANGE_TEXT_CHARS`. A replay of a
|
|
91
|
+
* request key returns the stored row; an append to a closed session is
|
|
92
|
+
* refused with `TutorSessionClosedError`.
|
|
93
|
+
*/
|
|
94
|
+
append(request: AppendTutorExchangeRequest): Promise<TutorExchangeView & {
|
|
95
|
+
changed: boolean;
|
|
96
|
+
}>;
|
|
97
|
+
/** Closes a session by appending a closure; closing twice is a no-op. */
|
|
98
|
+
close(request: LearnerRequest & {
|
|
99
|
+
sessionId: string;
|
|
100
|
+
}): Promise<TutorSessionView & {
|
|
101
|
+
changed: boolean;
|
|
102
|
+
}>;
|
|
103
|
+
/**
|
|
104
|
+
* The learner's own sessions, newest first, with a bounded number of
|
|
105
|
+
* exchanges each (first by sequence). `limit` (default 20, max 50) and
|
|
106
|
+
* `cursor` page sessions; `exchangeLimit` (default 50, max 200) bounds
|
|
107
|
+
* exchanges, and `sessionId` + `afterSequence` page one session's exchanges.
|
|
108
|
+
* Guardians read through the host's `education.tutor.read` decision.
|
|
109
|
+
*/
|
|
110
|
+
listForLearner(request: ListTutorSessionsRequest): Promise<{
|
|
111
|
+
sessions: TutorSessionWithExchanges[];
|
|
112
|
+
nextCursor: string | null;
|
|
113
|
+
}>;
|
|
114
|
+
}
|
|
115
|
+
//# sourceMappingURL=tutor-session-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tutor-session-service.d.ts","sourceRoot":"","sources":["../src/tutor-session-service.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/smrt-education",
|
|
3
|
-
"version": "0.57.
|
|
3
|
+
"version": "0.57.49",
|
|
4
4
|
"smrtJsdoc": "strict",
|
|
5
5
|
"description": "Tenant-aware learning catalog models and authorized catalog access for SMRT",
|
|
6
6
|
"type": "module",
|
|
@@ -25,18 +25,18 @@
|
|
|
25
25
|
}
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"@happyvertical/smrt-assets": "0.57.
|
|
29
|
-
"@happyvertical/smrt-core": "0.57.
|
|
30
|
-
"@happyvertical/smrt-profiles": "0.57.
|
|
31
|
-
"@happyvertical/smrt-tenancy": "0.57.
|
|
32
|
-
"@happyvertical/smrt-users": "0.57.
|
|
28
|
+
"@happyvertical/smrt-assets": "0.57.49",
|
|
29
|
+
"@happyvertical/smrt-core": "0.57.49",
|
|
30
|
+
"@happyvertical/smrt-profiles": "0.57.49",
|
|
31
|
+
"@happyvertical/smrt-tenancy": "0.57.49",
|
|
32
|
+
"@happyvertical/smrt-users": "0.57.49",
|
|
33
33
|
"@happyvertical/files": "^0.111.3",
|
|
34
34
|
"@happyvertical/sql": "^0.111.3",
|
|
35
35
|
"pdf-lib": "1.17.1",
|
|
36
|
-
"@happyvertical/smrt-ingestion": "0.57.
|
|
36
|
+
"@happyvertical/smrt-ingestion": "0.57.49"
|
|
37
37
|
},
|
|
38
38
|
"devDependencies": {
|
|
39
|
-
"@happyvertical/smrt-vitest": "0.57.
|
|
39
|
+
"@happyvertical/smrt-vitest": "0.57.49",
|
|
40
40
|
"@types/node": "24.13.6",
|
|
41
41
|
"typescript": "6.0.3",
|
|
42
42
|
"vite": "8.1.6",
|