@goscribe/server 1.2.0 → 1.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.
- package/check-difficulty.cjs +14 -0
- package/check-questions.cjs +14 -0
- package/db-summary.cjs +22 -0
- package/dist/context.d.ts +5 -1
- package/dist/lib/activity_human_description.d.ts +13 -0
- package/dist/lib/activity_human_description.js +221 -0
- package/dist/lib/activity_human_description.test.d.ts +1 -0
- package/dist/lib/activity_human_description.test.js +16 -0
- package/dist/lib/activity_log_service.d.ts +87 -0
- package/dist/lib/activity_log_service.js +276 -0
- package/dist/lib/activity_log_service.test.d.ts +1 -0
- package/dist/lib/activity_log_service.test.js +27 -0
- package/dist/lib/ai-session.d.ts +15 -2
- package/dist/lib/ai-session.js +147 -85
- package/dist/lib/constants.d.ts +13 -0
- package/dist/lib/constants.js +12 -0
- package/dist/lib/email.d.ts +11 -0
- package/dist/lib/email.js +193 -0
- package/dist/lib/env.d.ts +13 -0
- package/dist/lib/env.js +16 -0
- package/dist/lib/inference.d.ts +4 -1
- package/dist/lib/inference.js +3 -3
- package/dist/lib/logger.d.ts +4 -4
- package/dist/lib/logger.js +30 -8
- package/dist/lib/notification-service.d.ts +152 -0
- package/dist/lib/notification-service.js +473 -0
- package/dist/lib/notification-service.test.d.ts +1 -0
- package/dist/lib/notification-service.test.js +87 -0
- package/dist/lib/prisma.d.ts +2 -1
- package/dist/lib/prisma.js +5 -1
- package/dist/lib/pusher.d.ts +23 -0
- package/dist/lib/pusher.js +69 -5
- package/dist/lib/retry.d.ts +15 -0
- package/dist/lib/retry.js +37 -0
- package/dist/lib/storage.js +2 -2
- package/dist/lib/stripe.d.ts +9 -0
- package/dist/lib/stripe.js +36 -0
- package/dist/lib/subscription_service.d.ts +37 -0
- package/dist/lib/subscription_service.js +654 -0
- package/dist/lib/usage_service.d.ts +26 -0
- package/dist/lib/usage_service.js +59 -0
- package/dist/lib/worksheet-generation.d.ts +91 -0
- package/dist/lib/worksheet-generation.js +95 -0
- package/dist/lib/worksheet-generation.test.d.ts +1 -0
- package/dist/lib/worksheet-generation.test.js +20 -0
- package/dist/lib/workspace-access.d.ts +18 -0
- package/dist/lib/workspace-access.js +13 -0
- package/dist/routers/_app.d.ts +1349 -253
- package/dist/routers/_app.js +10 -0
- package/dist/routers/admin.d.ts +361 -0
- package/dist/routers/admin.js +633 -0
- package/dist/routers/annotations.d.ts +219 -0
- package/dist/routers/annotations.js +187 -0
- package/dist/routers/auth.d.ts +88 -7
- package/dist/routers/auth.js +339 -19
- package/dist/routers/chat.d.ts +6 -12
- package/dist/routers/copilot.d.ts +199 -0
- package/dist/routers/copilot.js +571 -0
- package/dist/routers/flashcards.d.ts +47 -81
- package/dist/routers/flashcards.js +143 -27
- package/dist/routers/members.d.ts +36 -7
- package/dist/routers/members.js +200 -19
- package/dist/routers/notifications.d.ts +99 -0
- package/dist/routers/notifications.js +127 -0
- package/dist/routers/payment.d.ts +89 -0
- package/dist/routers/payment.js +403 -0
- package/dist/routers/podcast.d.ts +8 -13
- package/dist/routers/podcast.js +54 -31
- package/dist/routers/studyguide.d.ts +1 -29
- package/dist/routers/studyguide.js +80 -71
- package/dist/routers/worksheets.d.ts +105 -38
- package/dist/routers/worksheets.js +258 -68
- package/dist/routers/workspace.d.ts +139 -60
- package/dist/routers/workspace.js +455 -315
- package/dist/scripts/purge-deleted-users.d.ts +1 -0
- package/dist/scripts/purge-deleted-users.js +149 -0
- package/dist/server.js +130 -10
- package/dist/services/flashcard-progress.service.d.ts +18 -66
- package/dist/services/flashcard-progress.service.js +51 -42
- package/dist/trpc.d.ts +20 -21
- package/dist/trpc.js +150 -1
- package/mcq-test.cjs +36 -0
- package/package.json +9 -2
- package/prisma/migrations/20260413143206_init/migration.sql +873 -0
- package/prisma/schema.prisma +471 -324
- package/src/context.ts +4 -1
- package/src/lib/activity_human_description.test.ts +28 -0
- package/src/lib/activity_human_description.ts +239 -0
- package/src/lib/activity_log_service.test.ts +37 -0
- package/src/lib/activity_log_service.ts +353 -0
- package/src/lib/ai-session.ts +79 -51
- package/src/lib/email.ts +213 -29
- package/src/lib/env.ts +23 -6
- package/src/lib/inference.ts +2 -2
- package/src/lib/notification-service.test.ts +106 -0
- package/src/lib/notification-service.ts +677 -0
- package/src/lib/prisma.ts +6 -1
- package/src/lib/pusher.ts +86 -2
- package/src/lib/stripe.ts +39 -0
- package/src/lib/subscription_service.ts +722 -0
- package/src/lib/usage_service.ts +74 -0
- package/src/lib/worksheet-generation.test.ts +31 -0
- package/src/lib/worksheet-generation.ts +139 -0
- package/src/routers/_app.ts +9 -0
- package/src/routers/admin.ts +710 -0
- package/src/routers/annotations.ts +41 -0
- package/src/routers/auth.ts +338 -28
- package/src/routers/copilot.ts +719 -0
- package/src/routers/flashcards.ts +201 -68
- package/src/routers/members.ts +280 -80
- package/src/routers/notifications.ts +142 -0
- package/src/routers/payment.ts +448 -0
- package/src/routers/podcast.ts +112 -83
- package/src/routers/studyguide.ts +12 -0
- package/src/routers/worksheets.ts +289 -66
- package/src/routers/workspace.ts +329 -122
- package/src/scripts/purge-deleted-users.ts +167 -0
- package/src/server.ts +137 -11
- package/src/services/flashcard-progress.service.ts +49 -37
- package/src/trpc.ts +184 -5
- package/test-generate.js +30 -0
- package/test-ratio.cjs +9 -0
- package/zod-test.cjs +22 -0
- package/prisma/migrations/20250826124819_add_worksheet_difficulty_and_estimated_time/migration.sql +0 -213
- package/prisma/migrations/20250826133236_add_worksheet_question_progress/migration.sql +0 -31
- package/prisma/seed.mjs +0 -135
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
import { ActivityLogCategory } from "@prisma/client";
|
|
2
|
+
import { logger } from "./logger.js";
|
|
3
|
+
import { getTrpcPathsMatchingDescriptionSearch } from "./activity_human_description.js";
|
|
4
|
+
const SENSITIVE_KEY_FRAGMENTS = [
|
|
5
|
+
"password",
|
|
6
|
+
"token",
|
|
7
|
+
"secret",
|
|
8
|
+
"authorization",
|
|
9
|
+
"cookie",
|
|
10
|
+
"credit",
|
|
11
|
+
"card",
|
|
12
|
+
"cvv",
|
|
13
|
+
"ssn",
|
|
14
|
+
];
|
|
15
|
+
export function isActivityLogEnabled() {
|
|
16
|
+
const v = process.env.ACTIVITY_LOG_ENABLED;
|
|
17
|
+
if (v === undefined || v === "")
|
|
18
|
+
return true;
|
|
19
|
+
return v === "1" || v.toLowerCase() === "true";
|
|
20
|
+
}
|
|
21
|
+
function activitySampleRate() {
|
|
22
|
+
const raw = process.env.ACTIVITY_LOG_SAMPLE_RATE;
|
|
23
|
+
if (!raw)
|
|
24
|
+
return 1;
|
|
25
|
+
const n = Number(raw);
|
|
26
|
+
if (!Number.isFinite(n) || n <= 0)
|
|
27
|
+
return 0;
|
|
28
|
+
if (n > 1)
|
|
29
|
+
return 1;
|
|
30
|
+
return n;
|
|
31
|
+
}
|
|
32
|
+
export function shouldSampleActivity() {
|
|
33
|
+
const rate = activitySampleRate();
|
|
34
|
+
if (rate >= 1)
|
|
35
|
+
return true;
|
|
36
|
+
if (rate <= 0)
|
|
37
|
+
return false;
|
|
38
|
+
return Math.random() < rate;
|
|
39
|
+
}
|
|
40
|
+
/** Recursive redaction for JSON-safe metadata (never log raw credentials). */
|
|
41
|
+
export function redactSensitive(value) {
|
|
42
|
+
if (value === null || value === undefined)
|
|
43
|
+
return value;
|
|
44
|
+
if (typeof value === "string") {
|
|
45
|
+
if (value.length > 2000)
|
|
46
|
+
return `${value.slice(0, 2000)}…[truncated]`;
|
|
47
|
+
return value;
|
|
48
|
+
}
|
|
49
|
+
if (typeof value !== "object")
|
|
50
|
+
return value;
|
|
51
|
+
if (Array.isArray(value)) {
|
|
52
|
+
return value.map((v) => redactSensitive(v));
|
|
53
|
+
}
|
|
54
|
+
const out = {};
|
|
55
|
+
for (const [k, v] of Object.entries(value)) {
|
|
56
|
+
const lower = k.toLowerCase();
|
|
57
|
+
if (SENSITIVE_KEY_FRAGMENTS.some((f) => lower.includes(f))) {
|
|
58
|
+
out[k] = "[REDACTED]";
|
|
59
|
+
continue;
|
|
60
|
+
}
|
|
61
|
+
out[k] = redactSensitive(v);
|
|
62
|
+
}
|
|
63
|
+
return out;
|
|
64
|
+
}
|
|
65
|
+
export function inferCategoryFromTrpcPath(path) {
|
|
66
|
+
const p = path.toLowerCase();
|
|
67
|
+
if (p.startsWith("auth."))
|
|
68
|
+
return ActivityLogCategory.AUTH;
|
|
69
|
+
if (p.startsWith("payment."))
|
|
70
|
+
return ActivityLogCategory.BILLING;
|
|
71
|
+
if (p.startsWith("admin."))
|
|
72
|
+
return ActivityLogCategory.ADMIN;
|
|
73
|
+
if (p.startsWith("workspace.") || p.startsWith("members.") || p.startsWith("member."))
|
|
74
|
+
return ActivityLogCategory.WORKSPACE;
|
|
75
|
+
if (p.startsWith("flashcards.") ||
|
|
76
|
+
p.startsWith("worksheets.") ||
|
|
77
|
+
p.startsWith("studyguide.") ||
|
|
78
|
+
p.startsWith("podcast.") ||
|
|
79
|
+
p.startsWith("annotations.") ||
|
|
80
|
+
p.startsWith("chat.") ||
|
|
81
|
+
p.startsWith("copilot."))
|
|
82
|
+
return ActivityLogCategory.CONTENT;
|
|
83
|
+
if (p.startsWith("notifications."))
|
|
84
|
+
return ActivityLogCategory.SYSTEM;
|
|
85
|
+
return ActivityLogCategory.SYSTEM;
|
|
86
|
+
}
|
|
87
|
+
/** Best-effort workspace id from tRPC input (nested objects included). */
|
|
88
|
+
export function extractWorkspaceIdFromInput(raw) {
|
|
89
|
+
if (raw === null || raw === undefined)
|
|
90
|
+
return undefined;
|
|
91
|
+
if (typeof raw === "object" && !Array.isArray(raw)) {
|
|
92
|
+
const o = raw;
|
|
93
|
+
const direct = o.workspaceId ?? o.workspace_id;
|
|
94
|
+
if (typeof direct === "string" && direct.length > 0)
|
|
95
|
+
return direct;
|
|
96
|
+
for (const v of Object.values(o)) {
|
|
97
|
+
const nested = extractWorkspaceIdFromInput(v);
|
|
98
|
+
if (nested)
|
|
99
|
+
return nested;
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (Array.isArray(raw)) {
|
|
103
|
+
for (const item of raw) {
|
|
104
|
+
const nested = extractWorkspaceIdFromInput(item);
|
|
105
|
+
if (nested)
|
|
106
|
+
return nested;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
return undefined;
|
|
110
|
+
}
|
|
111
|
+
export function truncateUserAgent(ua, max = 512) {
|
|
112
|
+
if (!ua)
|
|
113
|
+
return undefined;
|
|
114
|
+
return ua.length > max ? ua.slice(0, max) : ua;
|
|
115
|
+
}
|
|
116
|
+
export function getClientIp(req) {
|
|
117
|
+
const xf = req.headers["x-forwarded-for"];
|
|
118
|
+
if (typeof xf === "string")
|
|
119
|
+
return xf.split(",")[0]?.trim();
|
|
120
|
+
if (Array.isArray(xf))
|
|
121
|
+
return xf[0]?.split(",")[0]?.trim();
|
|
122
|
+
const ra = req.socket?.remoteAddress;
|
|
123
|
+
return ra ?? undefined;
|
|
124
|
+
}
|
|
125
|
+
function buildMetadata(path, rawInput) {
|
|
126
|
+
if (rawInput === undefined)
|
|
127
|
+
return undefined;
|
|
128
|
+
try {
|
|
129
|
+
const redacted = redactSensitive(rawInput);
|
|
130
|
+
return { trpcInputPreview: redacted };
|
|
131
|
+
}
|
|
132
|
+
catch {
|
|
133
|
+
return { trpcInputPreview: "[unserializable]" };
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
function buildExplicitMetadata(metadata) {
|
|
137
|
+
if (metadata === undefined)
|
|
138
|
+
return undefined;
|
|
139
|
+
try {
|
|
140
|
+
return redactSensitive(metadata);
|
|
141
|
+
}
|
|
142
|
+
catch {
|
|
143
|
+
return { metadata: "[unserializable]" };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Persists one activity row. Prefer `scheduleRecordActivity` from request path to avoid blocking.
|
|
148
|
+
*/
|
|
149
|
+
export async function recordActivity(input) {
|
|
150
|
+
if (!isActivityLogEnabled())
|
|
151
|
+
return;
|
|
152
|
+
if (!shouldSampleActivity())
|
|
153
|
+
return;
|
|
154
|
+
const category = inferCategoryFromTrpcPath(input.path);
|
|
155
|
+
const workspaceId = extractWorkspaceIdFromInput(input.rawInput) ?? undefined;
|
|
156
|
+
const action = `trpc.${input.path}`;
|
|
157
|
+
const metadata = buildMetadata(input.path, input.rawInput);
|
|
158
|
+
try {
|
|
159
|
+
await input.db.activityLog.create({
|
|
160
|
+
data: {
|
|
161
|
+
actorUserId: input.actorUserId,
|
|
162
|
+
actorEmailSnapshot: input.actorEmailSnapshot ?? undefined,
|
|
163
|
+
action,
|
|
164
|
+
category,
|
|
165
|
+
trpcPath: input.path,
|
|
166
|
+
httpMethod: input.httpMethod ?? undefined,
|
|
167
|
+
status: input.status,
|
|
168
|
+
errorCode: input.errorCode ?? undefined,
|
|
169
|
+
durationMs: input.durationMs,
|
|
170
|
+
workspaceId,
|
|
171
|
+
ipAddress: input.ipAddress ?? undefined,
|
|
172
|
+
userAgent: truncateUserAgent(input.userAgent ?? undefined),
|
|
173
|
+
metadata: metadata ?? undefined,
|
|
174
|
+
},
|
|
175
|
+
});
|
|
176
|
+
}
|
|
177
|
+
catch (e) {
|
|
178
|
+
logger.error(`ActivityLog write failed: ${e instanceof Error ? e.message : String(e)}`, "ACTIVITY");
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
export function scheduleRecordActivity(input) {
|
|
182
|
+
void Promise.resolve()
|
|
183
|
+
.then(() => recordActivity(input))
|
|
184
|
+
.catch((e) => logger.error(`ActivityLog async error: ${e instanceof Error ? e.message : String(e)}`, "ACTIVITY"));
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Persists one explicit (non-tRPC) activity row.
|
|
188
|
+
* This is used for cron jobs, webhooks, and other system-wide background operations.
|
|
189
|
+
*/
|
|
190
|
+
export async function recordExplicitActivity(input) {
|
|
191
|
+
if (!isActivityLogEnabled())
|
|
192
|
+
return;
|
|
193
|
+
if (!input.forceWrite && !shouldSampleActivity())
|
|
194
|
+
return;
|
|
195
|
+
const metadata = buildExplicitMetadata(input.metadata);
|
|
196
|
+
try {
|
|
197
|
+
await input.db.activityLog.create({
|
|
198
|
+
data: {
|
|
199
|
+
actorUserId: input.actorUserId ?? undefined,
|
|
200
|
+
actorEmailSnapshot: input.actorEmailSnapshot ?? undefined,
|
|
201
|
+
action: input.action,
|
|
202
|
+
category: input.category,
|
|
203
|
+
resourceType: input.resourceType ?? undefined,
|
|
204
|
+
resourceId: input.resourceId ?? undefined,
|
|
205
|
+
workspaceId: input.workspaceId ?? undefined,
|
|
206
|
+
trpcPath: input.trpcPath ?? undefined,
|
|
207
|
+
httpMethod: input.httpMethod ?? undefined,
|
|
208
|
+
status: input.status,
|
|
209
|
+
errorCode: input.errorCode ?? undefined,
|
|
210
|
+
durationMs: input.durationMs,
|
|
211
|
+
ipAddress: input.ipAddress ?? undefined,
|
|
212
|
+
userAgent: truncateUserAgent(input.userAgent ?? undefined),
|
|
213
|
+
metadata: metadata ?? undefined,
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
catch (e) {
|
|
218
|
+
logger.error(`ActivityLog explicit write failed: ${e instanceof Error ? e.message : String(e)}`, "ACTIVITY");
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
export function scheduleRecordExplicitActivity(input) {
|
|
222
|
+
void Promise.resolve()
|
|
223
|
+
.then(() => recordExplicitActivity(input))
|
|
224
|
+
.catch((e) => logger.error(`ActivityLog explicit async error: ${e instanceof Error ? e.message : String(e)}`, "ACTIVITY"));
|
|
225
|
+
}
|
|
226
|
+
/** Default retention: 365 days. Override with ACTIVITY_LOG_RETENTION_DAYS. */
|
|
227
|
+
export function getActivityRetentionDays() {
|
|
228
|
+
const raw = process.env.ACTIVITY_LOG_RETENTION_DAYS;
|
|
229
|
+
if (!raw)
|
|
230
|
+
return 365;
|
|
231
|
+
const n = Number(raw);
|
|
232
|
+
if (!Number.isFinite(n) || n < 1)
|
|
233
|
+
return 365;
|
|
234
|
+
return Math.min(Math.floor(n), 3650);
|
|
235
|
+
}
|
|
236
|
+
export async function deleteActivityLogsOlderThan(db, cutoff) {
|
|
237
|
+
const result = await db.activityLog.deleteMany({
|
|
238
|
+
where: { createdAt: { lt: cutoff } },
|
|
239
|
+
});
|
|
240
|
+
return { deleted: result.count };
|
|
241
|
+
}
|
|
242
|
+
export function buildActivityLogWhere(filter, options) {
|
|
243
|
+
const where = {};
|
|
244
|
+
if (options?.forceActorUserId) {
|
|
245
|
+
where.actorUserId = options.forceActorUserId;
|
|
246
|
+
}
|
|
247
|
+
else if (filter.actorUserId) {
|
|
248
|
+
where.actorUserId = filter.actorUserId;
|
|
249
|
+
}
|
|
250
|
+
if (filter.workspaceId)
|
|
251
|
+
where.workspaceId = filter.workspaceId;
|
|
252
|
+
if (filter.category)
|
|
253
|
+
where.category = filter.category;
|
|
254
|
+
if (filter.status)
|
|
255
|
+
where.status = filter.status;
|
|
256
|
+
if (filter.from || filter.to) {
|
|
257
|
+
where.createdAt = {};
|
|
258
|
+
if (filter.from)
|
|
259
|
+
where.createdAt.gte = filter.from;
|
|
260
|
+
if (filter.to)
|
|
261
|
+
where.createdAt.lte = filter.to;
|
|
262
|
+
}
|
|
263
|
+
if (filter.search?.trim()) {
|
|
264
|
+
const s = filter.search.trim();
|
|
265
|
+
const pathsFromDescription = getTrpcPathsMatchingDescriptionSearch(s);
|
|
266
|
+
where.OR = [
|
|
267
|
+
{ action: { contains: s, mode: "insensitive" } },
|
|
268
|
+
{ trpcPath: { contains: s, mode: "insensitive" } },
|
|
269
|
+
{ errorCode: { contains: s, mode: "insensitive" } },
|
|
270
|
+
...(pathsFromDescription.length > 0
|
|
271
|
+
? [{ trpcPath: { in: pathsFromDescription } }]
|
|
272
|
+
: []),
|
|
273
|
+
];
|
|
274
|
+
}
|
|
275
|
+
return where;
|
|
276
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { test } from "node:test";
|
|
2
|
+
import assert from "node:assert/strict";
|
|
3
|
+
import { ActivityLogCategory, ActivityLogStatus } from "@prisma/client";
|
|
4
|
+
import { buildActivityLogWhere, inferCategoryFromTrpcPath, redactSensitive, } from "./activity_log_service.js";
|
|
5
|
+
test("redactSensitive redacts sensitive keys", () => {
|
|
6
|
+
const out = redactSensitive({
|
|
7
|
+
email: "a@b.com",
|
|
8
|
+
password: "secret",
|
|
9
|
+
nested: { authToken: "t", safe: 1 },
|
|
10
|
+
});
|
|
11
|
+
assert.equal(out.password, "[REDACTED]");
|
|
12
|
+
const nested = out.nested;
|
|
13
|
+
assert.equal(nested.authToken, "[REDACTED]");
|
|
14
|
+
assert.equal(nested.safe, 1);
|
|
15
|
+
});
|
|
16
|
+
test("inferCategoryFromTrpcPath maps routers", () => {
|
|
17
|
+
assert.equal(inferCategoryFromTrpcPath("auth.login"), ActivityLogCategory.AUTH);
|
|
18
|
+
assert.equal(inferCategoryFromTrpcPath("payment.checkout"), ActivityLogCategory.BILLING);
|
|
19
|
+
assert.equal(inferCategoryFromTrpcPath("admin.listUsers"), ActivityLogCategory.ADMIN);
|
|
20
|
+
assert.equal(inferCategoryFromTrpcPath("workspace.list"), ActivityLogCategory.WORKSPACE);
|
|
21
|
+
assert.equal(inferCategoryFromTrpcPath("flashcards.list"), ActivityLogCategory.CONTENT);
|
|
22
|
+
});
|
|
23
|
+
test("buildActivityLogWhere forces actor for user scope", () => {
|
|
24
|
+
const w = buildActivityLogWhere({ status: ActivityLogStatus.SUCCESS }, { forceActorUserId: "user-1" });
|
|
25
|
+
assert.equal(w.actorUserId, "user-1");
|
|
26
|
+
assert.equal(w.status, ActivityLogStatus.SUCCESS);
|
|
27
|
+
});
|
package/dist/lib/ai-session.d.ts
CHANGED
|
@@ -25,8 +25,13 @@ export declare class AISessionService {
|
|
|
25
25
|
initSession(workspaceId: string, user: string): Promise<AISession>;
|
|
26
26
|
processFile(sessionId: string, user: string, fileUrl: string, fileType: 'image' | 'pdf', maxPages?: number): Promise<ProcessFileResult>;
|
|
27
27
|
generateStudyGuide(sessionId: string, user: string): Promise<string>;
|
|
28
|
-
generateFlashcardQuestions(sessionId: string, user: string, numQuestions: number, difficulty: 'easy' | 'medium' | 'hard'): Promise<string>;
|
|
29
|
-
generateWorksheetQuestions(sessionId: string, user: string, numQuestions: number, difficulty: 'EASY' | 'MEDIUM' | 'HARD'
|
|
28
|
+
generateFlashcardQuestions(sessionId: string, user: string, numQuestions: number, difficulty: 'easy' | 'medium' | 'hard', prompt?: string): Promise<string>;
|
|
29
|
+
generateWorksheetQuestions(sessionId: string, user: string, numQuestions: number, difficulty: 'EASY' | 'MEDIUM' | 'HARD', options?: {
|
|
30
|
+
mode?: 'practice' | 'quiz';
|
|
31
|
+
mcqRatio?: number;
|
|
32
|
+
questionTypes?: string[];
|
|
33
|
+
prompt?: string;
|
|
34
|
+
}): Promise<string>;
|
|
30
35
|
checkWorksheetQuestions(sessionId: string, user: string, question: string, answer: string, mark_scheme: MarkScheme): Promise<UserMarkScheme>;
|
|
31
36
|
generatePodcastStructure(sessionId: string, user: string, title: string, description: string, prompt: string, speakers: Array<{
|
|
32
37
|
id: string;
|
|
@@ -39,6 +44,14 @@ export declare class AISessionService {
|
|
|
39
44
|
name?: string;
|
|
40
45
|
}>, voiceId?: string): Promise<any>;
|
|
41
46
|
generatePodcastImage(sessionId: string, user: string, summary: string): Promise<string>;
|
|
47
|
+
segmentStudyGuide(sessionId: string, user: string, studyGuide: string): Promise<{
|
|
48
|
+
hint: string;
|
|
49
|
+
content: string;
|
|
50
|
+
}[]>;
|
|
51
|
+
validateSegmentSummary(sessionId: string, user: string, segmentContent: string, studentResponse: string, studyGuide: string): Promise<{
|
|
52
|
+
valid: boolean;
|
|
53
|
+
feedback: string;
|
|
54
|
+
}>;
|
|
42
55
|
getSession(sessionId: string): AISession | undefined;
|
|
43
56
|
getSessionsByUserAndWorkspace(userId: string, workspaceId: string): AISession[];
|
|
44
57
|
deleteSession(sessionId: string): boolean;
|